Rails, AJAX form validation - javascript

I am new to jQuery, AJAX, and javascript in general, and I am trying to do some front end validation for a rails form that uses an ajax call to have the server run a query. It seems to work well, if I am in the debugger (since the AJAX call has enough time to return and stop the submission of the form), but it wont work all of the time when I am just testing it without the debugger. I believe this happens because after the ajax call, the javascript validation method exits, and the form submits. Here is my javascript method
$('#runner-job-submit').click(function(e) {
runnerJobValidation(e);
});
function runnerJobValidation(e) {
var user_login = $('#user_login').val();
var name = $('#name').val();
var location = $('#location').val();
var description = $('#description').val();
var user_exists;
//AJAX call to check if user exists in the database
$.post("/jobs/user_exists", {user_login: user_login}, function (response) {
if(response == "false") {
$('#runner-new-job-errors').html('');
e.preventDefault();
$('#runner-new-job-errors').append('<small style="color:red"> User doesnt exist </small>');
}
});
if(user_login == "" || name == "" || location == "" || description == "") {
$('#runner-new-job-errors').html('');
e.preventDefault();
$('#runner-new-job-errors').append('<small style="color:red"> Please fill out all fields </small>');
}
}
And here is my controller action url it is hitting
def user_exists?
user_login = params[:user_login]
user = User.where("login = ?", user_login).first
user_exists = user.present?
respond_to do |format|
format.js { render :json => user_exists.to_json}
format.html { redirect_to jobs_path }
end
end
Can someone please tell me the correct way to do this. I feel the solution is to somehow prevent runnerJobValidation() from exiting before response is received from the server, but I just dont know how to do this.

You are trying to make an synchronous ajax request. In short, you can do it by set async in ajax object to false.
You can found your solution here : How to make JQuery-AJAX request synchronous.
Hope this help.

You can user jQuery validation plugin like http://jqueryvalidation.org/
For validation you should add new validation method http://jqueryvalidation.org/jQuery.validator.addMethod/
Something like this:
jQuery.validator.addMethod("user_exists", function(value, element, param) {
var isSuccess = false;
isSuccess = $.ajax(type: "POST", url: "/jobs/user_exists", data: {user_login: user_login}, dataType: "json").responseText == "false" ? false : true;
return isSuccess;
}, jQuery.format("User already exists!"));
And for form submit:
$("#myform").validate({
submitHandler: function(form) {
// some other code
// maybe disabling submit button
// then:
$(form).submit();
}
});
About how to properly use plugin read docs at http://validation.bassistance.de/documentation/

Related

Syntax error, unrecognized expression on ajax call

I am working on a project where i have an issue with the commenting function i've made. Whenever i comment and use special characters the console displays this error: syntax error, unrecognized expression. Furthermore the request goes through and my backend (PHP) inserts the data to the DB but i then have to refresh to get the updated version of the post with that new comment. I can't figure out why even after a couple of searches here on stack and i could really use a new pair of eyes on the code.
I figure that the backend isn't the issue which is why it's left out of this post. Furthermore the form just contains a text input and a submit button. It might be important to mention that i use jQuery v3.3.1.
Finally when the form is submitted an ajax call gets triggered. Here it is:
var newComment;
$(document).on("submit", "form[data-comment]", function(e){
e.preventDefault();
var where = $(this);
var updateThis = $(where).parent().parent();
var data = $(where).attr("data-comment").split(",");
var comment = $(where).find("input[name='commenter']").val().toString();// <= this might be the issue?
if (data[0] == 1){
if (data[1] != "" && data[2] != "" && data[3] != ""){
//insert comment via ajax and return post and insert post
if (newComment){ <= prevent firing until newComment = false
newComment.abort();
return false;
}
$(where).find("input[type='submit']").prop("disabled", true);
$(where).find("input[type='submit']").val("commenting...");
newComment = $.ajax({
url: "mypage/core/AjaxRequests.php", <= call to php handler
type: "POST",
data: { type: "15", data: data, comment: comment }
});
$(comment).val("");
newComment.done(function(response, textStatus, jqXHR){
newComment = false;
$(where).find("input[type='submit']").prop("disabled", false);
$(where).find("input[type='submit']").val("Comment");
if (response.length > 200){
$(updateThis).parent().fadeTo(0,0);
$(updateThis).parent().prop('outerHTML', response);
$(updateThis).parent().fadeTo(1,1);
}
});
}
}
});

My jQuery working but callback is not working on the first time

I am working on a simple project to learn jQuery. My problem is after clicking the button, I call a jquery. It works and carries data to the controller but success function is not working at first click. It works on the second click properly. With my parameters, in these two calls, the method in controller returns true. but at first call, jquery does not running in the success function, but second call does.
Here is my jquery:
function signin() {
var parameters = {
email: $('#emailtxt').val(),
password: $('#passwordtxt').val()
};
console.log(parameters);
$.ajax({
url: '#Url.Action("Login","Session")',
type: 'GET',
data: parameters,
dataType: 'json',
success: function (correctData) {
if (JSON.parse(correctData) == false) {
alert("Incorrect e-mail or password.");
} else if (JSON.parse(correctData) == true) {
window.location.assign('#Url.Action("Index","Home")');
}
}
});
};
Here is my codes in controller:
public JsonResult Login(string email, string password)
{
using (var context= new ProjistDbContext())
{
var user = context.Users.FirstOrDefault(x => x.UserEmail == email && x.UserPassword == password);
if (user == null)
{
var result = JsonConvert.SerializeObject(false);
return Json(result, JsonRequestBehavior.AllowGet);
}
else
{
Session["UserId"] = user.Id;
var result = JsonConvert.SerializeObject(true);
return Json(result, JsonRequestBehavior.AllowGet);
}
}
}
I kindly ask for your help in this issue. Thank you so much.
I solved my problem and I wanted to share it. The problem was caused because of that...
I was adding button like;
<button>...</button>
This kind of definition was refreshing page and it was causing error while getting response from controller. It also gave error sometimes like
XHR failed loading GET...
If I add type="button" to html button definition, it stops to refresh page and all posts and responses works good.
I would like to share the solution. Thank you all for your assistance.

Google reCAPTCHA reset multiple captchas rendered by function call

I have many reCAPTCHA's who are rendered dynamically, sometimes there are 2 sometimes 50 depends on page.
I've done rendering with this:
<script src="https://www.google.com/recaptcha/api.js?onload=CaptchaCallback&render=explicit" async defer></script>
var CaptchaCallback = function(){
$('.g-recaptcha').each(function(index, el) {
grecaptcha.render(el, {'sitekey' : 'myKey'});
});
};
And placed this where I want captcha to be displayed:
<div class="g-recaptcha" data-sitekey="myKey"></div>
I've got ajax call, that submits form data to process.php, and if form data isn't verified returns custom errors
$.ajax({
type : 'POST',
url : 'process.php',
data : $(this).serialize(),
dataType : 'json'
})
.done(function(data) {
if ( ! data.success) { ...
It works as intended, but now I want to show message to user as part of validation, if he forgot to solve captcha.
With
var response = grecaptcha.getResponse();
if(response.length == 0){
$('.result').append('Captcha incorrect, please click I am not robot');
}
and to reset captcha add this bellow
if ( ! data.success) {
grecaptcha.reset();
What does it do is: reset captcha if user didn't completed all forms valid.
This all works only on 1st occurrence of reCAPTCHA.
And I need it to somehow tell it to reset only captcha that is currently in use.
My best guess was to try with
var form = $(this); //get current form
grecaptcha.reset(form);
It won't work, since i need widget ID, and not form.
Can you assist me pls?
All credits to https://stackoverflow.com/a/41860070/7327467
reset is done with
var form = $(this); //store current form
var response = grecaptcha.getResponse(jQuery(form).find('#data-widget-id').attr('data-widget-id'));
if(response.length == 0){ //append error to result div
form.find('.result').append('<div class="alert alert-danger">' + "Captcha incorrect" + '</div>'); }
and to reset recaptcha, I've added this instead previous "grecaptcha.reset();"
grecaptcha.reset(jQuery(form).find('#data-widget-id').attr('data-widget-id'));
Hope this helps.

submit form with ajax validation jquery / standard javascript

I'll start with an apology - I'm a .NET coder with little (no) front-end experience.
When the user clicks on Submit, the form needs to call a REST service, if the service returns true then the user is presented with a warning that a duplicate exists and are asked whether they want to continue. Appreciate any help.
I have the Submit button ONCLICK wired up to Approve()
When the checkForDuplicateInvoice() gets called, it passes the control back to the calling function right away before the ajax call has a chance to get the result. The effect is that the Validate() function finishes without taking into account whether or not a duplicate invoice exists.
I need help in modifying the form so that when the user clicks on the submit button, the form validates (including the ajax call to the db) before finally submitting.
I've modified the code based on Jasen's feedback.
I'm including https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js in my header.
The error I get now is "Object doesn't support property or method 'button'"
What I have now for my form submission/validation is:
$(document).ready(function () {
$("#process").button().click( function () {
if (ValidateFields()) { // internal validation
var companyCode = document.getElementById("_1_1_21_1").value;
var invoiceNo = document.getElementById("_1_1_25_1").value;
var vendorNo = document.getElementById("_1_1_24_1").value;
if (vendorNo == "undefined" || invoiceNo == "undefined" || companyCode == "undefined") {
return false;
}
$.ajax({ // external validation
type: "GET",
contentType: "application/json;charset=utf-8",
//context: $form,
async: false,
dataType: "jsonp",
crossDomain: true,
cache: true,
url: "http://cdmstage.domain.com/services/rest/restservice.svc/CheckDuplicateInvoice?InvoiceNumber=" + invoiceNo + "&VendorNumber=" + vendorNo + "&CompanyCode=" + companyCode,
success: function (data) {
var result = data;
var exists = result.CheckForInvoiceDuplicateResult.InvoiceExists;
var valid = false;
if (exists) {
if (confirm('Duplicate Invoice Found! Click OK to override or Cancel to return to the form.')) {
valid = true;
}
}
else {
valid = true; // no duplicate found - form is valid
}
if (valid) {
document.getElementById("_1_1_20_1").value = "Approve";
doFormSubmit(document.myForm);
}
},
error: function (xhr) {
alert(xhr.responseText);
}
});
}
});
});
First review How do I return the response from an asynchronous call? Understand why you can't return a value from the ajax callback functions.
Next, disassociate the submit button from the form to prevent it from performing default submission. Test it to see it does nothing.
<form>
...
<button type="button" id="process" />
</form>
Then wire it up to make your validation request
$("#process").on("click", function() {
if (valid()) {
$(this).prop("disabled", true); // disable the button to prevent extra user clicks
// make ajax server-side validation request
}
});
Then you can make your AJAX request truly asynchronous.
$.ajax({
async: true,
...,
success: function(result) {
if (exists) {
// return true; // returning a value is futile
// make ajax AddInvoice call
}
}
});
Pseudo-code for this process
if (client-side is valid) {
server-side validation: {
on response: if (server-side is valid) {
AddInvoice: {
on response: if (successful) {
form.submit()
}
}
}
}
}
In the callback for the server-side validation you make the AddInvoice request.
In the callback for AddInvoice you call your form.submit().
In this way you nest ajax calls and wait for each response. If any fail, make the appropriate UI prompt and re-enable the button. Otherwise, you don't automatically submit the form until both ajax calls succeed and you call submit() programmatically.

Use jScript / AJAX to call PHP script but ONLY if form has been submitted?

This is kind of a follow up to this question.
I have this code:
var chpass = function()
{
var pass1 = encodeURIComponent($("#pass1").val());
var pass2 = encodeURIComponent($("#pass2").val());
$.ajax(
{
type: "POST",
url: "lib_ajax/somescript.php",
data: "pass1="+ pass1+"&pass2="+ pass2,
success: function(msg_pass)
{
$("#status_pass").ajaxComplete(function(event, request, settings)
{
if(msg_pass == 'empty pass1')
{
$("#pass1").removeClass('green');
$("#pass1").addClass("red");
}
});
}
});
}
$("#signup").ready(chpass);
$("#signup").change(chpass);
And in the php script:
$pass1 = trim($_POST['pass1']);
if(!isset($pass1)||empty($pass1)) die('empty pass1');
My problem is that I don't want the form to be validated with ready() the first time the page is loaded but every time the page is loaded after a submit.
I have tried to figure out how to set a default event for the handler and then use preventDefault but I've been completely unsuccessful so far.
Could part of the problem be that when the page is submitted some additional validation happens on the server and in some cases I use header('Location: ') to reload the page?
Any tips how I can work this out? Is there a way to change it to something like:
if ( FORM IS SUBMITED ) $("#signup").ready(chpass);
Or maybe:
if ( FORM IS SUBMITED && msg_pass == 'empty pass1')
{
$("#pass1").removeClass('green');
$("#pass1").addClass("red");
}
Can also add that I have tried to change ready() to submit() with no luck:
$("#signup").submit(chpass); // DO NOT WORK
I finally found a solution. Change the code:
$("#signup").ready(chpass);
to:
<?php if(isset($_POST['submit'])) { ?>$("#signup").ready(chpass);<?php } ?>
and that part of the jScript is left out unless the form is submitted!

Categories

Resources