I have a form in modal as follows:
<!-- Modal -->
<div class="modal fade" id="myModal" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Modal Header</h4>
</div>
<form id="Myform" action="/action_page.php" method="get">
First name: <input type="text" name="fname"><br>
Last name: <input type="text" name="lname"><br>
<input type="button" onclick="submitform()" value="Submit">
</form>
</div>
</div>
</div>
Javascript
function submitform() {
//try
//event.stopImmediatePropagation();
//event.stopPropagation();
//check validate is valid
if (formValid) {
$("#Myform").trigger("submit");
}
}
$("#Myform").submit(function (e) {
e.preventDefault();
// e.stopImmediatePropagation();
$.ajax({
type: this.method,
cache: false,
url: this.action,
enctype: 'multipart/form-data',
data: new FormData(this),
processData: false,
contentType: false,
success: function (data) {
$('#create-media').modal('toggle');
}
},
error: function (error) {
console.log(error);
}
});
});
Currently, when the user click on the submit button, the data will be sent to the server to process, during the time waiting for the results returned, the modal has not been closed, the user can click to submit more times. I do not want this to happen.
I want to prevent users submitting continuously, do not allow users to click on the second submit button, the user must wait for the results returned, if successful, the modal will be closed.
I was thinking of disabling the submit button, but that's not safe, because the user can enable that button because of javascript on the user machine.
I tried using event.stoppropagation () and event.stopimmediatepropagation () but it did not work.
Am I doing something wrong? How do I prevent users from submitting continuously?
Thanks AlL
Follwing CertainPerformance idea, I would suggest you use a variable. However, instead of placing the variable at the beginning of the code, I would suggest to use the beforeSend callback provided by Ajax, it will be called right before sending the request.
var isBusy = false;
$("#Myform").submit(function (e) {
e.preventDefault();
if(isBusy) {
return;
}
$.ajax({
type: this.method,
cache: false,
url: this.action,
enctype: 'multipart/form-data',
data: new FormData(this),
processData: false,
contentType: false,
beforeSend: function(xhr) {
isBusy = true;
},
success: function (data) {
$('#create-media').modal('toggle');
isBusy = false;
},
error: function (error) {
console.log(error);
isBusy = false;
}
});
});
You can learn more about the beforeSend callback here
P.S. You could also use the $.ajax.active variable, which returns the amount of active ajax request, this might be a more elegent method.
Give your submitform function a persistent alreadySubmitted variable. Also, try attaching the button handler from Javascript instead of HTML, and preventDefault:
const submitform = (() => {
let alreadySubmitted = false;
return (e) => {
e.preventDefault();
if (alreadySubmitted) return;
alreadySubmitted = true;
if (formValid) {
$("#Myform").trigger("submit");
}
}
})();
document.querySelector('#Myform input[type="button"]').addEventListener('click', submitForm);
Related
I am trying to submit a form using jquery. I am running a Django server.
The JS Code and HTML are as follows:
document.addEventListener('DOMContentLoaded', function() {
// Submit comment form
document.querySelector('#comment-form').addEventListener("submit", function(event){event.preventDefault()});
document.querySelector('#comment-form').addEventListener('submit', () => save_comment());
});
function save_comment() {
console.log('Save function triggered');
frm = document.querySelector('#comment-form');
data_submit = {
updated_comment: frm.querySelector('#comment-editbox').value,
month: frm.querySelector('#comment-mth').value,
gl_code: frm.querySelector('#comment-gl').value,
csrfmiddlewaretoken: jQuery("[name=csrfmiddlewaretoken]").val(),
};
console.log('Save function triggered 2');
frm.submit(function (e) {
console.log('Submit triggered');
e.preventDefault();
$.ajax({
type: frm.attr('method'),
url: frm.attr('action'),
data: data_submit,
success: function (data) {
console.log("successful");
},
error: function(data) {
console.log("failed");
}
});
console.log('save ended');
return false;
});
}
<!-- The Modal -->
<div id="myModal" class="modal">
<!-- Modal content -->
<div class="modal-content">
<label id="comment-heading">Comments <span id="comment-subheading"></span></label>
<form action="{% url 'comment' %}" method="post" id='comment-form'>
{% csrf_token %}
<textarea id="comment-editbox" name="comment-editbox"></textarea><br>
<input type="hidden" id="comment-mth" name="comment-mth" value="">
<input type="hidden" id="comment-gl" name="comment-gl" value="">
<input class="btn btn-primary" type="submit" value="Save" id='comment-save'>
</form>
</div>
</div>
"Save function triggered" and "Save function triggered 2" get logged onto the console when I submit the form. But "Submit triggered" does not.
The form does get submitted to the server which returns a json response and causes the form to navigate to the response route. I do not want the form to redirect to the response route or reload the page.
What am I doing wrong?
Why are you using?
frm.submit(function (e) {
...
});
You are calling submit method on the DOM and passing in a function to it. There is no function with submit(); Those two lines should be removed.
document.addEventListener('DOMContentLoaded', function() {
document.querySelector('#comment-form').addEventListener('submit', save_comment);
});
function save_comment(e) {
e.preventDefault();
console.log('Save function triggered');
const frm = document.querySelector('#comment-form');
const data_submit = {
updated_comment: frm.querySelector('#comment-editbox').value,
month: frm.querySelector('#comment-mth').value,
gl_code: frm.querySelector('#comment-gl').value,
csrfmiddlewaretoken: jQuery("[name=csrfmiddlewaretoken]").val(),
};
$.ajax({
type: frm.attr('method'),
url: frm.attr('action'),
data: data_submit,
success: function(data) {
console.log("successful");
},
error: function(data) {
console.log("failed");
}
});
console.log('save ended');
}
I'm trying to add validation to my ResetPassword function. validation its work fine, but I got another problem my ResetPassword function not going to work after I add validation.Can anyone direct me in the right direction? thx.
HTML code:
<div class="PopUpBG">
<div class="PopUp">
<h3 class="modal-title">
<span>Reset PAssword</span>
</h3>
<form id="form">
<input type="email" name="ResetEmail" id="ResetEmail" placeholder="Email Adresse" required/>
<input type="submit" class="btn btn-success" value="Send" onclick="ResetPassword(this)"/>
</form>
</div>
</div>
ResetPassword & validation code:
function ResetPassword(e) {
var email = $("#ResetEmail").val();
if ($("#form").validate()) {
return true;
} else {
return false;
}
$(".PopUp").html("We have sent mail to you");
$.ajax(
{
type: "POST",
url: "/Account/loginRequestResetPassword",
dataType: "json",
data: {
Email: email,
},
complete: function () {
console.log("send");
$(".PopUpBG").fadeOut();
}
})
}
The issue is because you're always exiting the function before you send the AJAX request due to your use of the return statement in both conditions of your if statement.
Change your logic to only exit the function if the validation fails:
function ResetPassword(e) {
if (!$("#form").validate())
return false;
$.ajax({
type: "POST",
url: "/Account/loginRequestResetPassword",
dataType: "json",
data: {
Email: $("#ResetEmail").val().trim(),
},
success: function() {
console.log("send");
$(".PopUp").html("We have sent mail to you");
setTimeout(function() {
$(".PopUpBG").fadeOut();
}, 10000); // fadeout the message after a few seconds
},
error: function() {
console.log('something went wrong - debug it!');
}
})
}
Also note that I amended the logic to only show the successful email message after the request completes. Your current code can show the 'email sent' message to the user, even though there is still scope for the function to fail.
I have a form which should submit data after pressing the submit button. After tagging a few input fields as required the form always shows me when there is no input in the required field after pressing the submit button - so far, so good.
What I would like to realize is that there is a redirection to another page if the submission was successful. If there are some empty required fields the form should show me, without redirecting me to another page.
By now I have the following code:
Submit button:
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" name="submityes" id="submityes" class="btn btn-danger">Submit</button>
</div>
</div>
Also I have the following js function to submit the form and to redirect me to another page:
$('document').ready(function () {
"use strict";
$(function () {
$('#submityes').click(function () {
$.ajax({
type: "POST",
/* url: "process.php", //process to mail
data: $('form.contact').serialize(), */
success: function (msg) {
window.location.replace("/submit_resolved.php");
},
error: function () {
alert("error");
}
});
});
});
});
The problem I have right now is that I will always be redirected to the "submit_resolved.php" page, whether all required fields are complete or not.
How can I solve this problem? I only want to be redirected when all required fields are not empty.
You should bind to the submit event, not click event:
UPDATED TO MATCH THE COMMENTS
$(function () {
var submityesClicked;
//catch the click to buttons
$('#submityes').click(function () {
submityesClicked = true;
});
$('#submitno').click(function () {
submityesClicked = false;
});
$('#webform').submit(function (e) {
e.preventDefault();//prevent the default action
$.ajax({
type: "POST",
/*url: "process.php", //process to mail
data: $('form.contact').serialize(),*/
success: function (msg) {
window.location.replace(submityesClicked ? "/submit_resolved_yes.php" : "/submit_resolved_no.php");
},
error: function () {
alert("error");
}
});
});
});
The submit event is triggered only if the form is valid.
Note that the submit event is triggered by the form but the click event is triggered by the input element.
Do redirection on complete. Not on success
$('document').ready(function () {
"use strict";
$(function () {
$('#submityes').click(function () {
$.ajax({
type: "POST",
/* url: "process.php", //process to mail
data: $('form.contact').serialize(), */
success: function (msg) {
//window.location.replace("/submit_resolved.php");
},
complete: function () {
window.location.replace("/submit_resolved.php");
},
error: function () {
alert("error");
}
});
});
});
});
I assume you are validating form in process.php so, you have to return error if validation fail from process.php like this.
header('HTTP/1.1 500 Internal Server Booboo');
header('Content-Type: application/json; charset=UTF-8');
die(json_encode(array('message' => 'ERROR', 'code' => 1337)));
check this link: Return errors from PHP run via. AJAX?
Hope this may be helpful to you.
The simplest thing you can do is to add "required" attribute to you input elements.Example:
<form action="/action_page.php">
Username: <input type="text" name="usrname" required>
<input type="submit">
</form>
It's a HTML5 attribute, so no JavaScript required. And it is supported by all major browsers. Check this link:
http://caniuse.com/#search=required
Anyway, you shouldn't rely just on front-end verification. Check those inputs on back-end, too.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<form action="">
Username: <input type="text" id="usrname" required>
<button type="button" name="submityes"
id="submityes" class="btn btn-danger">Submit</button>
</form>
</div>
function isValid(){
var usrname = $("#usrname").val();
if(usrname == ""){
return false;
}
return true;
}
$(function () {
$('#submityes').submit(function () {
if(isValid() == true){
$.ajax({
type: "POST",
/*url: "process.php", //process to mail
data: $('form.contact').serialize(),*/
success: function (msg) {
alert("success");
window.location.replace("/submit_resolved.php");
},
});
}else{
alert("error");
}
});
});
I have a form on a bootstrap modal with two buttons. This form is tied to an action named "DeleteWidgetConfirmed" I am trying to remove a widget from the database and from the front end, the panel gets removed from the front end but does not seem to get removed from the database.
Here is my Modal
<div class="modal fade" id="deleteWidgetModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="myModalLabel">Delete widget?</h4><!--add depending on which panel you have clicked-->
</div>
<div class="modal-body" id="myModalBody">
<!--Depending on which panel insert content-->
#using (Html.BeginForm("DeleteWidgetConfirmed", "Dashboard", FormMethod.Post))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
Do you wish to delete this widget?
<div class="form-group">
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button type="submit" value="DeleteWidgetConfirmed" class="btn btn-danger btn-ok" id="delete-widget">Delete</button>
</div>
</div>
</div>
}
</div>
</div>
</div>
Here is my action:
// POST: DashboardModels/Delete/5
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult DeleteWidgetConfirmed(int? id)
{
if(id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
DashboardModel dashboardModel = db.dashboards.Find(id);
db.dashboards.Remove(dashboardModel);
db.SaveChanges();
return new EmptyResult();
}
From my javascript I get the ID from the panel and store it into a variable, I then get the action attribute from my form and append the ID to the action attribute.
$(document).ready(function () {
$('#columns').on('click', '.glyphicon.glyphicon-trash', function (event) {
var panel = this;
//get id here
//toggle the modal
$('#deleteWidgetModal').modal('show');
var widgetID = $(this).closest('.panel.panel-default').attr('data-widgetid');
document.getElementById('delete-widget').onclick = function (event) {
event.stopPropagation();
//we make an ajax call to the controller on click
$.ajax({
url: '#Html.Raw(Url.Action("Dashboard", "DeleteWidgetConfirmed"))',
data: { id: widgetID},
type: 'POST',
dataType: 'json',
contentType: 'application/json; charset=utf-8',
success: function(data){
var parentElement = $(panel).closest(".col-md-4.column");
var targetElement = $(panel).closest(".panel.panel-default");
targetElement.remove();
//parentElement.addClass("expand-panel");
checkEmptyPanelContainers();
$('#deleteWidgetModal').modal('hide');
},
error: function (response) {
}
})
}
})
});
I have a hunch that maybe within my javascript I have overridden the default behaviour of the event.
What I want to achieve ultimately is
within the onclick event for the button to remove the panels(which works)
remove the entry within the database related to that panel.
When executing the post method do not refresh.
Try using AJAX to asynchronously post to your controller:
$(document).ready(function () {
$('#columns').on('click', '.glyphicon.glyphicon-trash', function (event) {
var panel = this;
//get id here
//toggle the modal
$('#deleteWidgetModal').modal('toggle');
var widgetID = $(this).closest('.panel.panel-default').attr('data-widgetid');
$.ajax({
url: '/Dashboard/DeleteWidgetConfirmed/',
type: 'POST',
data: { id: widgetid },
dataType: 'json',
contentType: 'application/json; charset=utf-8',
error: function (xhr) {
// request failed, handle here!
},
success: function (result) {
// request succeeded! handle that here. close the modal? remove the item from the UI?
}
});
}
});
});
How you handle the success callback depends on the UI, you can use the data- attributes to do so quite easily.
You need to decorate your action method as POST if you do this:
[HttpPost]
public ActionResult DeleteWidgetConfirmed(int id) {
...
}
Answer:
OK answer supplied below, by #www.innovacall.com is correct, I just didn't read it right the first time, now it works perfectly, thanks.
Original question:
I tried some solutions but none works for me.
In my project, I got a modal popup like this (I use bootstrap):
<!-- Modal -->
<div class="modal fade" id="skillAnswerModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id="myModalLabel">#ViewBag.AddressTimeTableMapModalEditHeaderTitle</h4>
</div>
<div class="modal-body">
<div id="addSkillAnswerModal">
#Html.Partial("_AddSkillAnswer", Model.TempSkillAnswer)
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">#ViewBag.CloseButtonLabel</button>
<button type="button" class="btn btn-primary" id="btnAddSkillAnswerModal" >#ViewBag.SaveChangesButtonLabel</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
I submit data from that popup with the following ajax:
$("#btnAddSkillAnswerModal").click(function () {
$.ajax({
url: addSkillUrl,
type: "POST",
cache: false,
async: true,
traditional: true,
data: $("#addSkillAnswerModal :input").serialize(),
dataType: "json",
success: function (result) {
$("#skillAnswerModal").modal('toggle');
$("#addSkillAnswerModal input[type!=hidden]").val('');
$("#IsAnswerVisible").val("true");
oTable.fnReloadAjax();
}
});
});
The problem:
Standard #Html.ValidationSummary() helper inside the View rendered in my modal popup, is not being called - thus I have no client side validation. I know that #Html.ValidationSummary() only works when I use #Html.BeginForm(...) but how can I validate my ajax before submit? I tried something like this:
$("#btnAddSkillAnswerModal").click(function () {
$("#AddSkillAnswerForm").validate({
debug: true,
submitHandler: function (form) {
$.ajax({
url: addSkillUrl,
type: "POST",
cache: false,
async: true,
traditional: true,
data: $("#addSkillAnswerModal :input").serialize(),
dataType: "json",
success: function (result) {
$("#skillAnswerModal").modal('toggle');
$("#addSkillAnswerModal input[type!=hidden]").val('');
$("#IsAnswerVisible").val("true");
oTable.fnReloadAjax();
}
});
},
showErrors: function (errorMap, errorList) {
$("#summary").html("Your form contains "
+ this.numberOfInvalids()
+ " errors, see details below.");
this.defaultShowErrors();
}
});
});
But it's not working, that is: there are no errors, but when I debug the JS, it sort of "skips" the validation, neither submitHandler nor showErrors is being hit...
How can I validate my form before ajax call?
Best regards.
EDIT1:
#www.innovacall.com:
I tried this approach but still it is not working for some reason...
My _AddSkillAnswer partial looks like this:
#model HostessServiceApplication.WebUI.Models.Admin.AgencyAnimatorSkillAnswerListAddSkillAnswer
#using HostessServiceApplication.Common.Localizer
#using HostessServiceApplication.WebUI.Resources
#using HostessServiceApplication.WebUI.Resources.Admin
#{
Layout = null;
//GlobalResources:
var globalLocalizer = new UniversalTextLocalizer(typeof(TranslationStrings));
ViewBag.SaveChangesButtonLabel = globalLocalizer.GetTranslatedVariable("SaveChangesButtonLabel");
var viewSpecificLocalizer = new UniversalTextLocalizer(typeof(AddSkillAnswer));
ViewBag.Title = viewSpecificLocalizer.GetTranslatedVariable("AddSkillAnswerPageTitle");
}
<h2>#ViewBag.Title</h2>
#using (Html.BeginForm("AddSkillAnswer", "Admin", FormMethod.Post, new { enctype = "multipart/form-data" ,id="AddSkillAnswerForm"}))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary()
#Html.EditorForModel("Admin/AgencyAnimatorSkillAnswerListAddSkillAnswer")
}
I tried the following combinations:
$("#btnAddSkillAnswerModal").click(function () {
var form = $("#AddSkillAnswerForm");
$.validator.unobtrusive.parse(form);
//form.validate();
form.validate({
debug: true,
submitHandler: function (form) {
$.ajax({
url: addSkillUrl,
type: "POST",
cache: false,
async: true,
traditional: true,
data: $("#addSkillAnswerModal :input").serialize(),
dataType: "json",
success: function (result) {
$("#skillAnswerModal").modal('toggle');
$("#addSkillAnswerModal input[type!=hidden]").val('');
$("#IsAnswerVisible").val("true");
oTable.fnReloadAjax();
}
});
},
showErrors: function (errorMap, errorList) {
$("#summary").html("Your form contains "
+ this.numberOfInvalids()
+ " errors, see details below.");
this.defaultShowErrors();
}
});
});
and this:
$("#btnAddSkillAnswerModal").click(function () {
var form = $("#AddSkillAnswerForm")
.removeData("validator") /* added by the raw jquery.validate plugin */
.removeData("unobtrusiveValidation"); /* added by the jquery unobtrusive plugin */
$.validator.unobtrusive.parse(form);
form.validate({
debug: true,
submitHandler: function (form) {
$.ajax({
url: addSkillUrl,
type: "POST",
cache: false,
async: true,
traditional: true,
data: $("#addSkillAnswerModal :input").serialize(),
dataType: "json",
success: function (result) {
$("#skillAnswerModal").modal('toggle');
$("#addSkillAnswerModal input[type!=hidden]").val('');
$("#IsAnswerVisible").val("true");
oTable.fnReloadAjax();
}
});
},
showErrors: function (errorMap, errorList) {
$("#summary").html("Your form contains "
+ this.numberOfInvalids()
+ " errors, see details below.");
this.defaultShowErrors();
}
});
});
but still it doesn't work, neither submitHandler nor showErrors is being hit.
If you loaded your form with ajax, you need to parse your form again :
$.validator.unobtrusive.parse(form);
form.validate();
if (form.valid()) {
form.submit();
}