Validation before saving Rails - javascript

I would like to carry out a validation before saving by determining if a User has filled in a particular field, the Payment amount field below and chosen status = "Closed" before submitting the form. If he does one without the other then the form should not save
Edit page
<%= simple_form_for #invoice, :html => { :class => 'form-horizontal' } do |f| %>
<%= render "shared/error_messages", :target => #invoice %>
<%= f.association :customer, disabled: #invoice.persisted? %>
<%= f.input :due_date, as: :string, input_html: { class: "datepicker" }, disabled: #invoice.persisted? %>
<%= f.input :invoice_date, as: :string, input_html: { class: "datepicker" }, disabled: #invoice.persisted? %>
<%= f.input :payment_method, as: :select, :collection => [['Cash','Cash'],['Cheque','Cheque'],['In-House transfer','In-House transfer'],['Account Ledger','Account ledger']], :selected => ['Cash','Cash'] %>
<%= f.input :reference_no, :label => 'Payment Reference No', as: :string %>
<%= f.input :amount, as: :string %>
<%= f.input :payment_date, as: :string, input_html: {class: "datepicker"} %>
<%= f.input :status, as: :select, collection: Invoice::VALID_STATUS %>
VALID_STATUS = [ 'Draft', 'Open', 'Closed', 'Void' ] in Invoice.rb
I would like that if the user changes the Status to Closed he should have entered an amount in the form. A user should not be able to change status to closed without entering an amount

In the model (app/models/invoice_model.rb) put
validate :close_must_have_amount
Then define it (same file)
def close_must_have_amount
:status == 'closed' && :amount # May need to tweak this
end
To have the model level validations applied client side you can use
https://github.com/bcardarella/client_side_validations/

1) Javascript Form Validation is generally done by names.
function ValidateForm(){
var form = document.forms['myForm'];
if ((form['status'].value == "Closed") && !(form['amount'].value)){
alert("You gave a 'Closed' status value, but did not provide an amount, please rectify this problem!");
return(false);
} else {
return(true);
}
}
And then:
<%= simple_form_for #invoice, :onsubmit => "ValidateForm();", :html => { :class => 'form-horizontal', :name => 'myForm' } do |f| %>
<%= f.input :amount, :html => { :name => 'amount'}, as: :string %>
<%= f.input :status, as: :select, :html => { :name => 'status'}, collection: Invoice::VALID_STATUS %>
A brief walkthrough onSubmit triggers when a form is submitted, but before it is actually posted to the server.
A javascrtipt function that is trigered by an event and terminates with return(false); will immediately terminate the event, while return(true); (or pretty much anything else really) makes the event continue as planned.
Finally, be aware that relying exclusively on client side validation is a terrible idea, as a determined user could do something like:
1) Make a perfectly legitimate submission with firebug open and inspect the headers etc.
2) Craft their own HTTP request containing bogus/bad data.
3) Submit it through any one of the myriad HTTP tools.
Clientside Validation is a "nice to have".
Serverside Validation is a "must have".

If you want to do it in client side:
<script>
$(document).ready(function(){
$('#status').change(function(){
if($(this).val() == "Closed" && ($('#amount').val() == null || $('#amount') == "")){
alert("Amount must be needed when status is closed")
}
});
});
</script>

Related

Rails - How to submit a form without changing the page and updating the view?

Hello all !
Im using rails and in the steps I would like the user to (on the same page) :
Enter his address
Filling the form
Submit the form
Click to submit
Update the view to show the address
The view updated
Should I use Stimulis or Ajax? I don’t quite understand which would be more useful!
Because i try to use simply JS but it’s was not DRY and not really simple:
// file.js
document.querySelector(".form").addEventListener('submit', function () {
adress_form = document.querySelector(".adress_form");
adress_form.style.display="none";
document.location.reload();
display_adress = document.querySelector(".display_adress");
display_adress.style.display = "block";
});
#file.html.erb
<div class="display_adress">
<% if current_user.line1? && current_user.postal_code? && current_user.city? %>
<p>Mon adresse actuel : <%= current_user.line1 %>, <%= current_user.city %> <%= current_user.postal_code %></p>
<% end %>
</div>
<div class="address_form">
<%= simple_form_for(current_user, remote: true, html: { id: "addddd"}) do |f| %>
<%= f.input :line1, label: 'Mon adresse' %>
<%= f.input :city, label: 'Ville' %>
<%= f.input :postal_code, label: 'Code Postal' %>
<%= f.submit %>
<% end %>
</div>
To resume, i want the user to enter his address on the form, to submit, to update my database and to update the view with the new address the user submitted
Thanks for helping!
You can respond in the controller javascript. For example:
file.html.erb
<%= simple_form_for(current_user, remote: true, format: :js, html: { id: "addddd"}) do |f| %>
users_controller.rb
def create
# do your business logic
render 'create
end
users/create.js.erb
document.getElementById("formId").innerText = "Othe html text or you can call render(*)"

How can i change checkbox in rails?

How can i set a check box to true or false.. I have tried all of these combinations:
<%= check_box_tag 'prefs[can_be_email_notified]', :id => 'user_preferences_can_email'%> Email
<%= check_box_tag 'prefs[can_be_email_notified]', '', :id => 'user_preferences_can_email'%> Email
<%= check_box_tag 'prefs[can_be_email_notified]', '', :checked =>'',:id => 'user_preferences_can_email'%> Email
tried to change the checkbox with these
document.getElementById("user_preferences_can_email").checked = true;
document.getElementById("user_preferences_can_email").value = true;
document.getElementById("user_preferences_can_email").checked.value = true;
Maybe i wasnt clear...
I have a set of values that are set to buttons and want to change the checkbox's to be checked or unchecked detirmed on the value set on the the button,
ie:
function doubleClickUser(can_email, can_screen) {
document.getElementById("user_preferences_can_email").checked = can_email;
document.getElementById("user_preferences_can_screen").checked = can_screen;
}
<button class="button" onclick="doubleClickUser('true','false')"><%= user[:email] %></button>
<%= check_box_tag 'prefs[can_be_email_notified]', :id => 'user_preferences_can_email'%> Email
<%= check_box_tag 'prefs[can_be_screen_notified]', :id => 'user_preferences_can_screen' %> Screen
Set the field's value in your controller or model, then simply include the element in the standard Rails form:
# controller
#pref = Pref.new (or Pref.find(params[:id])
# view
<%= form_for #pref do |f| %>
<%= f.label :can_be_email_notified %>
<%= f.check_box :can_be_email_notified %>
<% end %>
This will reflect whatever value of can_be_email_notified #pref has.
If you want to be checked try this:
EMAIL
<%= check_box_tag "email",params[:email].to_s , {:checked => true} %>
Also if you want to assing a value you can try this:
<%= check_box_tag "email", "5", params[:email].to_s == "5", {:checked => true} %>
Figured it out you have to set the status to false first
<%= check_box_tag 'prefs[can_be_email_notified]', '', false, :id => 'user_preferences_can_email' %> Email <br>
<%= check_box_tag 'prefs[can_be_screen_notified]', '', false, :id => 'user_preferences_can_screen' %> Screen <br>
<%= check_box_tag 'prefs[can_be_sms_notified]', '', false, :id => 'user_preferences_can_sms' %> Text </div></th>

Rails 3.2 - Ajax call when text field changes

I have a Rails 3.2.13 app with some Ajax on forms and links, using the remote parameter.
The problem is that i can't find in the docs how to do the same with text fields - the
remote parameter didn't work, so i think it's not supported on input objects.
I'd like to do bind 'ajax:xxx' events (like 'ajax:success') on my text_field objects.
I this even possible with UJS? If not, what my options are?
Here's some code:
<%= form_for #post, :html => {:class => 'form-horizontal'} do |f| %>
<div class = 'control-group'>
<%= f.label :title, :html => {:class => 'control-label'} %>
<%= f.text_field :title, :placeholder => 'Title', :class => 'input-xxlarge' %>
</div>
<div class = 'control-group'>
<%= f.label :body, :html => {:class => 'control-label'} %>
<%= f.text_area :body, :placeholder => 'Your post here', :class => 'input-xxlarge',
:rows => 15 %>
</div>
<div class = 'control-group'>
<%= f.label :tags, :html => {:class => 'control-label'} %>
<%= f.text_field :tags, :placeholder => 'Tags separeted by ,', :class => 'input-xxlarge',
:value => '' %>
</div>
<%= f.submit 'Create', :class => 'btn btn-primary'%>
Thanks!
I would bind a change or blur event to the input, and then make the Ajax call manually on your javascript/coffecript file.
posts.js
$('#post_title').change(function() {
// Do your stuff, instantiate variables, etc...
$.ajax({
type: post_or_get,
url: your_url,
data: your_data,
success: function(data) {
// Handle stuff after hitting the server here
},
error: function(data) {
}
});
});

Problems charging a card with Stripe in my Rails app

I'm building a Rails app that takes credit cards and I'm trying to use Stripe to do it. I'm having some issues passing the data from my app to Stripe in order to charge. That's what I'm hoping to get help with on this topic.
First, I have a standard form (with values instead of placeholders for quick submitting for testing purposes). The form successfully enters the name and email into the DB and the customer's "plan" is hardcoded in the controller for the time being:
<%= form_for #customer do |f| %>
<div class="payment-errors"></div>
<div class="name field">
<%= f.label :name %>
<%= f.text_field :name, :value => "Your name" %>
</div>
<div class="email field">
<%= f.label :email %>
<%= f.text_field :email, :value => "yourname#example.com" %>
</div>
<div class="cc_number field">
<%= label_tag 'cc_number' %>
<%= text_field_tag 'cc_number', nil, :value => "4242424242424242" %>
</div>
<div class="ccv field">
<%= label_tag 'ccv' %>
<%= text_field_tag 'ccv', nil, :value => "123" %>
</div>
<div class="cc_expiration field">
<%= label_tag 'cc_month', "Expiration date" %>
<%= text_field_tag 'cc_month', nil, :value => "12" %>
<%= text_field_tag 'cc_year', nil, :value => "2012" %>
</div>
<div class="actions">
<%= f.submit "Continue", :class => 'btn' %>
</div>
<% end %>
Also in my signups_view where the above code is, I have this JS, mostly provided by Stripe:
<script type="text/javascript">
// this identifies your website in the createToken call below
Stripe.setPublishableKey('<%= STRIPE['public'] %>');
function stripeResponseHandler(status, response) {
if (response.error) {
// show the errors on the form
$(".payment-errors").text(response.error.message);
$("input[type=submit]").removeAttr("disabled");
} else {
var form$ = $("form");
// token contains id, last4, and card type
var token = response['id'];
// insert the token into the form so it gets submitted to the server
form$.append("<input type='hidden' name='customer[stripe_token]' id='stripeToken' value='" + token + "'/>");
// and submit
$('.cc_number.field, .ccv.field, .cc_expiration.field').remove();
form$.get(0).submit();
}
}
$(document).ready(function() {
$("form").submit(function(event) {
// disable the submit button to prevent repeated clicks
$('input[type=submit]').attr("disabled", "disabled");
Stripe.createToken({
number: $('#cc_number').val(),
cvc: $('#ccv').val(),
exp_month: $('#cc_month').val(),
exp_year: $('#cc_year').val()
}, stripeResponseHandler);
// prevent the form from submitting with the default action
return false;
});
});
</script>
There seems to be a problem with the line form$.append("<input type='hidden' name='customer[stripe_token]' id='stripeToken' value='" + token + "'/>");, as my Ruby app breaks when it gets to customer[stripe_token].
Finally, in my `customers_controller`, I have:
def create
#customer = Customer.new(params[:customer])
#customer.product =
if #customer.save
save_order
redirect_to #customer
else
render action: 'new'
end
def save_order
Stripe.api_key = STRIPE['secret']
charge = Stripe::Charge.create(
:amount => 20,
:currency => "usd",
:card => #customer.stripe_token,
:description => "Product 1"
)
end
Whenever I submit the form, it hits the else clause in the controller each time and after plenty of debugging, Googling around and stripping out this from and rebuilding from scratch, I'm still stumped.
Any help would be very very much appreciated.
Edit: Added the customer model
attr_accessible :name, :email, :stripe_token, :product
email_regex = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :email, :presence => true,
:format => { :with => email_regex },
:length => { :minimum => 6, :maximum => 60 },
:uniqueness => { :case_sensitive => false }
validates :name, :length => {:minimum => 2, :maximum => 80 }
It would help to see your Customer model to get an idea of what's going on. If #customer.save returns false, it means that a validator is likely failing.
Also, do you have stripe_token as an accessible attribute on your model? Otherwise you won't be able to assign it form the form like you're doing. Note that the token should not be stored in the database, since it can only be used once.
class Customer
attr_accessor :stripe_token # do you have this?
end
One more note: you will probably want to store a Stripe ID field so that you can retrieve customer payments and cancel their account later.

Calling a JavaScript function during onchange of a select box

In my view, I have the following:
<%= select("event", :event_id, events_ids_titles_hash, { :include_blank => true, :onchange => "alert_me_test()" }) %>
alert_me_test() is:
<script type="text/javascript">
function alert_me_test()
{
alert ("this is a test")
}
</script>
The dropdown is appearing fine, but when I select from it, nothing happens. I'm expecting an alert box with "this is a test" in it.
The Edit case:
When I'm doing an edit, I have the following code:
<% if #panel.event_id %>
<%= select("panel", :event_id, events_ids_titles_hash, {:selected => #panel.event_id}, { :include_blank => true}) %>
My IDE (RubyMine) does not want to accept the "onchange" as an additional argument, and putting it inside one of the :selected or :include_blank argument hashes does not produce an error, but it does not work either
What ended up working for both new and edit:
<% if #panel.event_id %>
<%= 'Event is ' + events_ids_titles_hash.key(#panel.event_id) %>
<%= select("panel", :event_id, events_ids_titles_hash, {:selected => #panel.event_id}, { :include_blank => true, :onchange => "alert_me_test()"}) %>
<% else %>
<%= 'Select Event from list' %>
<%= select("event", :event_id, events_ids_titles_hash, { :include_blank => true }, { :onchange => "alert_me_test()" }) %>
<% end %>
<%= select("event", :event_id, events_ids_titles_hash, { :include_blank => true, :onchange => "alert_me_test()" }) %>
Worked for me, but I must say that you are fighting against the current with this one. Rails follows UJS, which means your even handlers should be separate from your HTML. In this case the select would be the same minus the onclick and then the script would be
<script type="text/javascript">
$('select').change(alert_me_test);
function alert_me_test(){
...
}
</script>
You don't have to do things this way, but it makes it clearer when looking at a script where your event calls are coming from.
I believe you need to set the :onchange as an HtmlOption, which is a 4th parameter:
<%= select("event", :event_id, events_ids_titles_hash, { :include_blank => true}, {:onchange => "alert_me_test()" }) %>

Categories

Resources