How to add element after label before input with simpleform - ruby-on-rails

I am trying to add a character counter to an app I am helping with but the app uses simple form gem for the page i need to work with. The Gem seems pretty cool expect that it auto generates the html and i need to figure out how to add my custom div after the label and the input so i can add the character count and change it as it goes.
I can do this with jquery but i am wanting to do an initial hard coded count for initial load just in case the user has an old browser without javascript.
<%= simple_form_for #organization do |f| %>
<div class="form-inputs">
<%= f.simple_fields_for :projects do |project| %>
<div class="row">
<%= project.input :description, :placeholder => 'What does your project do?', input_html: { class: 'project-description' }, :maxlength => 255 %>
<% end %>
I want to add the character limit to the description tag.

Related

Rails simple form doen't pass params from input

I want to display a list of InvestorTypes (as a radio button) but before each type I should be able to add an explanation of that type. Here is what I've got:
<%= simple_form_for(resource, as: resource_name, url: users_user_experience_level_path(resource_name), html: { method: :put }) do |f| %>
<div class="form-inputs">
<% User::USER_EXPERIENCE_LEVEL.each do |level| %>
<b>Investor type <%= level %></b>
<%= t("user.description.#{level}") %>
<%= f.input :experience_level, collection: [level], as: :radio_buttons, label: false %>
<% end %>
</div>
<div class="form-actions">
<%= f.button :submit, 'Submit' %>
</div>
<% end %>
Which gives me expected view:
Investor type Beginner
Some explanation of what is going on
[checkobox] type Beginner
Investor type Expert
Some clarification of who is an expert and what ever you want to display here
[checkbox] type Expert
Investor type Institutional
Some clarification of who is an institutional client and some legal stuff
[checkbox] type Institutional
But when Submit button is pressed it doesn't pass input value (radio box selection which user chose) into the params:
=> #<ActionController::Parameters {"experience_level"=>""} permitted: true>
[EDIT]
class User < ApplicationRecord
USER_EXPERIENCE_LEVEL = %w[institutional beginner expert].freeze
end
It looks to me like you're using simple form wrong. The "collection" input in Simple Form is expecting to get an entire list of options, not just one option.
Looping in the way you're doing it is creating one group for each experience level, and each group only has one button in it. So it might visually look correct, but it's not functioning the way you intended. Instead you want to create one group of radio buttons for experience level such that each button changes the value of experience level.
Because you're doing this with significant customization around the appearance, it's probably not a good use of Simple Form, and instead you should fall back to the normal Rails form helpers.
You want to pass a block to f.input to get the simple form wrapper and then use the lower level rails helpers:
<%= simple_form_for(resource, as: resource_name, url: users_user_experience_level_path(resource_name), html: { method: :put }) do |f| %>
<div class="form-inputs">
# adds the simple form wrapper
<%= f.input :experience_level do %>
# iterates across the options and yields a input builder to each iteration
<%= f.collection_checkboxes(:experience_level, User::USER_EXPERIENCE_LEVEL, :value_method, :label_method) do |cb| %>
# There are three special methods available:
# object, text and value,
# which are the current item being rendered, its text and value methods, respectively.
<%= t("user.description.#{cb.text}") %>
<%= cb.check_box %>
<% end %>
<% end %>
</div>
<div class="form-actions">
<%= f.button :submit, 'Submit' %>
</div>
<% end %>
If you don't actually have a model you can use #itself to iterate across a flat array:
<%= f.collection_checkboxes(:experience_level, User::USER_EXPERIENCE_LEVEL, :itself, :itself) do |cb| %>
Or an array of pairs:
<%= f.collection_checkboxes(:experience_level, User::USER_EXPERIENCE_LEVEL.zip(User::USER_EXPERIENCE_LEVEL), :first, :last) do |cb| %>
Or even a struct.

How do you add text inside a text field in Rails?

I would like to add username inside the username text field in my application (vs having a label next to it) the user would be able to type over this text. I've seen it done in html but I'm confused as to how to do it on my new.html.erb page since im using the form_for tag and the text_field tag.
thanks in advanced!
Use "placeholder".
<%= form_for #user do |f| %>
<%= f.text_field :username, :placeholder => "Username" %>
...
<%= f.submit %>
<% end %>
This will only work for html5 supported browsers by the way, so make sure you have jquery fallback for IE 8, 7 etc.
This is achieved by using the HTML5 placeholder attribute.
In rails, you can simply add the placeholder attribute:
<%= f.text_field :whatever, :placeholder => "text for placeholder..." %>

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" %>
...

Rails 3 Nested Form and jQuery UI datepicker updates first element only

This isn't working as I'd like.
I have an entry form for a new job, which is made up of a number of steps. By default there are 4 new and unsaved steps populated per job.
Using the code from the view below, I am able to attach the jQuery UI datepicker control to the text fields and they appear against the correct input field when i click them.
However, when I select a date from the picker it is only ever going into the field representing the start date of the first step.
<%= form_for #job, :url => jobs_path do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<% #job.steps.each do |step| %>
<%= fields_for "job[step_attributes][]", step do |s| %>
<%= s.label :name %>
<%= s.text_field :name %>
<%= s.label :start_date %>
<%= s.text_field :start_date, :class => :datepicker %>
<%= end %>
<% end %>
<script type="text/javascript">
$(function() {
$('.datepicker').datepicker({ dateFormat: "dd/mm/yy"});
});
</script>
I know ultimately this has to do with the generated id attribute for the input elements being the same, was wondering, has anybody successfully overcome this issue?
This fiddle: http://jsfiddle.net/twilson/u9m9L/ demonstrates my problem.
First, invoke fields_for on your form builder instead:
<%= f.fields_for :steps do |s| %>
Second, you don't need to iterate through #job.steps if you specify the association name to fields_for. There's an example on how to use it with one-to-many assoiciations here.
If you still have this problem, paste your generated HTML, it would easier to find the cause.
EDIT
OK so the problem is because Rails form builder does not generate child indexes to give unique IDs to nested fieldsets. This most likely happened because the associations are built but not yet saved to the DB. One way I see is to assign child indexes manually, like so:
<% #job.steps.each_with_index do |step,i| %>
<%= f.fields_for :steps, step, :child_index => i do |s| %>
See if that helps.
This is a somewhat contrived scenario given that you have only new objects. To be able to dynamically add/remove nested items, this would be a bit trickier. You can see how this can be dealt with in the nested model Railscasts.

Radio Buttons, Check boxes not lined up vertically with labels (Rails 3)

I've been looking for an existing answer to this question, but haven't found one. I am currently working on a Rails 3 project with some forms that have multiple choice/multiple selection questions with radio buttons and check boxes, respectively. I use the form builder style, like so:
<%= form_for [#profile,#answer], :method => 'put', :url => { :action => 'update' } do |f| %>
<% if #options.nil? %>
<%= #error_message %>
<% else %>
<% #options.each do |option| %>
<label for="<%= 'answer_response_' + option.downcase.gsub(' ','_') %>"><%= f.radio_button :response, option %><%= option %></label>
<% end %>
<% end %>
<div id="comments_area">
<p>Do you have any additional comments?</p>
<%= f.text_area :comments, :cols => 90, :rows => 5 %>
</div>
<%= submit_tag("Previous") %>
<%= submit_tag("Next") %>
<% end %>
#options is just an array of strings denoting each option to be displayed.
The labels work perfectly, attached to their respective radio button/check box. However, the text for the label always seems to show up on the next line no matter what I do. Example:
Describe yourself:
[]
Short
[]
Fun
[]
Bored
I have already tried using the f.label form helper after the f.radio_button/check_box as well, and it has the same problem. In fact, this is why I am doing the label tag "HTML-style" above (not using the ERB). Is this a styling problem that can be solved with CSS? If so, how can I put the label text on the same line after the respective check box/radio button?
For completeness' sake, this is how to resolve the multiline concern with an inline style (using haml)
= f.check_box :eula_accepted
= f.label :eula_accepted, "I accept the EULA", :style => "display:inline"
This could be a CSS issue, but more likely it's because you placed radio button INSIDE the label, when it should be before or after.
Try separating the two. If that doesn't change the outcome, look into input width - if your inputs are set to cover the entire line, that would push the text into the next line. To change alignment, you can also look into the CSS keywords "inline", "float" and possibly "vertical-align". Getting the Web Developer extension for Firefox can also help you figure out what's going on with the CSS, e. g. how much space an element is taking up.

Resources