Javascript/Jquery: setTimeout function not running AJAX query via anonymous function - javascript

I am working on a login page with some pretty animations. I would like to be able to pause the script while I run a custom animation after the user submits the login post. To simplify:
Behavior: user submits login --> load custom animation --> wait 5 seconds --> execute AJAX post --> present error or navigate to home
Here is my code in its most working form
function ValidateUser() {
var userid = $("#Username").attr('value');
var pass = $("#Password").attr('value');
var url = "/Account/ValidateUser";
var $this = $('.login'),
$state = $this.find('button > .state');
$this.addClass('loading');
$state.html('Authenticating');
setTimeout(function () {
$.ajax({
url: url,
data: { username: userid, password: pass },
cache: false,
type: "POST",
success: function (data) {
if (data == "1") {
$this.addClass('ok');
$state.html('Welcome back!');
window.location.href = "Home/Index";
} else {
$state.html('Incorrect username or password!');
$this.addClass('loginError');
$this.removeClass('ok loading');
}
$("#txtuserid").attr({ 'value': '' });
$("#txtpassword").attr({ 'value': '' });
},
error: function (reponse) {
alert(response);
$state.html('An unknown error has occurred!');
$this.addClass('loginError');
$this.removeClass('ok loading');
}
});
}, 5000);
}
After running it through firefox's javascript debugger I noticed that the ajax post is never actually run. I am developing in visual studio using C# and I place a breakpoint on the validate user method but it never hits the breakpoint.
Any help would be appreciated.
EDIT:
Here is the HTML I use to call the ValidateUser method.
<button onclick="ValidateUser()">
<i class="spinner"></i>
<span id="submit" class="state">Submit</span>
</button>

If the button is submitting the form you will have a problem.
A button without type="button" will submit - in some browsers actually submit to the page URL if no form
You likely want
$("#formID").on("submit",function (e) {
e.preventDefault();
var userid = $("#Username").attr('value');....

Related

specifying javascript function from button form

I'm using Ajax to display a comments widget on my site and am trying to upgrade from Recaptcha v2 to Recaptcha v3. So far it's gone well, comments successfully post, but instead of displaying the "thanks for submitting" modal, it just redirects to the form submission URL with the success data. This is not ideal.
The main change I made was to change the button code in my comment_form.html to this:
<button class="button g-recaptcha" id="comment-form-submit"
data-sitekey="{{ site.reCaptcha.siteKey }}"
data-callback='onSubmit'
data-action='submit'>
Submit
</button>
</form>
<script>
function onSubmit(token) {
document.getElementById("new-comment").submit();
}
</script>
(and added the id="new-comment" to the top of the form)
previously i had
<button class="button" id="comment-form-submit">Submit</button>
the relevant javascript code is:
(function ($) {
var $comments = $('.js-comments');
$('.js-form').submit(function () {
var form = this;
$("#comment-form-submit").html(
'<svg class="icon spin"><use xlink:href="#icon-loading"></use></svg> Sending...'
);
$(form).addClass('disabled');
$.ajax({
type: $(this).attr('method'),
url: $(this).attr('action'),
data: $(this).serialize(),
contentType: 'application/x-www-form-urlencoded',
success: function (data) {
showModal('Comment submitted', 'Thanks! Your comment is pending. It will appear when approved.');
$("#comment-form-submit")
.html("Submit");
$(form)[0].reset();
$(form).removeClass('disabled');
grecaptcha.reset();
},
error: function (err) {
console.log(err);
var ecode = (err.responseJSON || {}).errorCode || "unknown";
showModal('Error', 'An error occured.<br>[' + ecode + ']');
$("#comment-form-submit").html("Submit")
$(form).removeClass('disabled');
grecaptcha.reset();
}
});
return false;
});
I'm pretty sure it's like a one line change to make the Ajax process the reply, but I'm totally out of my depth with javascript, so any thoughts are greatly appreciated.
--
Edit: The other example I saw calls the onSubmit function from their callback but since I'm using this weird main.js I don't know how to reference $('.js-form').submit(function (event) { from onSubmit
The default browser behaviour after submitting a form is to redirect on success, try preventing this by calling preventDefault on the event, eg:
$('.js-form').submit(function (event) {
event.preventDefault();
// the rest of your code
});

CRUD - Add and Delete not working one after other if page is not refreshed

I have one annoying problem that I am not able to solve.
I am generating CRUD operations in my Symfony project. I made an AJAX request for Add method which works as it should.
After that I have created AJAX request for Delete method.
When I add my new entity object the table is reloaded without page refresh.
Problem is that if I click delete after it's added it throws an error that ID is not found.
/**
* #Route("/user/{id}", name="user_delete", options={"expose"=true})
*/
public function delete($id)
{
$em = $this->getDoctrine()->getManager();
$$user = $em->getRepository(User::class)
->findOneby(['id' => $id]);
if (!$user) {
throw $this->createNotFoundException('No User found for id '.$id);
}
$em->remove($user);
$em->flush();
return $this->json(["message" => "SUCCESS"]);
}
So, for example I have added entity with ID = 2 . DIV is reloaded. Now I click in delete of 2 and it's says:
No user found for id 1
Problem is it always fatches the last ID I deleted after page refresh.
Now, if I refresh the page and then try delete it will catch ID = 2 and delete it. Now, I add ID = 3 without refreshing the page and it will throw:
No user found for id 2
I think maybe it has to do with my add form:
Add form:
$('#form-submit').on('click', function (e) {
e.preventDefault();
$.ajax({
type: "POST",
url: '/subscription/add',
data: $('form#subscription-form').serialize(),
processData: false,
success: function () {
$("#user-table").load(location.href + " #user-table");
$('#addUser').modal('hide');
displayNotif('success', 'check', 'User created successfully');
},
error: function (xhr, status, error) {
var ErrorMessage = JSON.parse(xhr.responseText);
$('#general-error').html(ErrorMessage.message);
}
});
});
Can someone please help?
$(document).ready(function () {
$('.user_delete').on('click', function () {
let removeUrl = $(this).attr('data-remove-url');
$('.remove-user').attr('data-remove-url', removeUrl);
});
$(".remove-user").click(function (e) {
let removeUrl = $(this).attr('data-remove-url');
e.preventDefault();
$.ajax({
url: removeUrl,
type: 'DELETE',
success: function()
{
$("#user-table").load(location.href + " #user-table");
$('#confirmDelete').modal('hide');
displayNotif("danger", "warning", "User deleted successfully");
}
});
});
});
I am adding everything so you can get an idea of what I am doing:
<a href data-toggle="modal" data-target="#confirmDelete" data-remove-url="{{ path('user_delete', {'id':user.id}) }}" class="btn user_delete">x</a>
Option 1:
The click event is not working properly for the delete button.
Try to replace
$(".remove-user").click
With
$(".remove-user").on(“click”
Option 2:
data-remove-url
this attribute is not updated accordingly. Check your DOM to verify

NO refresh the page when success ajax

I have a ajax section to submit data in laravel. I want if I submit success then don't reload the page and submit the error then reload the page. In the code below, when the error reloads the page correctly, I am having a problem in the success case, the page must not be reloaded, but the result is reloaded. I have added the line e.preventDefault () then true in the success case but wrong in the error case
$(document).ready(function() {
$('form').submit(function(e){
//e.preventDefault();
var form_data = $(this).serialize();
$.ajax({
url:'{{ route('contracts.store') }}',
method: "POST",
data: form_data,
dataType: "json",
success: function(data) {
$("#mgsContract").text("Add successfully");
$("#hideForm").css("visibility", "visible");
$("#hideForm").css("height", "auto");
$("#result-contract-id").val(data.contract_obj);
},
error: function(data) {
$("#mgsContract").text("Something wrong");
}
})
});
});
Add back that e.preventDefault() to prevent the form submission, and in the error case, call location.reload(). (Or if you want to submit the form conventionally in the error case, use e.target.submit(); instead. Since that's calling submit on the DOM element [not a jQuery wrapper], it won't call your submit handler again. [This is one of the differences between programmatically calling submit on a DOM element vs. calling it on a jQuery object.])
when you use ajax, laravel automatically responds in JSON for validation errors. therefore to access the validation errors you can use this.responseJSON.errors in error section of your ajax. there is no need to reload the page to access validation errors.
however in any case if you need to reload or go to specific location you can use window.location
window.location.href = "an address"; // going to specific location
window.location.reload(); //reloading the page
an ajax example is the following, in which a loop for showing all errors inside the form is specified.
$("#form_id").submit(function (e) {
e.preventDefault(); // avoid to execute the actual submit of the form.
var form = $(this);
var url = form.attr('action');
$.ajax({
method: "POST",
url: url,
data: form.serialize(), // serializes the form's elements.
success: function (data) {
// code in the case of success
},
error: function (err) {
if (err.status == 422) { // when status code is 422, it's a validation issue
// code in the case of error
console.log(err.responseJSON);
// you can loop through the errors object and show it to the user
console.warn(err.responseJSON.errors);
// display errors on each form field
$.each(err.responseJSON.errors, function (i, error) {
var el = $(document).find('[name="' + i + '"]');
el.removeClass('is-valid');
el.addClass('is-invalid');
var parent = el.parents('.form-group');
parent.append("<small class='error-message text-right text-danger d-block pr-5 ' role='alert'>" + error + "</small >");
});
}
},
});
});

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.

Button callback function running every page load

I have a button:
<span id="signinButton">
<span
class="g-signin"
data-callback="onSignInCallback"
data-clientid="CLIENT_ID"
data-cookiepolicy="single_host_origin"
data-requestvisibleactions="http://schemas.google.com/AddActivity"
data-scope="https://www.googleapis.com/auth/plus.login">
</span>
</span>
When pressed, this runs a function... which at the moment goes off, makes an AJAX post, and prints some text back in the console (just to test, this part works):
<script type="text/javascript">
var helper = (function() {
return {
onSignInCallback: function(data) {
var dataString = 'access_token=' + data['access_token'];
$.ajax({
type: "POST",
url: "getdetails",
data: dataString,
dataType: 'html',
timeout: 0,
statusCode: {
200: function(data){
console.log(data);
},
error: function(data){
console.log("There was an error");
}
}
});
}
};
})();
function onSignInCallback(data) {
helper.onSignInCallback(data);
}
</script>
However, the issue is that every time I refresh the page without clicking the button, my function runs and the data is posted via AJAX and the text gets printed into the console.
Any idea why this is happening? I want it (obviously) so this only happens when they click the button.
I'm working with the Google Plus API, code modified from:
https://github.com/googleplus/gplus-quickstart-javascript/blob/master/index.html#L44
Per the documentation for that directive:
data-callback - A function in the global namespace, which is called when the sign-in button is rendered and also called after a sign-in flow completes. When the button is rendered the callback occurs to check whether or not the user previously authorized the app and should be automatically signed in.
By design the callback will run when the button is rendered (i.e. page loads) and also when the button is clicked.
A workaround would be to set a global boolean on the first run.
<script type="text/javascript">
var first_run = true;
var helper = (function() {
return {
onSignInCallback: function(data) {
var dataString = 'access_token=' + data['access_token'];
$.ajax({
type: "POST",
url: "getdetails",
data: dataString,
dataType: 'html',
timeout: 0,
statusCode: {
200: function(data){
console.log(data);
},
error: function(data){
console.log("There was an error");
}
}
});
}
};
})();
function onSignInCallback(data) {
if(!first_run) {
helper.onSignInCallback(data);
}
first_run = false;
}
</script>
In the Google Plus documentation:
If the user previously agreed to allow your application access through this button, or another button representing the same application, they are automatically logged in. The callback function is called automatically as soon as the sign-in button is rendered and passed a new authorization object with an access token.
I was getting this as well. On my global onSignInCallBack(authResult) function, I enclosed the call that makes the ajax request in an if statement that checks for a value in authResult['access_token']. I'm using AngularJs and moved my Ajax call into my controller. Since you are not using AngularJS, you can replace the gplusController().onSignInCallback(..) line with your AJAX call.
function onSignInCallback(authResult){
if (authResult['access_token']) {
var afToken = document.getElementById('afToken').getAttribute('data-afToken');
gplusController().onSignInCallback(authResult, afToken);
}
}

Categories

Resources