Dynamic changes in rails form (simpleform) - ruby-on-rails

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();
});
});

Related

How to have Rails 5 submit the form if IOS keyboard 'go' button is pressed

A default, scaffolded Rails 5 form will 'submit' if a desktop user presses the Enter button while the cursor is in a non-textarea form field. (If in a textarea field of course pressing Enter just inserts a newline into the field.)
When the form is viewed on an iphone, when you are editing a non-textarea field (such as a name) there is a Go button on the keyboard which is expected to submit the form.
The question: How does one enable that behavior by default on a Rails 5 app, eg, create forms so that the "Go" button on an iphone will submit the form the user is working on?
INCORRECTLY MARKED AS DUPLICATE FOR A GENERIC IOS QUESTION THAT HAS NOTHING TO DO WITH RAILS or RAILS FORMS. (Rails has myriad special issues such as default scaffolding of forms, authenticity tokens, etc. and that is what this question is about.)
Here is a sample form in HAML produced by simple_form:
.row
%h4 #{resource_name.to_s.humanize} sign in
= simple_form_for(resource, as: resource_name, url: session_path(resource_name)) do |f|
.row
.row.form-inputs
%div.col.l4.m6.s12
= f.input :email, required: false, autofocus: true
%div.col.l4.m6.s12
= f.input :password, required: false
%div.col.l4.m6.s12
= f.input :remember_me, as: :boolean if devise_mapping.rememberable?
.row
.form-actions
= f.button :submit, "Log in"
.row
= render "#{resource_name.to_s}s/shared/links"
Here is the form html:
<form novalidate="novalidate" class="simple_form new_admin" id="new_admin" action="/admins/sign_in" accept-charset="UTF-8" method="post">
<input name="utf8" type="hidden" value="✓" />
<input type="hidden" name="authenticity_token" value="XXXXXXX" /><div class='row'>
<div class='row form-inputs'>
<div class='col l4 m6 s12'>
<div class="input-field email optional admin_email">
<input class="string email optional" autofocus="autofocus" type="email" value="" name="admin[email]" id="admin_email" />
<label class="email optional" for="admin_email">Email</label></div>
</div>
<div class='col l4 m6 s12'>
<div class="input-field password optional admin_password">
<input class="password optional" length="128" type="password" name="admin[password]" id="admin_password" />
<label class="password optional" for="admin_password">Password</label></div>
</div>
<div class='col l4 m6 s12'>
</div>
</div>
</div>
<div class='row'>
<div class='form-actions'>
<input type="submit" name="commit" value="Log in" class="waves-effect waves-light btn" data-disable-with="Log in" />
</div>
</div>
</form>
Using
= f.button :button
in simple_form forces simple_form to use the button tag (instead of input) which seems to eliminate any issues with the IOS keyboard 'Go' button.
That said, I had some trouble reproducing the original issue several days later, so it's possible using the input tag works fine too under most circumstances, but I've switched to using :button just to be sure.

Add Image Tag to Checkbox Input Field with Rails 4 and Simple Form

Using Rails 4, Simple_Form and Bootstrap 3, I am trying to get my output HTML look like this to work with some front end styling:
<div class="checkbox">
<input value="0" type="hidden" name="member[remember_me]">
<label class="boolean optional" for="member_remember_me">
<input type="checkbox" value="">
<i class="input-helper"></i>
Keep me signed in
</label>
</div>
In my form, I have this:
<%= f.input :remember_me, class: 'checkbox inline', type: 'checkbox', as: :boolean if devise_mapping.rememberable? %>
And I cannot figure out how to get the image tag to show up inside the input field. What I get when the form is generated is this (missing the image tag):
<div class="checkbox">
<input value="0" type="hidden" name="member[remember_me]">
<label class="boolean optional" for="member_remember_me">
<input class="boolean optional" type="checkbox" value="1" name="member[remember_me]" id="member_remember_me">Remember me
</label>
</div>
I've tried this block that I thought should do it, but alas, no:
<%= f.input :remember_me, class: 'checkbox inline', type: 'checkbox', as: :boolean if devise_mapping.rememberable? do %>
<i class="input-helper"></i>
<% end %>
Any suggestions? Do I need to write a custom wrapper to get the image tag to show?
One option to put content inside any rails tag is to use
"#{image_tag('filename.png')}".html_safe
in place of the text, or using raw().

Test with Capybara cannot find a checkbox created using Simple Form association

I have a form created using Simple Form, as such
<%= simple_form_for #organisation do |f| %>
<div class="form-inputs">
<%= f.association :causes, as: :check_boxes %>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
The page works fine when I use a browser, but when I try to check this with Capybara, such as:
check('organisation_cause_ids_1')
And have tried many variations of this e.g.
find(:xpath , '//*[#id="organisation_cause_ids_1"]').set(true)
find("organisation_cause_ids_1").check
These always give an error:
Failure/Error: check('organisation_cause_ids_1')
Capybara::ElementNotFound:
Unable to find checkbox "organisation_cause_ids_1"
The HTML generated by Simple Form is:
<div class="input check_boxes optional organisation_causes">
<label class="check_boxes optional">Causes</label>
<span class="checkbox">
<label for="organisation_cause_ids_1" name="organisation[cause_ids]">
<input class="check_boxes optional" id="organisation_cause_ids_1" name="organisation[cause_ids][]" type="checkbox" value="1" />Cause A</label>
</span>
<span class="checkbox">
<label for="organisation_cause_ids_2" name="organisation[cause_ids]">
<input class="check_boxes optional" id="organisation_cause_ids_2" name="organisation[cause_ids][]" type="checkbox" value="2" />Hunger</label>
</span>
...
Edit: The problem was due to the lazy loading of the 'Causes' I created with the factories. They weren't being created so the page had no checkboxes.
Try with this
find_by_id('organisation_cause_ids_1').find("checkbox[value='1']").select_option
or maybe with this
find(:css, ".check_boxes[value='1']").set(true)

How to get Bootstrap button-like checkbox initially checked?

I have a problem with the following code in the view:
<div class="btn-group" data-toggle="buttons">
<%= f.label :private, class: "btn btn-default" do %>
<%= f.check_box :private %> Private
<% end %>
</div>
Technically it works, but when the private field is initially true (i.e. checked) the button looks as if it was unchecked. Perhaps it is due the fact that check_box helper generates two inputs, one of which is hidden.
Could someone show an example implementation of Bootstrap checkboxes in the Rails view?
It turned out that Bootstrap scripts just do not update the state on page load. So I solved it with this JavaScript code snippet:
$("[data-toggle='buttons'] .btn").each(function(i, el) {
var $button = $(el);
var checked = $button.find("input[type='checkbox']").prop("checked");
if (checked) {
$button.addClass("active");
} else {
$button.removeClass("active");
}
});
Here is a working checkbox from one of my projects generated using Simple Form:
<%= f.input :cost, label: "Cost to access resource" %>
Which generates:
<div class="form-group boolean optional archive_resource_cost">
<input name="archive_resource[cost]" type="hidden" value="0" />
<label class="boolean optional checkbox" for="archive_resource_cost">
<input checked="checked" class="boolean optional" id="archive_resource_cost" name="archive_resource[cost]" type="checkbox" value="1" />
Cost to access resource
</label>
</div>
Is your :private model attribute definitely boolean?

Rails simple form problem - How to put hidden input field last?

How do I change the order of the input element that simple form generate?
Because the hidden checkbox does block for clicking the label.
My simple_form code:
<label>
<span>Company<b></b></span>
<%= f.check_box :company_is_true %>
</label>
The form simple form generate:
<label>
<span>Company<b>0</b></span>
<input type="hidden" value="0" name="search[company_is_true]">
<input type="checkbox" value="1" name="search[company_is_true]" id="search_company_is_true">
</label>
That I want to generate, that works when clicking on label:
<label>
<span>Company<b>0</b></span>
<input type="checkbox" value="1" name="search[company_is_true]" id="search_company_is_true">
<input type="hidden" value="0" name="search[company_is_true]">
</label>
I don't know how to add a comment to the list of comments, but in response to:
The user should be able to click on the label to check and uncheck the checkbox – Rails
beginner 1 hour ago
It's not the checkbox that prevents the user from clicking on that label, it's the lack of the for="" in
<label>
<span>Company<b></b></span>
<%= f.check_box :company_is_true %>
</label>
Either use <%= f.label %> as agmcleod mentioned, or add a for="" to the label:
<label for="search_company_is_true">
<span>Company<b></b></span>
<%= f.check_box :company_is_true %>
</label>
In a traditional html form, it should be structured something like this:
<label for="name">Name: </label>
<input type="text" name="name" />
The for attribute connects it to a field with either a name attribute or id attribute with that value you use in for. To do this in rails, use the following:
<%= f.label :company_is_true, 'Company' %>
<%= f.check_box :company_is_true %>

Resources