Rails 3: Changing input box length - ruby-on-rails

Using Rails 3 with Twitter Bootstrap and Simple_form, I am having issues changing the length of the input box in this field:
<div class="input-prepend input-append">
<%= f.input :price, :wrapper => :append do %>
<span class="add-on">$</span>
<%= f.input_field :price %>
<span class="add-on">.00</span>
<% end %>
</div>
Others say to add this after the :price variable:
:input_html => {:size => 15}
The 'do' loop seems to change the rules, any suggestions?

try
:style => "width: 100px;"

Twitter bootstrap has css classes for this. Depending on what size you want you can add class input-min, input-small, input-large and so on. You can also use the span classes, e.g. span1, span2, etc.
<div class="input-prepend input-append">
<%= f.input :price, :wrapper => :append do %>
<span class="add-on">$</span>
<%= f.input_field :price, :class => 'input-medium' %>
<span class="add-on">.00</span>
<% end %>
</div>

I am using the f.input form to create controls with labels in a :class => 'form-horizontal' form, using a class attribute or style attribute (directly or as a hash, any way I tried) didn't work for me, and had zero effect on the generated HTML.
This is what worked for me:
<%= f.input :description, input_html: { class: 'span12' } %>
This works with both the Bootstrap column layout classes ('span1', 'span2', etc,) the input sizing classes ('input-large', 'input-xxlarge', etc,) or whatever custom class you want. The trick is using the input_html key. You can also mess with the label using the label_html key but that's likely to mess up the form-horizontal layout.
It looks like the size key in :input_html => {**:size** => 15} is ignored by SimpleForm... when I tired this it did not affect the HTML output.
I found this here in the SimpleForm docs:
https://github.com/plataformatec/simple_form#usage

Related

How can I add classes to a simple_form input wrapper in Rails?

I need to add a data attribute to an f.association input in a simple form. To do this I found this article and subsequent reference to simpleform's documentation. It is easy enough to add classes with the standard syntax, I am wondering why it's proving difficult using a wrapper.
So rather than the standard:
<%= f.association :size, input_html:{class: 'sku-suffix-component'} %>
I am using:
<%= f.input :size, as: :select, input_html:{class: 'sku-suffix-component'} do %>
<%= f.select :size, Size.all.map{ |s| [s.name, s.id, {'data-code-num' => s.code_num}] } %>
<% end %>
Much to my frustration, the added class is nowhere in the <select> tag (not to mention the missing other default classes and id naming convention [id="product_size_id" becomes id="product_size"]). I have tried various syntaxes and placements of the input_html hash.
Below you can see the difference in appearance etc. On the right is using the standard syntax.
And here is the resulting html:
<select name="product[size]" id="product_size"> (...)
Compared with:
<select class="form-control select required sku-suffix-component" name="product[color_id]" id="product_color_id"> (...)
Try this solution and if it is possible than create some link for jsfiddle so we can test and try to find solution
<%= f.input :size do %>
<%= f.select :size, Size.all.map { |s| [s.name, s.id, { class: 'sku-suffix-component', 'data-code-num' => s.code_num }]}, input_html: { class: 'sku-suffix-component' }, include_blank: true %>
<% end %>
I found the solution combining strategies that I found on separate posts.
The long and the short of it was to utilize the map method but not within a custom input wrapper.
<%= f.association :size, collection: Size.all.map{ |s| [s.name, s.id, {'data-code-num' => s.code_num}]}, input_html:{class: 'sku-suffix-component'} %>
This nets perfectly my desired <select> with an added class, and the <option>'s with a custom data- attribute.
<select class="form-control select required sku-suffix-component" name="product[size_id]" id="product_size_id">
<option value=""></option>
<option data-code-num="001" value="113">onesize</option>
(...)

Remove the default :size from form.text_field method

I see myself writing a lot of :size => nil for f.text_field as so:
<%= f.text_field :street_address, :size => nil %>
<%= f.text_field :post_code, :size => nil %>
<%= f.text_field :city, :size => nil %>
Which is just dumb. Without the :size => nil above, text_field renders an <input> with a size="some number" (usually size="30") which I don't need or want there.
So, how can I implement DRY and make it so that f.text_field would not generate the size=30 or size="some number" attribute by default? This way I can avoid always having to type :size => nil.
All default field options are stored in one hash. It defaults to the following:
# action_view/helpers/form_helper
DEFAULT_FIELD_OPTIONS = { "size" => 30 }
You can delete "size" from it in an initializer, for example.
ActionView::Helpers::InstanceTag::DEFAULT_FIELD_OPTIONS.delete("size")
Rails extends Object class with with_options method. You can take advantage of it:
<%= form_for :foo do |f| %>
<% f.with_options :size => nil do |f_nil| %>
<%= f_nil.text_field :street_address %>
<%= f_nil.text_field :post_code %>
<%= f.text_field :city %> <!-- you can use old f here too! -->
<% end %>
<% end %>
Gives:
<input id="foo_street_address" name="foo[street_address]" type="text" />
<input id="foo_post_code" name="foo[post_code]" type="text" />
<input id="foo_city" name="foo[city]" size="30" type="text" /> <!-- you can use old f here too! -->
Try encapsulating the text_field like so:
def no_size_text_area(form, method) form.text_area(method, {:size => nil}) end
put the function in your helper file.
and using no_size_text_area in its place like so:
no_size_text_area(f,:city)
The Rails Team has since removed these defaults as of version 4.0.x. There is no way to set global defaults anymore either. The only easy solution is to use CSS to set the dimensions.

How to use one partial in different contexts

i am new to rails and try to do the following:
I would like, because i use Bootstrap, to have a partial for a input field, with it's label and a little icon i called symbol in this case.
Here is my view:
<%= form_for(#user, :class => "form-horizontal" ) do |f| %>
<fieldset>
<%= render 'shared/text_field', function: f, tag: :name, symbol: '<i class="icon-user"></i>' %>
<%= render 'shared/text_field', function: f, tag: :email, symbol: "#" %>
<%= render 'shared/password_field', function: f, tag: :password, symbol: '<i class="icon-log"></i>' %>
<%= render 'shared/password_field', function: f, tag: :password_confirmation, alt: "Passwort wiederholen", symbol: '<i class="icon-log"></i>' %>
<!-- SUBMIT -->
<%= f.submit "Anmeldung", :class => "btn btn-primary" %>
</fieldset>
<% end %>
Here a subpartial for normal input fields:
<%= render 'shared/bootstrap/input_field' %>
<% content_for :label do %>
<%= function.label tag, :class => "control-label", :for => "prependedInput" %>
<% end %>
<%content_for :symbol do %>
<%= raw(symbol) %>
<% end %>
<% content_for :field do %>
<%= function.text_field tag, :class => "input-xlarge", :id => "prependedInput", :size => "6" %>
<% end %>
(there is also a subpartial for password fields, basicly exchanging function.text_field with function.input_field)
And here is the input_field which is rendered:
<div class="control-group">
<%= yield :label %>
<div class="controls">
<div class="input-prepend">
<span class="add-on"><%= yield :symbol %> </span>
<%= yield :field %>
</div>
</div>
</div>
So my question is: how can i solve this Problem in a nice and easy way (this things happend while refactoring and it got even worse then better) and how can i make it work, because by now something like this happens: http://pastebin.com/bNsgT9AR so yield puts with each content_for the content and the content before into the place (except the last one)
It would be great to hear nice solutions from you, there has to be a so much nicer way as almost always in Rails.
Greetings form Germany ;)
As the author of The Rails View, I agree with Ben Taitelbaum's post on this and say that Formtastic is totally a great option for this kind of complexity.
With regards to the code you posted, as developers we want to avoid that kind of view writing across the board, as it ends up an unmanageable mess. There's too many files involved in editing a form, and at some point, some other dev will come in and overwrite our shared partial, not knowing where else it was used, to change the way a different form behaves. Any benefit of code reuse that we can get out of this kind of abstraction is completely obliterated by the potential for it to go sour very quickly with mutliple developers.
While Formtastic is great, I've also been using SimpleForm a lot in my recent apps, especially when I don't need the full power of Formtastic.
SimpleForm will handle your label, and it also supports i18n as well. With this it would be:
<%= simple_form_for #user do |f| %>
<%= f.input :name, :input_html => { :class => 'user-icon' } %>
<%= f.input :email %>
<%= f.input :password, :as => :password, :input_html => { :class => 'log-icon' } %>
<%= f.input :password_confirmation, :as => :password, :input_html => { :class => 'log-icon' } %>
<%= f.button :submit %>
<% end %>
Then in your I18n file, you can have:
en:
simple_form:
labels:
user:
username: 'User name'
password: 'Password'
password_confirmation: 'Password confirmation'
de:
simple_form:
labels:
user:
username: 'Benutzername'
password: 'Passwort'
password_confirmation: 'Passwort wiederholen'
And more as you need it. You can define your hints and placeholders in the i18n file as well.
Also, think about adding the icon as a CSS pseudo class :after, and do so for each class that you need to add in the code)
input.user-icon:after {
// image as background, positioned properly, etc etc
}
input.log-icon:after {
// image as background, positioned properly, etc etc
}
And that way, you can remove this kind of stuff from your ERB/HTML and put it where it belongs: In the CSS (presentation layer).
There's a great section on forms in The Rails View, where they recommend using FormBuilders for this type of thing (they also discuss formtastic, which is worth checking out).
The biggest lesson I got out of this book (and I can't recommend it enough!) is that it's important to keep views as simple as possible, since they tend to be the least fun part of a rails app to debug, especially as the app grows large. So from this perspective, I would want the view to be nice and simple, something like:
<%= semantic_form_for(#user) do |f| %>
<%= f.inputs do %>
<%= f.input :name, class: 'icon-user' %>
<%= f.input :email %>
<%= f.input :password %>
<%= f.input :password_confirmation %>
<% end %>
<%= f.buttons %>
<% end %>
Start with a nice readable view as the goal, and add the necessary helpers and formbuilders as needed for custom field types.
I'd recommend using I18n for setting the submit button text to be "Anmeldung" instead of hardcoding that as well.
I haven't used it, but you might want to check out formtastic-bootstrap for getting the integration you want..
I feel that's a bit too much generalization overhead for a simple input field.
Have you considered simply creating one shared input field partial and just passing in the field name (you named it tag) and the type of field (text_field or password_field) as parameters? I can see that your approach might be more general, but if you just need those two options for now, keep it as simple as possible.
Addition in reply to comment:
You can simply pass parameters to your partial like so:
<%= render 'shared/error_messages', object: f.object %>
And then use the the variables in your partial. in your case you could
<%= render 'shared/bootstrap/input_field', function: f, tag: :name, input_field_type: :text_field %>
and then in _input_field.html.erb
<div class="control-group">
<%= function.label tag, :class => "control-label", :for => "prependedInput" %>
...

Disable a Text Box in Ruby on Rails?

I have the code:
<% generate_bullets = Bullet.all %>
<% generate_bullets.shuffle.first(4).each do |t| %>
<%= f.text_field, :bullets, :class => 'text_field disabled' %>
I want to disable a text box using embedded ruby, and am unable to do so. If I could receive any help on the situation I'm facing, it would be very greatly appreciated.
After I disable the text box I want to have a button generate four random ID's from the database table "bullets" and print them on the disabled text box in an array format, and utilize those four printed ID's to post them onto a created page. Any help with that would be even better.
Let me know if I'm reading this right: you're trying to disable the text field from the get-go in the HTML. Is that right?
If so, disabled isn't a class; it's its own attribute.
<%= f.text_field, :bullets, :class => 'text_field', :disabled => true %>
You can also use :readonly => true attribute.
For HAML
= f.text_field :name, :class => "form-control", :readonly => true
For ERB
<%= f.text_field :name, :class => "form-control", :readonly => true %>

How do I change the html tag and class generated by fields_for?

This is a simple question that I'm kinda ashamed to ask, but I've been banging my head against the wall and navigating through the rails 3 documentation without any success :/
So, here is the thing:
When I use the fields_for helper it wraps the generated fields in a <div class="fields"> ... </div> tag.
so, my code is
<ul class="block-grid two-up">
<%= f.fields_for :images do |image_builder| %>
<%= render "images/form", :f => image_builder %>
<% end %>
</ul>
and the generated html is:
<ul class="block-grid two-up">
<div class="fields">
<div>
<label for="company_images_attributes_0_image"> Image</label>
<input id="company_images_attributes_0_image"
name="company[images_attributes][0][image]" type="file">
</div>
</div>
<div class="fields">
<div>
<label for="company_images_attributes_1_image"> Image</label>
<input id="company_images_attributes_1_image"
name="company[images_attributes][1][image]" type="file">
</div>
</div>
</ul>
What I want to do is actually change the <div class="fields"> wrapper tag to <li>.
The documentation says you can pass options to the fields_for, but its not clear about what options you can pass, maybe you can change this wrapper tag?
A possibility could be to override a function, kinda like ActionView::Base.field_error_proc when there is an error in the form.
Quick edit: I forgot to mention that I'm using simple_form to generate this form. I tried looking in the simple_form.rb config file for a way to customize this, but I didn't see any way of doing it.
Solution
After further investigation, it turns out the form was using the nested_form gem as well to generate the form (not only simple_form). This generator was causing the fields_for to be wrapped in the div tag. Thanks everybody for their suggestions!
The following disables the wrapper:
f.fields_for :images, wrapper:false do |image_builder|
then you can add your own wrapper in the builder block.
A cheap solution would be just adding <li> tag into the form like:
<%= f.fields_for :images do |image_builder| %>
<li><%= render "images/form", :f => image_builder %></li>
<% end %>
I am not sure if you can completely eliminate the div tag by passing some params to field_for. But I think you can change the name of div class or id by passing the html block, like in form_for:
<%= form_for #image, :as => :post, :url => post_image_path,
:html => { :class => "new_image", :id => "new_image" } do |f| %>
You said you're using simple_form then you should be saying <%= f.simple_fields_for... Have you tried using wrapper_html option:
<%= f.input :name, :label_html => { :class => 'upcase strong' },
:input_html => { :class => 'medium' }, :wrapper_html => { :class => 'grid_6 alpha' } %>
Edit 1:
From SimpleForm documentation:
Wrapper
SimpleForm allows you to add a wrapper which contains the label, error, hint and input. The first step is to configure a wrapper tag:
SimpleForm.wrapper_tag = :p
And now, you don't need to wrap your f.input calls anymore:
<%= simple_form_for #user do |f| %>
<%= f.input :username %>
<%= f.input :password %>
<%= f.button :submit %>
<% end %>
Edit 2:
And there is this config option with which you can say what css class to use with the wrapper elements:
config/initializers/simple_form.rb
# CSS class to add to all wrapper tags.
config.wrapper_class = :input

Resources