Validating fields on entry or embedding on submit with regex validation - javascript

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.

Related

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.

How to store course other than dropdown menu and open new textbox put other educations?

Model field - degree, institute, percentage these are the model field.
If course is other than dropdown menu so select "Other" and display textbox for enter user education. and when form submit i want to store education in degree column. but now i am not able to handle these two value.
education.html.erb file
<p>
<%= f.label :user_id, "Select User.*" %>
<% if params[:user_id] != nil %>
<%= f.select :user_id, :collection => User.where(:id => params[:user_id]).map{|u| ["#{u.firstname}, #{u.lastname}", u.id]} %>
<% else %>
<% #selected_user_id = EducationInformations.where(:id => params[:id]).pluck(:user_id).first %>
<%= f.select :user_id, :collection => User.where(:id => #selected_user_id).map{|u| ["#{u.firstname}, #{u.lastname}", u.id]} %>
<% end %>
</p>
<br/>
<% course = ["MCA","BCA","BSC","Engg","Diploma in computer science","Other"] %>
<p>
<%= f.label :degree, "Select Course.*" %>
<%= f.select :degree , :collection => (course) %>
</p>
<div id="other_edu">
<br/>
<p>
<%= f.label :other_degree, "Enter your course" %>
<%= f.text_field :other_degree , :id => "other_course", :onblur => "getCourse()" %>
</p>
</div>
<br/>
<p>
<%= f.label :institute, "Institute*" %>
<%= f.text_field :institute %>
</p>
<br/>
<p>
<%= f.label :percentage, "Grade/Percentage" %>
<%= f.text_field :percentage %>
</p>
javascript
$(document).ready(function() {
var select = document.getElementById('education_informations_degree');
var other_course = document.getElementById('other_course');
$('#other_edu').hide();
select.onchange = function() {
var selected_course = select.value;
if (selected_course == "Other")
{
$('#other_edu').show();
}else{
$('#other_edu').hide();
}
}
});
function getCourse() {
var x = document.getElementById("other_course");
var select = document.getElementById('education_informations_degree');
select.value = x.value;
console.log(x.value);
}
Model
class EducationInformations < ActiveRecord::Base
unloadable
attr_accessible :user_id, :degree, :institute, :passing_year, :country, :university, :percentage
validates :degree, presence: true
validates :passing_year, presence: true
validates :university, presence: true
validates :institute, presence: true
end
Controller
def create
#edu_info = EducationInformations.new(educational_params)
if #edu_info.save
#flash[:notice] = 'Vote saved.'
redirect_to #edu_info
else
render "new"
end
end
private
def educational_params
params.require(:education_informations).permit(:user_id, :degree, :institute, :passing_year, :country, :university, :percentage)
end
How I fixed this problem when user select value from dropdown list so I set value as textbox value. If I select "Other" item so display textbox and whatever user can enter so I send value of text. I know this is not best way but I think this solution handle my problem.
View code
<% course = ["MCA","BCA","BSC","Engg","Diploma in computer science","Other"] %>
<p>
<%= label_tag "select_degree", "Select Course *" %>
<%= select_tag "select_degree" , options_for_select(course) %>
</p>
<div id="other_edu">
<br/>
<p>
<%= f.label :degree, "Enter your course *" %>
<%= f.text_field :degree %>
</p>
</div>
<br/>
<p>
<%= f.label :institute, "Institute *" %>
<%= f.text_field :institute %>
</p>
<br/>
<p>
<%= f.label :percentage, "Grade/Percentage " %>
<%= f.text_field :percentage %>
</p>
Javascript
$(document).ready(function() {
var select = document.getElementById('select_degree');
var other_course = document.getElementById('education_informations_degree');
$('#other_edu').hide();
select.onchange = function() {
var selected_course = select.value;
if (selected_course == "Other")
{
$('#other_edu').show();
}else{
$('#other_edu').hide();
other_course.value = select.value;
}
}
});

Can't get flash or error messages to display on button submit

I have this form and I'm trying to submit the contents of the form to the model "Leeds" then display a success/failure message depending on if the data passes the model validations.
The issue I'm having is that when I click on the "Send Message" button, it takes me from Root to Root/leeds.
This is the form I'm using:
<%= form_for #leed, {url:root_path, html: {id:"contactForm", name:"sentMessage", novalidate:true}} do |leed| %>
<div class="row">
<div class="col-md-6">
<!-- Name -->
<div class="form-group">
<%= leed.text_field :name, class: "form-control", :placeholder => "Your name *", :required => true, :data => {:validation_required_message => 'Please enter your name.' } %>
<p class="help-block text-danger"></p>
</div>
<!-- Email -->
<div class="form-group">
<%= leed.email_field :email, class: "form-control", :placeholder => "Your email *", :required => true, :data => {:validation_required_message => 'Please enter your email address.' } %>
<p class="help-block text-danger"></p>
</div>
<!-- Phone -->
<div class="form-group">
<%= leed.telephone_field :phone, class: "form-control", :placeholder => "Your phone *", :required => true, :data => {:validation_required_message => 'Please enter your phone number.' } %>
<p class="help-block text-danger"></p>
</div>
</div>
<!-- Message -->
<div class="col-md-6">
<div class="form-group">
<%= leed.text_area :message, class: "form-control", :placeholder => "Your message *", :required => true, :data => {:validation_required_message => 'Please enter a message.' } %>
<p class="help-block text-danger"></p>
</div>
</div>
<div class="clearfix"></div>
<!-- Submit -->
<div class="col-lg-12 text-center">
<div id="success">
<%= render 'shared/error_messages' %>
</div>
<%= button_tag "Send Message", class: "btn btn-xl" %>
</div>
</div>
<% end %>
This is my routes.rb:
Rails.application.routes.draw do
root 'home#index'
post "/" => 'home#create'
end
This is the HomeController method I have:
def create
#leed = Leed.new(leed_params)
if #leed.save
#update page to reflect success
flash[:success] = "Thank you, we'll contact you as soon as possible"
else
#update page to flect failure
flash[:danger] = "There was an issue with the login attempt #{#leed.errors.full_messages.inspect}"
end
# redirect_to thank_you.html.erb
render nothing:true
end
At the end of your #create method you have render nothing: true. This means the post request will be submitted to /leads, but then the server won't tell the browser to go anywhere else, so the browser will stay at the /leads url. You can add a redirect at the end of your create action if you want the browser to be redirected to a different page after the post request is completed. Hope that helps!
Puhlze is right, you should be able to have the page redirect to itself where the Flash message should show up. You could also make the form remote: true and create a create.js.erb file that will popup a notification message without re-rendering the page; that's what we usually do when we are using AJAX submits.

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