Add more fields to form dynamically in Rails - javascript

I have a button that adds a partial to my form. The partial is additional form fields using fields_for
The main form is for creating a Project and the fields_for are for creating a RewardsTier model that belongs to the Project
Everything works for adding one additional RewardsTier, but when I add more than one additional RewardsTier form they all have the same name in the html: project[rewards_tiers_attributes][1][min_amount]. I think I just need the integer value to increment, but am not sure how to do this
#_rewards_tier_form.html.erb
<div class="tier-creation-div">
<%= f.fields_for :rewards_tiers do |r| %>
<label for="min_amount">Tier Amount</label>
<%= r.text_field :min_amount, data: {name: 'min_amount'}, class: "w-input", id: "min_amount", maxlength: "256", placeholder: "$1", required: "required", autofocus: 'true' %>
<label for="body">Tier Body</label>
<%= r.text_area :body, data: {name: 'body'}, class: "w-input", id: "body", maxlength: "5000", placeholder: "We email you the show notes and links...", required: "required", autofocus: 'true' %>
<% end %>
</div>
.
#new.html.erb
<%= form_for(#project, data: {name: "Email Form 2"}, html: {class: 'w-clearfix', id: "email-form-2", name: "email-form-2"}, url: '/projects/create', method: 'post' ) do |f| %>
...
<div class="rewards-creation-div" id="rewards-creation-div">
<h4>Rewards</h4>
<%= render 'rewards_tier_form', f: f %>
</div>
<div>
<a class="add-tier-button w-button" id="add-tier-button" href="#">+ Add tier</a>
<script type="text/javascript">
$('#add-tier-button').click(function() {
$("#rewards-creation-div").append('<%= escape_javascript("#{render 'rewards_tier_form', f: f}").html_safe %>');
});
</script>
</div>
...
<input class="submit-project-button w-button" data-wait="Please wait..." type="submit" value="Create Project"><a class="cancel-button w-button" href="#">Cancel</a>
<% end %>

This can't be done in Rails because it's all rendered client side. I got around this by using Javascript. My JS isn't great, so there is probably a cleaner way of writing it, but it works.
#_rewards_tier_form.html.erb
<div class="tier-creation-div">
<script>
document.getElementById("rewards-creation-div").lastElementChild.insertAdjacentHTML('beforeend','<label for="min_amount">Tier Amount</label>');
document.getElementById("rewards-creation-div").lastElementChild.insertAdjacentHTML('beforeend','<input data-name="min_amount" class="w-input" id="min_amount" maxlength="256" placeholder="$1" required="required" autofocus="autofocus" size="256" type="text" name="project[rewards_tiers_attributes]['+rewards_tier_index+'][min_amount]">');
document.getElementById("rewards-creation-div").lastElementChild.insertAdjacentHTML('beforeend','<label for="body">Tier Body</label>');
document.getElementById("rewards-creation-div").lastElementChild.insertAdjacentHTML('beforeend', '<textarea data-name="body" class="w-input" id="body" maxlength="5000" placeholder="We email you the show notes and links..." required="required" autofocus="autofocus" name="project[rewards_tiers_attributes]['+rewards_tier_index+'][body]"></textarea>');
</script>
</div>
.
#new.html.erb
<div class="rewards-creation-div" id="rewards-creation-div">
<h4>Rewards</h4>
<script type="text/javascript">
var rewards_tier_index = 0;
</script>
<%= render 'rewards_tier_form', f: f %>
</div>
<div>
<a class="add-tier-button w-button" id="add-tier-button" href="#">+ Add tier</a>
<script type="text/javascript">
$('#add-tier-button').click(function() {
rewards_tier_index = rewards_tier_index + 1;
$("#rewards-creation-div").append('<%= escape_javascript("#{render 'rewards_tier_form', f: f, child_index: #indx}").html_safe %>');
});
</script>
</div>

Related

How to set text_field required attribute false to submit the form using Ruby on Rails

I'm trying to submit a form with a looped text_field. But whenever I click the submit button, nothing is happening. The VIP name text_field is displaying whenever the user click the VIP discount from the discount dropdown. For each VIP ticket, there's a field for VIP name. The text_field is required. I'm trying to submit it by clicking the Purchase button. Maybe the required field on the hidden text_Field is taking effect that's why the form can't submit yet. I tried to implement the javascript .removeAttribute("required") and the .required = false; whenever the text_field is hidden but it didn't work as well. What's your thought?
<%= f.fields_for :movie_tickets do |mtf| %>
<div class="row text-center">
<label>============================ <%= "TICKET " + #count.to_s %> =============================</label> <br> <br>
<b> SEAT NO: <%=mtf.object.seat.name%> | ORIGINAL PRICE: <label class="label_original_prices"><%= number_to_currency mtf.object.net_price, unit:'' %></label> | DISCOUNTED PRICE: <label class="label_discounted_prices" id="pricediscount<%=#count%>">No Discount</label> </b> <br> <br>
</div>
<div class="form-group">
<div class="col-md-3">
<label>DISCOUNT :</label>
</div>
<div class="col-md-9">
<%= mtf.select :discount_id, options_from_collection_for_select(discounts, :id,:name),{include_blank:true}, class:"form-control", id:"discount"+#count.to_s, onchange:"getDisc(this)" %>
</div>
</div>
<br><br>
<div class="form-group" style="display: none;" id="divVIP<%=#count%>">
<div class="col-md-3">
<label>VIP NAME :</label>
</div>
<div class="col-md-9">
<%= mtf.text_field :vip_name , placeholder: "Type VIP name here...",class: "form-control", required: true %>
</div>
</div>
<% #count += 1 %>
<% end %>
<script type="text/javascript">
if(getValueDiscount == "9") {
document.getElementById('divVIP' + count).style.display = "block";
}else {
document.getElementById('divVIP' + count).style.display = "none";
}
</script>
Remove the required: true or set it to false in the below line:
<%= mtf.text_field :vip_name , placeholder: "Type VIP name here...",class: "form-control", required: true %>

Multiple fields types for nested form

My app has got location, each location got many IPs. Using railscasts relevant episode (http://railscasts.com/episodes/197-nested-model-form-part-2) I have built a location form which includes the ips list and an option to add new ones. Each ip has its text_field generated by the form.
Thing is, I want the existing ips to appear as labels rather than editable text boxes, something like this:
existing (read only)
existing (read only)
existing (read only)
new link
and upon clicking the link, an editable textbox is appended. Any ideas?
Models:
location.rb:
class Ip < ActiveRecord::Base
belongs to :location
validates_uniqueness_of :address
[...]
end
ip.rb:
class Location < ActiveRecord::Base
has_many :ips
accepts_nested_attributes_for :ips
[...]
end
Controller:
class LocationsController < ApplicationController
[...]
def location_params
params.require(:location).permit(:name, ips_attributes: [:id, :address])
end
end
Helper:
module ApplicationHelper
[...]
def link_to_add_fields(name, f, association)
new_obj = f.object.class.reflect_on_association(association).klass.new
fields = f.fields_for(association, new_obj, :child_index => "new_#{association}") do |builder|
render(association.to_s.singularize + "_fields", :f => builder)
end
link_to name, "#", onclick: "add_fields(this, \"#{association}\", \"#{escape_javascript(fields)}\")"
end
end
Views:
/locations/_form.html.erb:
<header>
<script>
function add_fields(link, association, content) {
var new_id = new Date().getTime();
var regexp = new RegExp("new_" + association, "g")
$(link).parent().before(content.replace(regexp, new_id));
}
</script>
</header>
<%= form_for #location do |f| %>
[...]
<%= f.label :ips, t('location.ips') %>
<%= f.fields_for :ips do |builder| %>
<%= redner "ip_fields", f: builder %>
<% end %>
<p>
<%= link_to_add_fields t('location.add_ip'), f, :ips %>
</p>
[...]
<% end %>
_ip_fields.html.erb:
<p class="fields">
<%= f.text_field :address %>
</p>
The relevant HTML:
<label for="location_ips">Addresses</label>
<p class="fields">
<input type="text" value="1.2.3.5" name="location[ips_attributes][0][address]" id="location_ips_attributes_0_address" />
</p>
<input type="hidden" value="19" name="location[ips_attributes][0][id]" id="location_ips_attributes_0_id" />
<p class="fields">
<input type="text" value="2.3.4.5" name="location[ips_attributes][1][address]" id="location_ips_attributes_1_address" />
</p>
<input type="hidden" value="20" name="location[ips_attributes][1][id]" id="location_ips_attributes_1_id" />
<p class="fields">
<input type="text" value="3.4.5.6" name="location[ips_attributes][2][address]" id="location_ips_attributes_2_address" />
</p>
<input type="hidden" value="21" name="location[ips_attributes][2][id]" id="location_ips_attributes_2_id" />
<p class="fields">
<input type="text" value="9.9.9.9" name="location[ips_attributes][3][address]" id="location_ips_attributes_3_address" />
</p>
<input type="hidden" value="22" name="location[ips_attributes][3][id]" id="location_ips_attributes_3_id" />
<p>
<a onclick="add_fields(this, "ips", "<p class=\"fields\">\n <input type=\"text\" name=\"location[ips_attributes][new_ips][address]\" id=\"location_ips_attributes_new_ips_address\" />\n<\/p>\n")" href="#">add new IP address</a>
</p>
Well, this isn't pretty (logic in the view isn't recommended) but it provides the solution I wanted: an extra parameter in the helper method to signal for a non-labelled field, then refactoring the partial conditional on the existence of this variable
helper:
module ApplicationHelper
[...]
def link_to_add_fields(name, f, association)
new_obj = f.object.class.reflect_on_association(association).klass.new
fields = f.fields_for(association, new_obj, :child_index => "new_#{association}") do |builder|
render(association.to_s.singularize + "_fields", :f => builder, labelled: false)
end
link_to name, "#", onclick: "add_fields(this, \"#{association}\", \"#{escape_javascript(fields)}\")"
end
end
_ip_fields.html.erb:
<p class="fields">
<% if (defined? labelled) %>
<%= f.text_field :address %>
<% else %>
<%= f.label :address, f.object.address %>
<% end %>
</p>

Ruby On Rails : AJAX and Submit Request Running Parallely

This is My code:
<%= simple_form_for #video do |form| %>
<div class="form-inputs">
<%= form.input :title, id: :video_title %>
<div class="row">
<div class="input-field col s12">
<textarea id="textarea1" name="video[description]" class="materialize-textarea"></textarea>
<label for="textarea1">Description</label>
</div>
</div>
<label for="spaceTags">Tags</label>
<div id="spaceTags" class="chips chips-placeholder"></div>
<%= form.label :movie %>
<%= form.file_field :movie %>
<%= form.label :preview_images%>
<%= form.file_field :preview_images, multiple: true %>
<p>
<input type="checkbox" name=video[published] id="test5" />
<label for="test5">Publish Video</label>
</p>
<div class="form-actions" onclick="fetch();">
<%= form.submit%>
</div>
<% end %>
and my javascript code is :
$('#textarea1').trigger('autoresize');
$('.chips').material_chip();
$('.chips-placeholder').material_chip({
placeholder: 'Enter a tag',
secondaryPlaceholder: '+Tag',
});
function fetch(){
var x = $('#spaceTags').material_chip('data');
$.ajax({
type: "POST",
url : "/videos",
data: {"sarthak":JSON.stringify(x)},
success : function(){alert ("Success!")},
error : function(data){alert(data.message)}
});
}
when i try to submit the form it makes the call to same action in both the cases.Is there some way by which i can delay the form submission until the AJAX call gets executed or any other way by which i can resolve this issue.
You can use event.preventDefault which will stop the normal execution of the form and just trigger your fetch method.
You can change your fetch method to:
function fetch(event){
event.preventDefault();
// the rest of your code
}
Then, in your ajax success promise, you can handle anything else you want, even submitting the form again if you wish
$.ajax({
type: "POST",
url : "/videos",
data: {"sarthak":JSON.stringify(x)},
success : function(){
alert ("Success!");
$('form').submit()
},
error : function(data){alert(data.message)}
});

Issues customizing Stripe payment form

Apologies in advance for the long question. I am new to Rails and Stacked Overflow and am running into road blocks.
I have stripe payments working in my app through my payments controller. The localhost:3000/payments/new works perfectly, but now I need to expand it in my app reservation app.
Currently when a user finds a table they like at a venue they can make a reservation. I did this by copying over the reservation/new form into a partial in my tables show page for a specific table
tables/show:
<%= render :partial=>'new_reservation', :locals=> {:reservation => Reservation.new(:table_id=> #table.id)} %>
And the following code for the partial:
<%= form_for(reservation) do |f| %>
<% if reservation.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(reservation.errors.count, "error") %> prohibited this reservation from being saved:</h2>
<ul>
<% reservation.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :user_id %><br>
<%= f.number_field :user_id %>
</div>
<div class="field">
<%= f.label :table_id %><br>
<%= f.number_field :table_id %>
</div>
<div class="field">
<%= f.label :reservation_date %><br>
<%= f.date_field :reservation_date %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Now I'd like to add the following code from my payments/new file to this partial to integrate stripe into the new reservation process:
<div id="new_card">
<div class="field">
<%= f.hidden_field :stripe_token %>
</div>
<div class="field">
<label>Card Number</label>
<input id="card-number" type="text" placeholder="4242 4242 4242 4242" />
</div>
<div class="field">
<label>CV Code</label>
<input id="cvc" type="text" placeholder="123" />
</div>
<div class="field">
<label>Expiry Month</label>
<input id="exp-month" type="text" placeholder="12" />
</div>
<div class="field">
<label>Expiry Year</label>
<input id="exp-year" type="text" placeholder="14" />
</div>
</div>
<div class="field">
<%= f.label :amount %><br />
<%= f.text_field :amount %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
I have updated the javascript for my reservation.js to the following:
$( function() {
$('#card-number').reservation'formatCardNumber')
$('#cvc').reservation('formatCardCVC')
$('#exp-month, #exp-year').reservation('restrictNumeric')
$(document).on('click', "#new_reservation [name='commit']", function( event ) {
if( $('input[name=saved_card]:checked').val() !== 'true' ) {
event.preventDefault()
var card = {
number: $("#card-number").val(),
expMonth: $("#exp-month").val(),
expYear: $("#exp-year").val(),
cvc: $("#cvc").val()
}
Stripe.createToken(card, function( status, response ) {
if (status === 200) {
$("[name='reservation[stripe_token]']").val(response.id)
$("#new_reservation").submit()
} else {
$("#stripe-error-message").text(response.error.message)
$("#credit-card-errors").show()
$("#user_submit").attr("disabled", false)
}
} )
}
} )
$("[name='saved_card']").change( function() {
showSaved = $(this).val() === 'true'
$('#saved_card').toggle( showSaved )
$('#new_card').toggle( ! showSaved )
} )
$("[name='saved_card']").eq(0).prop( 'checked', true ).change()
} )
The only issue is these payment do not show up on my stripe dashboard nor does the stripe_token pass to reservations.stripe_token through the hidden field.However, I get no errors and the reservation shows up as complete.
I have loaded the proper js in my application header, and stripe works when I use payments/new. Not sure why when i copy over the code it fails.
Should I attack the problem at another angle?

form not displayed in page source

i am creating a veiw page in my rails application
this is my view page :
<html>
<head>
<%= stylesheet_link_tag "$.multiselect2side", :media => "all" %>
<%= javascript_include_tag "$.multiselect2side" %>
<script>
$().ready(function() {
$("#student_name_id").multiselect2side();
});
</script>
<script>
function callGrade(grade_value_123) {
var id = grade_value_123;
}
</script>>
</head>
<body>
<div class="container">
<h1> <%= #message%> </h1>
<%= select(:grade,:id,#distinct_grade_list,{},:onchange => "callGrade(this.value)")%>
<%= select(:period,:id,#distinct_period_list)%>
<%= select(:student_name,:id,#student_name_list,{},{ :multiple => true, :size => 4 }) %>
<br/>
<%= radio_button_tag(:age, :child,{},:onclick => "callMe(this.id)") %><%= label_tag(:age_child, :" General Curriculum") %>
<%= radio_button_tag(:age, :adult) %><%= label_tag(:age_adult, :"Common Core Standards") %>
<br/>
<div id="farzi" style="border: 3px solid red;margin-top: 20px">
<% form_tag('call_ajax', :method=>'post', :multipart => true) do %>
<p>
Subject:
<br />
<%= text_field_tag "subject" %>
</p>
<p>
Priority:
<br />
<%= select_tag("priority", options_for_select([['Critical', '1'],
['Important', '2'],['Standard','3']], '3')) %>
</p>
<p>
Describe your problem:
<br />
<%= text_area_tag "description", "", :size=>"50x20" %>
</p>
<p>
Add an attachment:
<br />
<%= file_field_tag "attachment" %>
</p>
<p>
<%= submit_tag 'Submit' %>
</p>
<% end %>
</div>
</body>
</html>
now when i execute the page , the page doent display any form ,
and when i check the page source , there is no form content inside the div with id= farzi
in the page source from browser it shows
<div id="farzi" style="border: 3px solid red;margin-top: 20px">
</div>
any explanation ??
Replace
<% form_tag('call_ajax', :method=>'post', :multipart => true) do %>
with this
<%= form_tag('call_ajax', :method=>'post', :multipart => true) do %>
The <%= is used to output data from ruby in html.erb. If you just execute first command, it will return the correct data, but it won't output anything in html.

Categories

Resources