Setting up error message html view in this way? - ruby-on-rails

I'm using Twitter-Bootstrap and want to generate the correct html to display the error view how it does it on the main site, which is:
The html for the above field is:
<div class="control-group error">
<label for="inputError" class="control-label">Input with error</label>
<div class="controls">
<input type="text" id="inputError">
</div>
</div>
Note: I deleted Please correct the error, <span>, I just want the input field and label.
And if I was to use my sign up page as an example, the email field, it would be:
<div class="control-group">
<label for="user_email" class="control-label">Email*</label>
<div class="controls">
<input type="email" value="" name="user[email]" id="user_email" class="span3">
</div>
</div>
What do I have to do to get it to function like the former?

Don't re-invent the wheel. Use simple_form. The current version of the gem allows you to do the following:
rails generate simple_form:install --bootstrap
With that, you can use the simple_form helpers. They will generate the right things for you.

I've just encountered this issue, and have fixed it with a simple modification to the Bootstrap CSS.
My usual field code is:
<div class="control-group">
<%= f.label :fieldname, t('models.model.fieldname'), :class => "control-label" %>
<div class="controls">
<%= f.text_field :fieldname, :class => 'input-large' %>
</div>
</div>
Since I'm using f.label and f.text_field the label and input are both encapsulated with divs with the field_with_errors class (as Nicholas mentions), making the resulting HTML:
<div class="control-group">
<div class="field_with_errors"><label class="control-label" for="model_fieldname">Field name</label></div>
<div class="controls">
<div class="field_with_errors"><input class="input-large" id="model_fieldname" name="model[fieldname]" size="30" type="text" value=""></div>
</div>
</div>
To make these have the same look appearance as Bootstrap's <div class="control-group error"> style I add some extra selectors into bootstrap.css. I find all references to .control-group.error ... and add duplicate lines with .control-group .field_with_errors .... So I end up with this kind of thing:
.control-group.error > label,
.control-group.error .help-block,
.control-group.error .help-inline,
.control-group .field_with_errors > label,
.control-group .field_with_errors .help-block,
.control-group .field_with_errors .help-inline {
color: #b94a48;
}
It might not be the most elegant way of doing it for Rails, but to me it seemed a lot easier than more dependant gems or overriding the error processing. Yes, you'll have to make the same changes each time you update Bootstrap, but they're fairly simple changes, and you could probably make a patch file to do it automatically.

Rails automatically generates a div with the class field_with_errors when an error message appears. That div wraps the element with error. In order to customize it, you can add this line to application.rb:
config.action_view.field_error_proc = Proc.new { |html_tag, instance| %Q(<div class="field_with_errors">#{html_tag}</div>).html_safe }
This is the default, so in order to get the same structure as Twitter Bootstrap, you could play with it.
html_tag is a placeholder for the field with errors, e.g. <input name="model[attribute]" size="30" type="text" value="">
You could wrap this within another div, and also add a span saying "Please correct the error".
More info: http://guides.rubyonrails.org/configuring.html - item 3.9

Related

make hint span wrapper div in simple_form horizontal-form?

When using the horizontal-form in simple_form 3, I've got a f.input :name, hint: "this is a really long hint" the hint will display under the input field and wrap to whatever width the input is constrained to.
How do I make the hint display under both the label and the input but still within the form-group div that is around the label and the input?
This is how one of my fields is currently rendered (as shown in the screenshot above):
<div class="form-group string optional scenario_answers_value">
<label class="string optional col-xs-8 control-label" for="scenario_answers_attributes_14_value">Customer's Normal Oil Change Interval</label>
<div class="col-xs-4">
<input class="string optional form-control" data-original-title="hrs" data-placement="bottom" data-toggle="tooltip" data-trigger="focus" id="scenario_answers_attributes_14_value" name="scenario[answers_attributes][14][value]" rel="tooltip" type="text">
<p class="help-block">Most LT manufacturers recommend 250 hours because of wet stacking problems from the engine not running under a load.</p>
</div>
</div>
You force your form-group to render with bootstrap grid. 8/12 of row for a label and 4/12 for input field. In this way, you can`t use hint as you want.
You need something like:
`
<div class='form-group'>
<div class='row'>
<div class='col-xs-8'>
<label>
</div>
<div class='col-xs-4'>
<input class='form-control'>
</div>
</div>
<div class='row'>
<div class='col-xs-12'>
<p class='hint'></p>
</div>
</div>
</div>
Or you could try to style hint with CSS, but it is not the best way.
Also, you could provide your erb\haml\slim markup for more useful answers.

Dynamic changes in rails form (simpleform)

I'm trying to make a simple form with this general structure:
o accept o decline
[submit]
when the radio button accept is checked and submit pressed, I want it to change the state of my model (called Offer here).
BUT when the button decline is checked, the form needs to change to something like this:
o accept x decline
Please enter reason here: [text box]
[submit]
Having entered a (mandatory) reason for declining and pressing submit, will change the state of the model Offer too, but differently.
I'm currently having problems getting the form to display the way I want. I'm using SimpleForm and tried something like this:
<%= simple_form_for #offer do |f| %>
<%= f.input accepts, as: :radio_buttons %>
<%= f.input :r_comment, as: :text, :label => 'Please enter reason here:' , :input_html => { :rows => 2, } %>
<%= f.button :submit %>
<% end %>
This of course doesn't work, because there is no "accepts" method or variable defined for offers (and it shouldn't be!). As for dynamically showing the input text box, I don't even have the slightest clue.
I'd be glad for any help you might offer,
Lordylike
UPDATE: HTML generated by simple_form
<div class="control-group radio_buttons optional">
<label class="radio_buttons optional control-label">Accept?</label>
<div class="controls">
<label class="radio">
<input class="radio_buttons optional" id="offer_accepts_decline" name="offer[accepts]" type="radio" value="Decline" />
Decline
</label>
<label class="radio">
<input class="radio_buttons optional" id="offer_accepts_accept" name="offer[accepts]" type="radio" value="Accept" />
Accept
</label>
</div>
UPDATE: HTML generated for comment box
<div class="control-group text optional">
<label class="text optional control-label" for="offer_r_comment">Reason for rejection:</label>
<div class="controls">
<textarea class="text optional" cols="40" id="offer_r_comment" name="offer[r_comment]" rows="2">
</textarea>
</div>
</div>
i'm not a fan of formtastic or simple_form but looking at the documentation, you should be able to do the following
# offer.rb
attr_accessor :accepts
# view
<%= f.input :accepts, as: :radio_buttons, collection: ['Decline', 'Accept'] %>
# js which can be placed inline or in the assets. let's use coffee
# you should also limit the selector below to include the class or the id of the
# radio buttons. I'm also not familiar with the html generated by simple form so
# the selectors to show and hide should also be changed.
$ ->
$(':radio').change ->
if $(this).prop('checked')
if $(this).val() == 'Accept'
$('#offer_r_comment').show()
else
$('#offer_r_comment').hide()
UPDATE: non coffee version. you can place this inside a script tag and just throw in the view.
$(document).ready(function() {
$(':radio').change(function() {
if ($(this).prop('checked'))
if ($(this).val() == 'Accept')
$('#offer_r_comment').show();
else
$('#offer_r_comment').hide();
});
});

Twitter bootstrap "lead" not working with simple_form

I'm using Twitter Bootstrap along with simple_form in Rails. For some reason I cannot get the Bootstrap class="lead" to function. I see in the rendered HTML some additional classes which I assume come from simple_form. How can I get the two to play together?
This is my code:
<p class="lead">
<%= sentence.input :dialog, :input_html => { :class => "span8" },
:placeholder => "Enter your sentence here", :label => false %>
</p>
And this is the rendered HTML:
<p class="lead">
<div class="control-group string optional">
<div class="controls"><input class="string optional span8" id="dialog_catagory_dialogs_attributes_0_dialog" name="dialog_catagory[dialogs_attributes][0][dialog]" placeholder="Enter your sentence here" size="50" type="text" />
</div>
</div>
</p>
EDIT
I've tried various options, including using the rendered HTML, like this and removing the divs. Still not working.
<p class="lead">
<input class="string optional span8" id="dialog_catagory_dialogs_attributes_0_dialog" name="dialog_catagory[dialogs_attributes][0][dialog]" placeholder="Enter your sentence here 2" size="50" type="text" />
</p>
output
<p class="lead">
<input id="dialog_catagory_dialogs_attributes_0_dialog" name="dialog_catagory[dialogs_attributes][0][dialog]" size="30" type="text" />
</p>
Here's the problem: Placing a div inside of a p element implicitly closes the p tag in standards-confirming browsers. ( Reference )
You can see (and modify locally, if you wish) the behavior of Simple Form's Bootstrap generators in this file on Github.

Twitter Bootstrap + SimpleForm: appending an icon to a form field doesn't show error messages

I want to append an icon to a SimpleForm form field using Twitter Bootstrap. Here is the solution that I found in another SO question:
<div class="input-append date" id="birthday-picker" data-date="06-04-1986" data-date-format="dd-mm-yyyy">
<%= f.input :birthday, :wrapper => :append do %>
<%= f.input_field :birthday, as: :string, placeholder: "06-04-1986", readonly: true %>
<span class="add-on"><i class="icon-th"></i></span>
<% end %>
</div>
However, when I add this piece of code to my form, the validation kicks in but the message is not shown for that particular field. Any ideas on what's happening please?
Update
Here is the HTML generated:
<div class="input-append date" id="birthday-picker" data-date="06-04-1986" data-date-format="dd-mm-yyyy">
<div class="control-group date required error">
<label class="date required control-label" for="user_birthday">Birthday <abbr title="required">*</abbr></label>
<div class="controls"><div class="input-append">
<input class="string required readonly" id="user_birthday" name="user[birthday]" readonly="readonly" size="50" type="text" value="31-03-2012">
<span class="add-on"><i class="icon-th"></i></span>
</div>
<span class="help-inline">You are too young</span>
</div>
</div>
As you can see, the error message is generated. But for some reason, the span that contains the error message gets applied the following styles:
.input-append, .input-prepend {
font-size: 0;
white-space: nowrap;
}
Even though it's outside the input-append div... Any ideas what's happening?
Update 2
The error message was in fact in an input-append div, which I removed. Now the error message appears but it's below the input, not inline like regular inputs...

custom validation markup in Rails(3)

I'm trying to accomplish the following mark-up for all my form elements
<div class="input-container">
<label>Topic Title</label>
<div class="input-holder">
<input type="text" />
</div>
</div>
<div class="textarea-container">
<label>Post</label>
<div class="textarea-holder">
<textarea></textarea>
</div>
</div>
invalid fields mark-up:
<div class="input-container alert">
<label>Topic Title</label>
<div class="input-holder">
<input type="text" />
</div>
</div>
<div class="textarea-container alert">
<label>Post</label>
<div class="textarea-holder">
<textarea></textarea>
</div>
</div>
here's my current haml markup:
.input-container
= f.label :title, 'Topic Title'
.input-holder
= f.text_field :title
.textarea-container
= f.label :body, 'Post'
.textarea-holder
= f.text_area(:body, :size => "60x10")
Now what would I need to do if I want the container divs to have the alert class when a field in my form is invalid?
I want to do the same thing but unfortunately haven't figured out a clean way to handle it.
You can override ActionView::Base.field_error_proc, but that doesn't help with the enclosing elements.
It can be done manually by checking errors on each field ('post.errors['body'].nil?') and outputting your alert class conditionally.
The next step could be extracting the logic into a view helper, and perhaps some further abstraction after that.
But it would still be nice to do this in a more automated, Rails-y fashion.
It might be best to use either the formtastic or simple_form gems which out of the box support highlighting an individual invalid field.
I'm almost certain they do this by changing the CSS class on the field or its container, which you could also hook into in your stylesheets.

Resources