Uploader
‹ BackExample uploader
Here is an example uploader in demo mode. It will simulate an upload but won't actually save anywhere.
This is a hint message for the image uploader
<%= render "form_field_uploader", { f: f, attr: :banner_image } -%>
By default the uploader assumes a 1:1 aspect ratio for your image, however you can change this by passing in ratio:
.
This is a hint message for the image uploader
<%= render "form_field_uploader", { f: f, attr: :banner_image, ratio: "2/1" } -%>
Cropping
You can add the crop tool by simply adding croppable: "true"
to your partial include:
This is a hint message for the image uploader
<%= render "form_field_uploader", { f: f, attr: :banner_image, croppable: "true" } -%>
Aspect ratio changes can be set alongside croppability:
This is a hint message for the image uploader
<%= render "form_field_uploader", { f: f, attr: :banner_image, ratio: "2/1", croppable: "true" } -%>
This is a hint message for the image uploader
<%= render "form_field_uploader", { f: f, attr: :banner_image, ratio: "1/2", croppable: "true" } -%>
Existing images
The uploader supports existing images by showing the thumbnail (and crop if available) with no extra logic needed in your markup. Simply include the partial as normal and if an image already exists it will show it.
This is a hint message for the image uploader

<%= render "form_field_uploader", { f: f, attr: :banner_image, croppable: true } -%>
Document Uploads
The uploader will switch to "file" mode (rather than image mode) if the file types include "pdf", "xls", "xlsx", "doc", "docx".
These requirements can be updated in the form_field_uploader
partial.
This is a hint message for the image uploader
<%= render "form_field_uploader", { f: f, attr: :banner_image, types: "pdf, xls, xlsx, doc, docx"} -%>
Behind the scenes
There are two hidden fields (exposed here) that track the asset ID when the image is uploaded and the crop string if croppable.
The image id is emptied when the image is removed.
The crop string only saves when a crop is made. The crop string is emptied when the image is removed.
You can see the fields updating here as you add, remove and crop images.
This is a hint message for the image uploader
Events and callbacks
Change the state of the uploader by triggering uploader:set-state:[state]
eg. $(".my-uploader").trigger("uploader:set-state:saving");
The available states are:
- Idle (no image)
- Uploading
- Saving
- Uploaded
- Error
Note: setting states does not destroy data. If you change the state from uploaded to idle, the image and fields will still be filled in. This is purely presentational.
There are several events that fire at certain times during the upload process that you can hook in to by adding on()
event handlers to your field. For example:
$(".my-field").on("uploader:after-upload", function(e,$uploader,$dropZone,$cropStringField,$hiddenField){ alert("uploaded!") }
The list of events are:
- on("uploader:init", function() {})
- on("uploader:after-upload", function(e,$uploader,$dropZone,$cropStringField,$hiddenField) {})
- on("uploader:image-removed", function() {})
- on("uploader:progress-bar-updated", function() {})
- on("uploader:state-changed", function(event,state) {})
- on("uploader:crop-set", function(event,cropValue,$cropField) {})
- on("uploader:upload-cancelled", function() {})
There are also some action events you can trigger on the field:
- uploader:update-thumbnail
- uploader:close-crop-modal
This is a hint message for the image uploader
<div data-uploader-callbacks> <%= render "form_field_uploader", { f: f, attr: :banner_image } -%> <pre data-uploader-tracker></pre> </div>
<script> Ornament.onLoad(function(){ if(typeof $ === "undefined") { return; } var $callbacksContainer = $("[data-uploader-callbacks]"); var $callbackUploader = $callbacksContainer.find("[data-file-uploader]"); var $callbackTracker = $callbacksContainer.find("[data-uploader-tracker]"); $callbackUploader.on("uploader:init", function(){ $callbackTracker.append("Uploader initialised<br />"); }).on("uploader:after-upload", function(e, $uploader, $dropZone, $cropStringField, $hiddenField) { $callbackTracker.append("Upload successful" + "<br />"); }).on("uploader:image-removed", function(e) { $callbackTracker.append("Image was removed" + "<br />"); }).on("uploader:progress-bar-updated", function(e, value) { $callbackTracker.append("Progress was changed to " + value + "<br />"); }).on("uploader:state-changed", function(e, state) { $callbackTracker.append("State was changed to: " + state + "<br />"); }).on("uploader:crop-set", function(e, cropValue, $cropField) { $callbackTracker.append("Crop set to: " + cropValue + "<br />"); }).on("uploader:modal-opened", function(e){ $callbackTracker.append("Crop modal opened<br />"); }).on("uploader:upload-cancelled", function(e){ $callbackTracker.append("Upload was cancelled<br />"); }); }); </script>
Setting up your model
All uploads are passed through to the Asset
model so instead of storing the image as a dragonfly object aginst the model, all you store is an integer field for the asset id.
Assuming you want to create an uploader for "banner image", you'll need a migration to add banner_image_id:integer
to your model:
rails generate migration AddBannerImageIdToModel banner_image_id:integer
If you want to be able to crop your banner image, you'll also need a crop_string, in which case you would change your migration to add a second field as well:
rails generate migration AddBannerImageToModel banner_image_id:integer banner_image_crop:string
Then in your form you want to render the uploader partial:
<%= render "form_field_uploader", { f: f, attr: :cover_image } -%>
If you want to enable cropping for the field, simply add a ratio value to the crop_ratio attribute:
<%= render "form_field_uploader", { f: f, attr: :cover_image, crop_ratio: "1/1" } -%>
Open up your model and add some basic helper functions for the view.
def banner_image_asset Asset.find(banner_image_id).data end def banner_image if banner_image_crop.blank? banner_image_asset else banner_image_asset.thumb(banner_image_crop) end end
This will set up a banner_image
method that will look to see if there's a crop available, if not it just uses the original image that was uploaded.
Now in your view you can simply call <%= @my_model.banner_image.url -%>
to get the cropped version of the image.