I've been using Formtastic for awhile now, and it's great for speeding up implementation of forms. However, I have a special case where I need some more customization in what's displayed in my form. Specifically, the field is a file upload form for uploading images, and on the edit form, I want to show a thumbnail of the current version of the image that has been uploaded.
I've got this working, but it required that I use custom HTML markup, which means that any time Formtastic changes the output format, I need to update my matching HTML. Here's what I've got right now:
<%= form.inputs do %>
<% if form.object.new_record? -%>
<%= form.input :image, :required => true, :hint => 'Maximum size of 3MB. JPG, GIF, PNG.' %>
<% else -%>
<li class="file input required" id="profile_image_input">
<label class="label" for="profile_image">Image</label>
<%= image_tag form.object.image.url(:thumb), :class => 'attachment' %>
<%= form.file_field :image %>
<p class="inline-hints">Maximum size of 3MB. JPG, GIF, PNG.</p>
</li>
<% end -%>
<% end %>
Ideally, it would be nice to do something more like the following, where input_html
is assumed to be the generated HTML for the input, hint, etc.:
<%= form.inputs do %>
<%= form.input :image, :required => true, :hint => 'Maximum size of 3MB. JPG, GIF, PNG.' do |input_html| %>
<%= image_tag form.object.image.url(:thumb), :class => 'attachment' unless form.object.new_record? %>
<%= input_html %>
<% end %>
<% end %>
Does anything like this already exist? Or is there another similar option that will make my life easier?
Well, I solved this myself of course. As always happens when I post here. :P
For anyone looking to do something similar, I created a custom input type derived from Formtastic's file input.
class AttachmentInput < Formtastic::Inputs::FileInput
def image_html_options
{:class => 'attachment'}.merge(options[:image_html] || {})
end
def to_html
input_wrapping do
label_html <<
image_html <<
builder.file_field(method, input_html_options)
end
end
protected
def image_html
return "".html_safe if builder.object.new_record?
url = case options[:image]
when Symbol
builder.object.send(options[:image])
when Proc
options[:image].call(builder.object)
else
options[:image].to_s
end
builder.template.image_tag(url, image_html_options).html_safe
end
end
Now I can just create an input of this type in the following manner:
<%= form.input :image, :as => :attachment,
:required => true,
:hint => 'Maximum size of 3MB. JPG, GIF, PNG.',
:image => proc { |o| o.image.url(:thumb) } %>
Optionally, the :image
tag can accept one of:
Additionally, I can utilize the :image_html
option for specifying HTML classes, id's, etc.
At the bottom of the Formtastic docs at https://github.com/justinfrench/formtastic#modified--custom-inputs:
Create a file in app/inputs with a filename ending in _input.rb
Not enough for a full solution, but after rooting through the formtastic source for inspiration was able to come up with the following which is working well for me.
in app/inputs/label_input.rb:
class LabelInput
include Formtastic::Inputs::Base
def to_html
input_wrapping do
label_html <<
"#{@object.send(method)}"
end
end
end
happen to be using ActiveAdmin, in form on page:
form do |f|
f.inputs do
f.input :project
f.input :date_consumed
f.input :total_consumed
f.input :computed_waste, :as => :label
f.actions
end
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With