I'm trying to use the input-append feature of Twitter Bootstrap. However, I want to try and keep my code cleaner with the simple_form.
<div class="control-group string required">
<label class="string required control-label" for="video_company_id"><abbr title="required">*</abbr> Company</label>
<div class="controls">
<div class="input-append">
<%= f.text_field :company_id, :class => "span2" %>
<span class="add-on"><%= link_to image_tag('/assets/button/magnifier.png'), "#select_company", :"data-toggle" => "modal" %></span>
</div>
</div>
</div>
yields
What is a better way to write this with simple_form using f.input?
Edit to mdepolli
Thanks mdepolli. That does get me closer to where I need to be. However, it just puts the lookup inline with the form instead of an 'add-on'.
<%= f.input :company_id, :as => :string, :class => "span2", :wrapper_html => { :class => "input-append"} %>
<%= link_to image_tag('/assets/button/magnifier.png'), "#select_company", :"data-toggle" => "modal", :class => "add-on", :wrapper_html => { :class => "input-append"} %>
edit again
with the content_tag, it takes it to the separate line
First off, let's create a custom wrapper in the SimpleForm initializer.
In config/initializers/simple_form.rb:
config.wrappers :append, :tag => 'div', :class => "control-group", :error_class => 'error' do |b|
b.use :html5
b.use :placeholder
b.use :label
b.wrapper :tag => 'div', :class => 'controls' do |input|
input.wrapper :tag => 'div', :class => 'input-append' do |append|
append.use :input
end
input.use :hint, :wrap_with => { :tag => 'span', :class => 'help-block' }
input.use :error, :wrap_with => { :tag => 'span', :class => 'help-inline' }
end
end
Now let's go back to your form.
Be sure to replace #model with the actual instance variable attached to the ActiveRecord model you're using.
<%= simple_form_for #model do |f| %>
<%= f.input :company_id, :wrapper => :append do %>
<%= f.input_field :company_id %>
<%= content_tag :span, link_to(image_tag('/assets/button/magnifier.png'), "#select_company", :"data-toggle" => "modal"), :class => 'add-on' %>
<% end %>
<%= f.button :submit %>
<% end %>
Edit: Sorry it took me a bit, ended up having to make a custom wrapper in the end.
Related
I am looking for a more elegant way to accomplish this.
<div class="control-group">
<%= f.label :shoot_date, class: "control-label" %>
<div class="controls">
<% if #shoot.new_record? %>
<%= f.text_field :shoot_date, :class => 'datepicker', :value => Date.today.strftime('%m/%d/%Y'), 'data-behavior' => 'datepicker', :readonly => true %>
<% else %>
<%= f.text_field :shoot_date, :class => 'datepicker', :value => #shoot.shoot_date.strftime('%m/%d/%Y'), 'data-behavior' => 'datepicker', :readonly => true %>
<% end %>
<span class="help-block">Sitting date of this shoot.
</div>
Yeah, just throw it in the controller:
def new
shoot.shoot_date = Date.today
end
You shouldn't have to put it in the edit method or anything; that should happen automatically. You could even put it in the model if you like, but the controller works well.
I have the following model relationships:
OrderModel:
has_one :credit_card
accepts_nested_attributes_for :credit_card
attr_accessible :user_id, :date_updated, :date_finished, :amount, :payment_method, :status, :billing_cycle, :auth_net_subscription_id, :billing_start_date, :credit_card_attributes, :billing_address_id, :cc_id
CreditCardModel:
belongs_to :order
Here is my Order Controller (orders#checkout)
def checkout
#order = current_order
#cc = CreditCard.new
#order.build_credit_card
respond_with #order
end
Here is the form for entering in a CC on the order:
<%= form_for(#order, :url => finish_checkout_path, :html => { :class => 'validate' }) do |f| %>
<%= f.fields_for #cc do |cc| %>
<%= cc.text_field :cc_number, :placeholder => "Credit Card Number", :class => "full-width validate[required, creditCard] cc" %>
<%= cc.text_field :name, :placeholder => "Name as it appears on card", :class => "full-width validate[required]" %>
<%= select_month(Date.today, {:field_name => 'exp_month', :prefix => "order[credit_card]", :prompt => "EXP. MONTH"}, { :class => "dk half-width validate[required,past] marginRight10" }) %>
<%= select_year(Date.today, {:field_name => 'exp_year', :prefix => "order[credit_card]", :prompt => "EXP. YEAR", :start_year => Date.today.year, :end_year => Date.today.year + 10}, { :class => "dk half-width validate[required]" }) %>
<%= link_to "What's this?", "#", :class => 'cvv-help' %>
<%= cc.text_field :cvv, :class => 'half-width validate[required] marginRight10', :placeholder => "CVV" %>
<%= cc.text_field :zip_code, :class => 'half-width validate[required]', :placeholder => "Zip Code" %>
<% end %>
<%= f.hidden_field :amount, :value => #order.products.collect(&:price).reduce(&:+) %>
<p class="tos">By clicking the button below you agree to our terms of service.</p>
<p class="align-center"><%= f.submit "Submit", :class => 'btn submit' %></p>
<% end %>
And here is where I update the order (orders#finish):
current_order.update_attributes(params[:order])
When I do this, I get the following error: Can't mass-assign protected attributes: credit_card
I clearly have the credit_card_attributes in my attr_accessibleso I am not sure why this is erroring out.
Not sure, but it might be because of your controller code:
def checkout
#order = current_order
#cc = CreditCard.new
#order.build_credit_card
respond_with #order
end
With this, the credit card that you use in your fields_for is not linked to your order. That might be the problem.
Try doing that:
def checkout
#order = current_order
#order.build_credit_card
respond_with #order
end
and
<%= f.fields_for :credit_card do |cc| %>
I have a simple form that looks like this:
<%= simple_form_for #study,:url => studies_path, :html => { :class => 'form-horizontal' } do |f| %>
<%= f.input :category, :collection => #categories, :label => "Category", :selected => #categories.first %>
<%= f.button :submit, t('add_form'),:class => 'btn-primary' %>
I want to add a new field in that form that will be merely visual sugar. It will be a helper to dynamically change the :category field.
How do I do that?
Use text_field_tag or whichever other _tag helper to generate a form element without attaching it to any specific attribute of the model:
<%= simple_form_for #study,:url => studies_path, :html => { :class => 'form-horizontal' } do |f| %>
<%= f.input :category, :collection => #categories, :label => "Category", :selected => #categories.first %>
<%= text_field_tag :blah %>
<%= f.button :submit, t('add_form'),:class => 'btn-primary' %>
<% end %>
Update: I updated this after doing some digging and realizing that this might be twitter-bootstrap causing the problem.
Here is a rough version of my nested form:
<%= simple_nested_form_for #user, :html => { :class => 'form-horizontal' } do |f| %>
<fieldset>
<%= f.input :email %>
<%= f.input :name_first %>
<%= f.input :name_last %>
<table class="table table-striped">
<thead>
<tr>
<th>Active</th>
<th>Company</th>
<th>Role</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<%= f.simple_fields_for :roles, :wrapper_tag => :tr do |role_form| %>
<td><%= role_form.hidden_field :id %><%= role_form.input :active, :label => false, :wrapper => false %></td>
<td><%= role_form.association :company, :label => false, :wrapper => false %></td>
<td><%= role_form.input :role, :label => false, :collection => [ "Guest", "User", "Inspector", "Owner"], :wrapper => false %></td>
<td><%= role_form.link_to_remove "Delete", :class => 'btn btn-mini btn-danger' %>
</td>
<% end %>
</tbody>
</table>
<p><%= f.link_to_add "Add a Role", :roles %></p>
</div>
<div class="form-actions">
<%= f.submit nil, :class => 'btn btn-primary' %>
<%= link_to 'Cancel', users_path, :class => 'btn' %>
</div>
</fieldset>
<% end %>
When it's rendered the fields in the table rows are indented the same as the parent form via the { :class => 'form-horizontal' }. I just want the fields with no wrapper divs etc. and can't seem to figure it out. I thought the :wrapper => false was the ticket but no luck so far.
Dan
I ended up figuring it out on my own. You have to move the form style (form-horizontal) into a div just around the non-nested fields:
<%= simple_nested_form_for #user do |f| %>
<fieldset>
<div class="form-horizontal">
<%= f.input :email %>
<%= f.input :name_first %>
<%= f.input :name_last %>
<%= f.input :phone %>
<%= f.input :mobile %>
<%= f.input :password %>
<%= f.input :password_confirmation %>
</div>
<div class="tubbable">...
If you want to use a table (as in your initial example) to do the layout, I've patched the nested_form gem here https://github.com/ritchiey/nested_form to allow that.
To specify that you want the new fields appended at the bottom of the tbody and wrapped in a tr, replace your current link_to_add call with:
<%= f.link_to_add "Add a Role", :roles, :container =>'tbody', :fields_element=>'tr'%>
Note: the :container param is a CSS selector.
Not sure if this is what you want, but if you want to remove the div wrapper from an input field, use f.input_field instead of f.input:
= f.input_field :email, label: false, placeholder: 'email'
Add :wrapper => false to the simple_nested_form_for call.
The problem is, that :wrapper => false in simple_fields_for gets overwritten by the default :wrapper => nil in the simple_form_for configuration.
See this link for a setup:
How To: Render nested fields inside a table
Can anyone please convert these haml code snippets to the equivalent html.erb?
1.
%h1
Edit Project Form
.edit_project
= semantic_form_for [:admin, #project], :url => admin_organization_project_path(#organization), :html => { :multipart => true } do |f|
= f.inputs do
= f.input :name
= f.input :status, :as => :select, :collection => Project.statuses
= f.input :overview
= f.input :funds_purpose
= f.input :goal
.files
= render :partial => 'admin/edit_photo', :collection => #project.project_photos, :locals => { :field_name => 'project[project_photos_attributes][][file]' }
= f.submit 'Save Project'
2.
%li.file.optional#project_project_photo_file_input
= label_tag 'File'
= image_tag edit_photo.file.url(:thumb) if edit_photo.file?
= file_field_tag field_name
For the second:
<li class="file optional" id="project_project_photo_file_input">
<%= label_tag 'File' %>
<%= image_tag edit_photo.file.url(:thumb) if edit_photo.file? %>
<%= file_field_tag field_name %>
</li>
for first:
<h1> Edit Project Form </h1>
<div class='edit_project'>
<%= semantic_form_for [:admin, #project], :url => admin_organization_project_path(#organization), :html => { :multipart => true } do |f| %>
<%= f.inputs do %>
<%= f.input :name %>
<%= f.input :status, :as => :select, :collection => Project.statuses%>
<%= f.input :overview %>
<%= f.input :funds_purpose %>
<%= f.input :goal %>
<div class='files' >
<%= render :partial => 'admin/edit_photo', :collection => #project.project_photos, :locals => { :field_name => 'project[project_photos_attributes][][file]' } %>
</div>
<% end %>
<%= f.submit 'Save Project' %>
<% end %>
</div>