Ruby On Rails : AJAX and Submit Request Running Parallely - javascript

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

Related

Validating fields on entry or embedding on submit with regex validation

I have a form for creating charges where some of the fields get entered into a table and some get sent to Stripe only.
One of the fields may cause confusion as it needs to be entered with a certain URL format via Regex and I want a custom message for when this field is entered incorrectly.
Function I desire: I preferably would like for it to be validated right away, sort of like how some website when you enter an incorrect email format, it will let you know either while you're still in the text field or once you click away from it.
I have tried:
function validateHhMm(inputField) {
var isValid = /^(?:https?:\/\/)?(?:(?:www|m)\.)?twitter\.com\/\w+\/status\/\d+(?:\/\/?)?\$/.test(inputField.value);
if (isValid) {
inputField.style.backgroundColor = '#bfa';
} else {
inputField.style.backgroundColor = '#fba';
}
return isValid;
}
with:
<%= form_for(#order, url: listing_orders_path([#listing, #listing_tweet]), remote: true) do |form| %>
<% if #order.errors.any? %>
<ul>
<% #order.errors.full_messages.each do |msg| %>
<div class="alert alert-danger alert-dismissable">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<%= msg %>
</div>
<% end %>
</ul>
<% end %>
<div class="form-group">
<%= form.label :name, "Who's the Shout for?" %>
<%= form.text_field :name, class: "form-control", required: true %>
</div>
<div class="form-group">
<%= form.label :email %>
<%= form.text_field :email, class: "form-control", required: true %>
</div>
<div class="form-group">
<%= form.label :description %>
<%= form.text_area :description, class: "form-control", :rows => 10, required: true %>
</div>
<div class="form-group">
<%= form.label :twitter_tag %>
<%= form.text_field :twitter_tag, class: "form-control", required: true %>
</div>
<div class="form-group">
<div class="input-group">
<%= form.label :twitter_link, "Twitter Link", id: "twitter" %>
</div>
<%= form.text_field :twitter_link, class: "form-control", required: true %>
</div>
<script
src="https://js.stripe.com/v3/">
</script>
<div class="form-row">
<label for="card-element-2">
Credit or debit card
</label>
<div id="card-element-2" class="form-control">
</div>
<div id="card-errors" role="alert"></div>
</div>
<br>
<div class="form-group">
<%= form.submit, id:"button-element" %>
</div>
<span class="token"></span>
<% end %>
<% end %>
</div>
For whatever reason, I can't get notices to pop up within this controller (it's used within another controllers show page which might be causing the issue) --- so i figured i would go this route and try with javascript / jquery as i would rather have the validation in real time.
Now, another piece to the puzzle is the stripe code:
var stripe = Stripe('pk_test_1234567890');
var elements = stripe.elements();
var style = {
base: {
#styling_code_here
};
var card = elements.create('card', {style: style});
card.mount('#card-element-2');
card.addEventListener('change', function(event) {
var displayError = document.getElementById('card-errors');
if (event.error) {
displayError.textContent = event.error.message;
} else {
displayError.textContent = '';
}
});
var form = document.getElementById('payment_form');
form.addEventListener('submit', function(event) {
event.preventDefault();
stripe.createToken(card).then(function(result) {
if (result.error) {
var errorElement = document.getElementById('card-errors');
errorElement.textContent = result.error.message;
} else {
stripeTokenHandler(result.token);
}
});
});
function stripeTokenHandler(token) {
var form = document.getElementById('payment_form');
var hiddenInput = document.createElement('input');
hiddenInput.setAttribute('type', 'hidden');
hiddenInput.setAttribute('name', 'stripeToken');
hiddenInput.setAttribute('value', token.id);
form.appendChild(hiddenInput);
form.submit();
}
I added the above code because maybe i should embed the validation within that?
Aside from the attempt above, I have made a few others but none seem to work aside from validating if a field is empty, this rails already has a feature for this. I want the validation for the regex either in real time or once the field is left.
HTML5 has a built in feature:
for example this will work:
<%= form.text_field :twitter_link, class: "form-control", required: true, pattern: '^(?:https?:\/\/)?(?:(?:www|m)\.)?twitter\.com\/\w+\/status\/\d+(?:\/\/?)?$',
title: "Click the '?' for more information" %>
A message will appear when the validation isn't working.
One issue i did notice is this front end validation doesn't work when the page isn't fully loaded. If you are going to use this, i suggest using a model validation as well as i did.

Dynamically update rails form textarea based on dropdown select

I have a table called Email_Template. It contains two columns: template_name and template_body.
I also have a form in which user selects template_name in dropdown (coming from database column). In the same form, based on template_name selection, the textarea should display corresponding “template_body” content coming from the same database table. Please tell me how to do this.
My Form
<%= form_for :email_form, :html => {:class => "form-horizontal"}, url: candidates_send_email_path do |f| %>
<div class="form-group">
<%= f.label :template_name, "Template" %>
<div class="col-md-10">
<%= select_tag "template_name", options_from_collection_for_select(Email_Template.all, "id", "id") %>
</div>
</div>
<div class="form-group">
<%= f.label :template_body, "Template Body" %>
<div class="col-md-10">
<%= f.text_area :email_content, rows: 7 %><br/>
</div>
</div>
<div class=text-right>
<%= f.button class: "btn btn-primary btn-modal" do %>
SEND EMAIL <i class="glyphicon glyphicon-send"></i>
<% end %>
</div>
<% end %>
routes.rb
post '/template_body_finder/:template_id' => 'search#find_template'
search_controller.rb
def find_template
#email_template = Email_Template.find(params[:template_id])
respond_to do |format|
format.js
end
end
search.js.coffee
$ ->
$(document).on 'change', '#template_id', (evt) ->
template_id = $(this).val()
window.alert(template_id)
curr_url = "/template_body_finder/" + template_id
$.ajax({
type: 'POST',
url: curr_url,
data: {'template_id': template_id},
success: ( data, status, xhr ) -> })
find_template.js.erb
$(“#email_content”).val= <%= #email_template.template_body %>
;
Here try this:-
1- your form
<%= form_for :email_form, :html => {:class => "form-horizontal"}, url: candidates_send_email_path_path do |f| %>
<div class="form-group">
<%= f.label :template_name, "Template" %>
<div class="col-md-10">
<%= select_tag "template_name", options_from_collection_for_select(Email_Template.all, "id", "id") %>
</div>
</div>
<div class="form-group">
<%= f.label :template_body, "Template Body" %>
<div class="col-md-10">
<%= f.text_area :email_content, rows: 7 %><br/>
</div>
</div>
<div class=text-right>
<%= f.button class: "btn btn-primary btn-modal" do %>
SEND EMAIL <i class="glyphicon glyphicon-send"></i>
<% end %>
</div>
<% end %>
<script type="text/javascript">
$('#template_name').on('change', function(){
var template_id = $(this).val();
// alert(template_id);
// ajax request
$.ajax({
url: "/template_body_finder",
type: "GET",
data : {
template_id: template_id
},
dataType: "script",
});
})
</script>
2- change your url:
get '/template_body_finder' => 'search#find_template'
3- in controller -
def find_template
#email_template = Email_Template.find(params[:template_id])
respond_to do |format|
format.js
end
end
4- in your find_template.js.erb file it should like this-
$('#email_form_email_content').val("<%=#email_template.template_body%>");
this works for me, if you have any doubt you can ask in comments.
thank you.

Add more fields to form dynamically in Rails

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>

Issue with Payment method selection when I add Braintree Drop-in UI in Spree Store

I'm trying to implement extension to accommodate drop-in UI of braintree when customer selects Braintree as a payment method. If I add braintree js code into _gateway.html.erb then all the other payment methods stop working. If I select any other method except braintree and click "Save and continue" then nothing happens. "Save and continue" button just gets disabled.
I've overwritten spree/frontend/app/views/spree/checkout/_gateway.html.erb.
<% if payment_method.name == "Braintree" %>
<div id="dropin"></div>
<% else %>
<div class="well clearfix">
<%= image_tag 'credit_cards/credit_card.gif', :id => 'credit-card-image', :class => 'pull-right', :width => '170', :height => '28' %>
<% param_prefix = "payment_source[#{payment_method.id}]" %>
<p class="field">
<%= label_tag "name_on_card_#{payment_method.id}" do %>
<%= Spree.t(:name_on_card) %><abbr class="required" title="required">*</abbr>
<% end %>
<%= text_field_tag "#{param_prefix}[name]", "#{#order.billing_firstname} #{#order.billing_lastname}", { id: "name_on_card_#{payment_method.id}", :class => 'form-control required'} %>
</p>
<p class="field" data-hook="card_number">
<%= label_tag "card_number" do %>
<%= Spree.t(:card_number) %><abbr class="required" title="required">*</abbr>
<% end %>
<% options_hash = Rails.env.production? ? {:autocomplete => 'off'} : {} %>
<%= text_field_tag "#{param_prefix}[number]", '', options_hash.merge(:id => 'card_number', :class => 'form-control required cardNumber', :size => 19, :maxlength => 19, :autocomplete => "off") %>
<span id="card_type" style="display:none;">
( <span id="looks_like" ><%= Spree.t(:card_type_is) %> <span id="type"></span></span>
<span id="unrecognized"><%= Spree.t(:unrecognized_card_type) %></span>
)
</span>
</p>
<div class="row">
<div class="col-md-8 field" data-hook="card_expiration">
<%= label_tag "card_expiry" do %>
<%= Spree.t(:expiration) %><abbr class="required" title="required">*</abbr>
<% end %>
<%= text_field_tag "#{param_prefix}[expiry]", '', :id => 'card_expiry', :class => "form-control required cardExpiry", :placeholder => "MM / YY" %>
</div>
<div class="col-md-4 field" data-hook="card_code">
<%= label_tag "card_code" do %>
<%= Spree.t(:card_code) %><abbr class="required" title="required">*</abbr>
<% end %>
<%= text_field_tag "#{param_prefix}[verification_value]", '', options_hash.merge(:id => 'card_code', :class => 'form-control required cardCode', :size => 5) %>
<%= link_to "(#{Spree.t(:what_is_this)})", spree.content_path('cvv'), :target => '_blank', "data-hook" => "cvv_link", :id => "cvv_link" %>
</div>
</div>
<%= hidden_field_tag "#{param_prefix}[cc_type]", '', :id => "cc_type", :class => 'ccType' %>
</div>
<% end %>
<%= #client_token = Braintree::ClientToken.generate %>
<script type="text/javascript">
braintree.setup("<%=#client_token%>", 'dropin', {
container: 'dropin'
});
</script>
I work at Braintree. If you don't specify the form option inside the call to braintree.setup, braintree.js will attach its behavior to the closest parent form element. Since it looks like the parent form of your braintree container is the same form used by the other checkout flows, braintree.js will indeed hijack the call made by the submit button (regardless of the payment flow being used). I recommend creating two separate form elements, and passing the id of the one used by braintree to the braintree.setup call.
braintree.setup("<%=#client_token%>", 'dropin', {
container: ‘dropin’,
form: ‘braintree_checkout'
});

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?

Categories

Resources