Rails: Show or Hide elements based on DropDown selection using IF - ruby-on-rails

Using an IF Statement, How can I hide/show an element based on the value in the drop-down selection (transactionType)
Here's something I've been trying
Where did I go wrong?
<%= form_for(transaction) do |f| %>
<div class="field">
<%= f.label :transactionType %>
<%= f.select :transactionType, ['Income', 'Expense']%>
</div>
<%= if transaction.transactionType == 'Income' %>
<div class="field">
<%= f.label :amount %>
<%= f.number_field :amount, options = { max: 0 }%>
</div>
<% else %>
<div class="field">
<%= f.label :amount %>
<%= f.number_field :amount, options = { min: 0 }%>
</div>
<% end %>

How about using css classes..if its all about hiding elements from view...
So if you are using bootstrap,you can use hidden class.check more here.
in below example,i have used ternary operator which is just like if else.
for example:-
<%= form_for(transaction) do |f| %>
<div class="field">
<%= f.label :transactionType %>
<%= f.select :transactionType, ['Income', 'Expense']%>
</div>
<!-- here comes ternary operator -->
<div class="field <%= transaction.transactionType == 'Income' ? 'present' : 'hidden' %>">
<%= f.label :amount %>
<%= f.number_field :amount, options = { max: 0 }%>
</div>
<div class="field <%= transaction.transactionType != 'Income' ? 'present' : 'hidden' %>"">
<%= f.label :amount %>
<%= f.number_field :amount, options = { min: 0 }%>
</div>
if not using bootstrap,you can create custom class to hide/show elements.

Haven't used erb in quite some time, but I think you need to change
<%= if transaction.transactionType == 'Income' %>
should be
<% if transaction.transactionType == 'Income' %>
But this is only for the initial state. After that you will need jquery to toggle according to your select element

Related

Displaying different divs based on dropdown selection in Rails form

I am trying to create a form in Rails that includes a dropdown menu with three options: 'foo', 'bar', and 'baz'. If the user selects one of these options, I want to display a different div based on the selected option.
Here is my code:
<% options = [['Foo', 'foo'], ['Bar', 'bar'], ['Baz', 'baz']] %>
<%= form.label :type %>
<%= form.select :type, options_for_select(options, #selected_type), name: 'type' %>
<% if #selected_type == 'foo' %>
<div>
<%= form.hidden_field :type, value:'foo' %>
</div>
<% elsif #selected_type == 'bar' %>
<div>
<%= form.hidden_field :type, value:'bar' %>
</div>
<% elsif #selected_type == 'baz' %>
<div>
<%= form.hidden_field :type, value:'baz' %>
</div>
<% end %>
This is in my controller:
#vendor_item = VendorItem.new
#selected_type = params[:type]
puts "Selected type: #{#selected_type}"
I have implemented this using a select element, but the form is not working as expected. When I select an option from the dropdown menu, the form is not being submitted, and the divs are not being displayed.
CASE 1: If the form should be submitted on the server side, after the dropdown change:
<% options = [['Foo', 'foo'], ['Bar', 'bar'], ['Baz', 'baz']] %>
<%= form_with url: "your URL goes here", class: 'test_submit_form' do |form| %>
<%= form.label :type %>
<%= form.select :type, options_for_select(options, #selected_type), name: 'type' %>
<% if #selected_type == 'foo' %>
<div>
<%= form.hidden_field :type, value:'foo' %>
</div>
<% elsif #selected_type == 'bar' %>
<div>
<%= form.hidden_field :type, value:'bar' %>
</div>
<% elsif #selected_type == 'baz' %>
<div>
<%= form.hidden_field :type, value:'baz' %>
</div>
<% end %>
<%= form.submit %>
<% end %>
Javascript:
<script>
$('#type').on('change', function(){
$('form.test_submit_form').submit();
});
</script>
CASE 2: If you just need to show/hide DIVs on client side, after dropdown change:
<% options = [['Foo', 'foo'], ['Bar', 'bar'], ['Baz', 'baz']] %>
<%= form_with url: "your URL goes here", class: 'test_submit_form' do |form| %>
<%= form.label :type %>
<%= form.select :type, options_for_select(options, #selected_type), name: 'type' %>
<div class="option-container foo" style="display: <%= #selected_type == 'foo' ? 'block' : 'none'%>">
<%= form.hidden_field :type, value:'foo' %>
</div>
<div class="option-container bar" style="display: <%= #selected_type == 'bar' ? 'block' : 'none'%>">
<%= form.hidden_field :type, value:'bar' %>
</div>
<div class="option-container baz" style="display: <%= #selected_type == 'baz' ? 'block' : 'none'%>">
<%= form.hidden_field :type, value:'baz' %>
</div>
<%= form.submit %>
<% end %>
Javascript:
<script>
$('#type').on('change', function(){
$('.option-container').hide();
$('.option-container.' + $(this).val()).show();
});
</script>
Notice the option-container and option (foo, bar, baz) class on div and controller code will remain the same for both cases:
#selected_type = params[:type]

nested <div> element inside <button> element to get both links working

Open image here
So here's the situation I am trying to nest a div element ( a paypal button ) and a button element (rails element which submits forms) so on clicking, form gets submitted after paypal successful transaction.currently only one of it works No IDEA ON How to also redirect to a paypal payments page.### Please tell me any other way.if I'm following a wrong path ###. Here's the code
<%= form_for([#listing, #order]) do |form| %>
<% if order.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(order.errors.count, "error") %> prohibited this order from being saved:</h2>
<ul>
<% order.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-group">
<%= form.label :name %>
<%= form.text_field :name, class:"form-control" %>
</div>
<div class="form-group">
<%= form.label :size %>
<%= form.text_field :size, class:"form-control" %>
</div>
<div class="form-group">
<%= form.label :mobile %>
<%= form.text_field :mobile, class:"form-control" %>
</div>
<div class="form-group">
<%= form.label :city %>
<%= form.text_field :city, class:"form-control" %>
</div>
<div class="form-group">
<%= form.label :address %>
<%= form.text_field :address, class:"form-control" %>
</div>
<div class="form-group">
<%= form.label :PinCode %>
<%= form.text_field :PinCode, class:"form-control" %>
</div>
<div class="form-group">
<%= form.label :Landmark %>
<%= form.text_field :Landmark, class:"form-control" %>
</div>
<div class="form-group">
<%= form.label :Description %>(if any special changes)
<%= form.text_field :Description, class:"form-control" %>
</div>
<div class="form-group">
<%=form.submit%>
<%=link_to "Checkout" %>
</div>
<button type="submit" onClick="placeOrder(this.form)" class="button button2">
<!-- Set up a container element for the button -->
<div id="paypal-button-container"> </div>
<!-- Include the PayPal JavaScript SDK -->
<script src="https://www.paypal.com/sdk/js?client-id=sb&currency=USD"></script>
<script>
// Render the PayPal button into #paypal-button-container
paypal.Buttons({
// Set up the transaction
createOrder: function(data, actions) {
return actions.order.create({
purchase_units: [{
amount: {
value: '0.01'
}
}]
});
},
// Finalize the transaction
onApprove: function(data, actions) {
return actions.order.capture().then(function(details) {
// Show a success message to the buyer
alert('Transaction completed by ' + details.payer.name.given_name + '!');
});
}
}).render('#paypal-button-container');
</script>
<%=form.submit%>
Place Order</button>
If the form submission depends on the paypal transaction success, then submit the form only ater the transaction was approved on the onApprove callback. Something like this:
onApprove: function(data, actions) {
return actions.order.capture().then(function(details) {
// Show a success message to the buyer
alert('Transaction completed by ' + details.payer.name.given_name + '!');
yourForm = document.getElementById('id_of_the_form');
Rails.fire(yourForm, 'submit');
});
}

How to create a form with dependent fields? (RoR)

I am wondering how to create a form that displays field dependent on the fields selected beforehand. For example: if Coffee is selected as a drink, only then do I want to allow sugar and milk amounts to be input.
Here is my form:
<%= simple_form_for(#order) do |f| %>
<%= f.error_notification %>
<div class="field">
Drink: <%= f.select :drink, ['Coffee', 'Orange Juice', 'Tea'], id: 'extended_list' %><br />
</div>
Coffee Type: <%= f.select :coffee_type, ['Espresso', 'Cappuccino', 'Filter', 'Greek', 'Frappe', 'Latte'] %><br />
Sugar Amount: <%= f.select :sugar_amount, ((1..5).map {|i| [i,i] } << ["None",nil]) %><br />
Milk Amount: <%= f.select :milk_amount, ((1..5).map {|i| [i,i] } << ["None",nil]) %><br />
<% end %>
<%= f.button :submit, class: "button is-info" %>
<% end %>
First you need to wrap the fields you'd like to hide in a div. Add a distinct id to each of them.
For example, if you want to hide coffee_type, you can add the id "js-coffee-type" to it.
Also, add a class (for instance, d-none, as used by Bootstrap) so we can hide it using CSS.
<%= simple_form_for(#order) do |f| %>
<div class="field">
Drink: <%= f.select :drink, ['Coffee', 'Orange Juice', 'Tea'], id: 'extended_list' %><br />
</div>
<div id="js-coffee-type" class="d-none">Coffee Type: <%= f.select :coffee_type, ['Espresso', 'Cappuccino', 'Filter', 'Greek', 'Frappe', 'Latte'] %></div>
<div>Sugar Amount: <%= f.select :sugar_amount, ((1..5).map {|i| [i,i] } << ["None",nil]) %></div>
<div>Milk Amount: <%= f.select :milk_amount, ((1..5).map {|i| [i,i] } << ["None",nil]) %></div>
<%= f.button :submit, class: "button is-info" %>
<% end %>
In the same file, you can write the CSS code that hides this field.
<style>
.d-none { display: none; }
</style>
Now you can write the JS code to toggle the class depending on the first field.
<script>
$("#extended_list").change(function() {
var drink = $("#extended_list").val();
if (drink == "Coffee") {
$("#js-coffee-type").removeClass("d-none");
} else {
$("#js-coffee-type").addClass("d-none");
}
});
</script>
These are not best practices but they should do the work.

Rails4: How to apply Bootstrap to simple_nested_form_for

I'd like to apply bootstrap to the input fields as following.
<div class="input-group">
<span class="input-group-addon">Title</span>
<input type="text" class="form-control">
</div>
My current code is as following.
_form.html.erb
<%= simple_nested_form_for #event do |f| %>
<%= f.input :title %>
<%= f.input :description, input_html: { rows: 5, cols: 30 } %>
<%= f.input :charge_person %>
.
.
.
<% end %>
It would be appreciated if you could give me the best way in Rails.
This should do the trick:
<%= simple_nested_form_for #event do |f| %>
<div class="input-group">
<span class="input-group-addon">Title</span>
<%= f.input :title, class: 'form-control' %>
</div>
<div class="input-group">
<span class="input-group-addon">Description</span>
<%= f.input :description, class: 'form-control' %>
</div>
<div class="input-group">
<span class="input-group-addon">Charge Person</span>
<%= f.input :charge_person, class: 'form-control' %>
</div>
...
<% end %>
You shouldl read more detail SIMPLE FORM DOCS
<%= simple_nested_form_for #event, , wrapper_html: { class: 'input-group' } do |f| %>
<%= f.label :title, wrapper_html: { class: 'input-group-addon' } %>
<%= f.input_field :title, wrapper_html: { class: 'form-control' } %>
.
.
.
<% end %>

show rest of a form if a checkbox is ckecked in ruby on rails

I need to ask to my user if will pay a service with credit card...if it checked the option pay_with_card? it must show the rest of the form, that ask for other data like card number, mail, etc. if the user don't checked it, it must show a message, the question is...how can I do this? thanks in advance
<%= form_for(#product) do |f| %>
<%= f.label :pay_with_card? %>
<%= f.check_box :pay_with_card,{}, "Yes", "No"%>
<div>
<%= f.label :card_number %> <%= f.text_field :card_number %>
</div>
<div>
<%= f.label :mail %> <%= f.text_field :mail %>
</div>
<% end %>
Make the card number/mail details div style="display:none;", then add some javascript to the checkbox to change it to display:block;
Something like this:
<%= form_for(#product) do |f| %>
<%= f.label :pay_with_card? %>
<%= f.check_box :pay_with_card,{}, "Yes", "No"%>
<div id="card_details" style="display:none;">
<%= f.label :card_number %> <%= f.text_field :card_number %>
<%= f.label :mail %> <%= f.text_field :mail %>
</div>
<% end %>
<script type="text/javascript">
var checkbox = document.getElementById('product_pay_with_card');
var details_div = document.getElementById('card_details');
checkbox.onchange = function() {
if(this.checked) {
details_div.style['display'] = 'block';
} else {
details_div.style['display'] = 'none';
}
};
</script>
How about using jQuery?
First, wrap your credit card fields in a div with class credit_card_fields and than add this JS code to your page:
$("input[type='checkbox']#pay_with_card").on('change', function(){
$('.credit_card_fields').toggle();
});
You can use JS for it or move pay_with_card out of form like:
<%= link_to 'pay with card', your_current_path(:pay_with_card => 1) %>
<%= form_for(...) do |f| %>
<% if params[:pay_with_card] %>
<%= # fields for card %>
<% end %>
<% end %>
You can do it through jQuery, for example:
$ ->
$('select#pay_with_card').change ->
if $(this).val() == 'yes'
$('.card_block').slideDown('fast')
else
$('.card_block').slideUp('fast')
assumed that part of the form with payment card is included in the div with .card_block class
Ok my solution is this: all the code in the view, if a user check pay_with_card...(mi code is in spanish) it shows the complete form...if is not checked donĀ“t show nothing, just the same checkbox asking for payment... thanks guys.
function mostrar (){
var checkbox = document.getElementById('chk_tarjeta');
if (checkbox.checked)
document.getElementById("card_details").style.display = "block";
else
document.getElementById("card_details").style.display = "none";
</script>
<h1>Forma de Pago</h1>
<%= form_for(#product) do |f| %>
<div id="product_pay_with_card">
<div >
<%= f.label :paga_con_tarjeta? %></br>
<%= f.check_box :paga_con_tarjeta, :id => "chk_tarjeta", :onclick => "mostrar();" %>
<div>
</div>
</div>
<div id="card_details" >
<div>
<%= f.label :numero_de_tarjeta %></br>
<%= f.text_field :numerotarjeta %>
</div>
<div>
<%= f.label :codigo_de_seguridad %></br>
<%= f.text_field :codigoseguridad %>
</div>
This worked for me with a form_with model and bootstrap
Change my_hidden_form with an id that makes sense for your form.
Original code is haml
= form_with scope: :model, url: models_path, local: true do |form|
.row
.col-6
.form-group
%h5.mb0 THE CASE TO TICK
= form.check_box :form_value, {:data => {:aria => {controls: :my_hidden_form, expanded: false}, :toggle => "collapse", :type => "checkbox", :target => "#my_hidden_form" }}
.row
.col-6
.form-group.collapse#my_hidden_form
%h5.mb0 THE FORM TO SHOW WHEN CASE IS TICKED
= form.text_field :name, placeholder: "A name"
.row
.col-md-12.text-right
= form.submit 'Submit', class: "btn btn-primary"
Converted to erb/html with https://haml2erb.org/
<%= form_with scope: :model, url: models_path, local: true do |form| %>
<div class="row">
<div class="col-6">
<div class="form-group">
<h5 class="mb0">THE CASE TO TICK
<%= form.check_box :form_value, {:data => {:aria => {controls: :my_hidden_form, expanded: false}, :toggle => "collapse", :type => "checkbox", :target => "#my_hidden_form" }} %>
</h5>
</div>
</div>
</div>
<div class="row">
<div class="col-6">
<div class="form-group collapse" id="my_hidden_form">
<h5 class="mb0">THE FORM TO SHOW WHEN CASE IS TICKED
<%= form.text_field :name, placeholder: "A name" %>
</h5>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12 text-right">
<%= form.submit 'Submit', class: "btn btn-primary" %>
</div>
</div>
<% end %>
Since the approach suggested by #Unixmonkey didn't work for me, here's a slight variation I put together using an event listener.
<script type="text/javascript">
const checkbox = document.getElementById('product_pay_with_card');
const details_div = document.getElementById('card_details');
checkbox.addEventListener("change", (event) => {
if (event.currentTarget.checked) {
details_div.style['display'] = 'block';
}
else {
details_div.style['display'] = 'none';
}
});
</script>

Resources