I have a function which verifies if some fields have been filled out (if length > 0) before submitting. If it fails to submit, I don't want to redirect the client at all. Right now, I have the following:
function onSubmit()
{
if (verify()) //This function will throw alert statements automatically
{
document.getElementById('my_form').submit();
return void(0);
}
else
{
document.getElementById('my_form').action = null;
}
}
However, it doesn't matter if verify() returns true or not, I still redirect the client and wipe her inputted fields. How do I keep the client on the page if a required field is blank? (I don't want to lose her currently filled out form...)
Also, I can't use the slick JQuery libraries, since it's not supported on some older browsers. (I'm trying to capture the most general audience.)
This is how I would try to solve this:
document.getElementById('my_form').onsubmit = function( e ){
var event = e || window.event;
// function payload goes here.
event.returnValue = false;
if ( event.preventDefault ){ event.preventDefault(); }
return false;
}
Can be used with event delegation too.
return false to the form!
<form onsubmit="return onSubmit()">
function onSubmit()
{
if (verify()) //This function will throw alert statements automatically
{
return true;
}
else
{
return false;
}
}
to stop the form from submitting, return false from your onSubmit
Related
Fortify SCA flagged this line of code as a vulnerability, with the following warning:
The call to on() in jquery.validate.js on sets a callback that could lead to a race condition
https://github.com/jquery-validation/jquery-validation/blob/98fbc5f4287b9e580be6c1404094e9ae31b4abb2/src/core.js#L46
However based on my understanding, I don't see how is it setting a callback that might induce a race condition. Isn't it only listening for the "submit.validate" event?
How do I resolve this? Is this a vulnerability? I checked the CVE and security advisories in the github repo and I see no mention of it.
this.on("submit.validate", function(event) {
if (validator.settings.debug) {
// Prevent form submit to be able to see console output
event.preventDefault();
}
function handle() {
var hidden, result;
// Insert a hidden input as a replacement for the missing submit button
// The hidden input is inserted in two cases:
// - A user defined a `submitHandler`
// - There was a pending request due to `remote` method and `stopRequest()`
// was called to submit the form in case it's valid
if (validator.submitButton && (validator.settings.submitHandler || validator.formSubmitted)) {
hidden = $("<input type='hidden'/>")
.attr("name", validator.submitButton.name)
.val($(validator.submitButton).val())
.appendTo(validator.currentForm);
}
if (validator.settings.submitHandler) {
result = validator.settings.submitHandler.call(validator, validator.currentForm, event);
if (hidden) {
// And clean up afterwards; thanks to no-block-scope, hidden can be referenced
hidden.remove();
}
if (result !== undefined) {
return result;
}
return false;
}
return true;
}
// Prevent submit for invalid forms or custom submit handlers
if (validator.cancelSubmit) {
validator.cancelSubmit = false;
return handle();
}
if (validator.form()) {
if (validator.pendingRequest) {
validator.formSubmitted = true;
return false;
}
return handle();
} else {
validator.focusInvalid();
return false;
}
});
To make an evaluation on the last page of a portal, using the submit button, Microsoft provides an extension for the function "webFormClientValidate" that the submit button should trigger:
https://learn.microsoft.com/en-us/dynamics365/customer-engagement/portals/add-custom-javascript.
I put this code in my last step in the portal:
console.log("alive");
if (window.jQuery) {
console.log("1");
(function ($) {
console.log("2");
if (typeof (webFormClientValidate) != 'undefined') {
console.log("3");
var originalValidationFunction = webFormClientValidate;
if (originalValidationFunction && typeof (originalValidationFunction) == "function")
{
console.log("4");
webFormClientValidate = function()
{
console.log("5");
originalValidationFunction.apply(this, arguments);
console.log("6");
// do your custom validation here
if (...)
{
console.log("7 false");
return false;
}
// return false;
// to prevent the form submit you need to return false
// end custom validation.
return true;
};
}
}
}(window.jQuery));
}
On pageload the log writes out:
alive
1
2
3
4
Pressing the submit button should trigger the "webFormClientValidate" function, but nothing happens. "5" is not being written to the log. Anyone know why?
Update: From debugging it appears as if the page does not recognize "webFormClientValidate" at all. Searching through the elements however, this guy appears:
function webFormClientValidate() {
// Custom client side validation. Method is
called by the next/submit button's onclick event.
// Must return true or false. Returning false
will prevent the form from submitting.
return true;
}
My research shows other people just pasting in the same bit of code. Witch tells me that it should work somehow:
http://threads290.rssing.com/chan-5815789/all_p2645.html
https://rajeevpentyala.com/2016/09/12/useful-jscript-syntaxes-adx-portal/
http://livingindynamics365.blogspot.com/2018/02/validating-user-input-in-crm-portals.html
If you are using an Entity Form, use entityFormClientValidate in place of webFormClientValidate
I've spent some time looking around and trying multiple solutions without luck, while attempting to streamline a form to create a pseudo bulk process.
Essentially I simply need to prevent default on a submit button, but to trigger it if several subconditions are met, at least one of which uses an ajax call.
I've tried variations of e.preventDefault, $('#form').submit(false); and I can either get the validation to occur, or the form to submit, but never both in the right places. (for example it will submit without checking for duplicate entries)
Here's a summed up version of what I've been attempting.
This is the main variable which holds the first part of the check:
var verifyValue = function() {
// this stops the form, and then things validate fine.
$('#add-item-form').submit(false);
//but then I need to get it started again to submit valid entries
if($('#value_of_json_array').val().length != 0){
$('#value_of_json_array').prop("readonly", true);
jQuery.getJSON('{{ path('query_to_get_array') }}?' +
$.param({barcode: $('#value_of_json_array').val()}))
.done(checkedValue);
}
};
This is where it is called:
$("#verify-value").click(verifyValue);
Below is a shorthand of the conditional being run:
var checkedValue = function(items) {
if(items.length == 0){
// success conditions
}
else {
//this was just one attempt
$('#form').submit(false);
if( /* sub condition of data passed from JSON array */){
//condition creates new form which upon action sends AJAX call
}
else
{
//second error condition
}
}
};
What I'm trying to do is to have if any of the subconditions occur, to have it stop the submit button (e.g. preventDefault behavior) and if it does not have any of these, to allow the submission of the form
It feels like it should be simple, however no matter where I do this, including using $(this).unbind('submit').submit() It doesn't work right.
Either the validation occurs correctly and nothing submits, or everything submits even if it's not supposed to.
I feel like modifying var verifyValue will work but I'm not sure how to get the conditional statements bound into an event.
Edit:
Okay, so I was guilty of seriously overthinking this issue, and came up with a solution which I will put below (in case anyone is interested)
Since your validation includes an async step, it'd be easier to just stop the form submission right away.
Then call your validation function, which will set the validation state of the form in a "global" state (maybe just a closure of the event handler). If the validation is fine, submit the form, else just show the validation error.
// You'll need to reset this if an input changes
var isFormValid = false;
$("#form").on('submit', function(e) {
if (isFormValid) {
return true;
}
e.preventDefault();
validateForm(function(valid) {
if (valid) {
isFormValid = true;
$('#form').submit();
}
});
});
function validateForm(cb) {
var form = $('#form');
// do some synchronous validations on the form inputs.
// then do the async validation
if($('#value_of_json_array').val().length != 0){
$('#value_of_json_array').prop("readonly", true);
jQuery
.getJSON(
'{{ path('query_to_get_array') }}?' +
$.param({barcode: $('#value_of_json_array').val()})
)
.done(function(result) {
if (checkedValue(result)) {
cb(true);
} else {
cb(false);
}
});
} else {
cb(false);
}
}
How about this approach, here's a simple skeleton:
$('#form').submit(function(e){
var formError = false;
// set formError to true if any of the checks are not met.
if(some condition) {
// do a conditional check
formError = true;
} else if(another condition) {
// do another conditional check
formError = true;
}
if(formError) { // stop form submission of any of the conditions are not met.
return false; // same as e.preventDefault and e.stopPropagate()
}
});
It turned out I was seriously overthinking this issue. It was a lot easier to handle by binding everything into a button that was not a submit, and if it passed the validation simply use a submit condition. This way I didn't need to worry about preventing default behavior and turning it back on again (which was where I was getting stuck). Since regular buttons have no default behavior, there was no need to be concerned about it submitting incorrectly.
The original function just needed to be simplified to:
var verifyValue = function() {
if($('#value_of_json_array').val().length != 0){
$('#value_of_json_array').prop("readonly", true);
$('#barcode-buttons').hide();
jQuery.getJSON('{{ path('query_to_get_array') }}?' +
$.param({barcode: $('#value_of_json_array').val()}))
.done(checkedValue);
}
};
$("#verify-value").click(verifyValue);
and then the check only needed to do this
var checkedValue = function(items) {
if(items.length == 0){
$('#form').submit()
}
else {
//error conditions
}
};
I have form that calls the function GenerateWords when it is submitted and returns false.
<form id="3Form" onsubmit="GenerateWords(this); return false;">
This is causing problems with Google Tag Manager implementation as it does not bubble up to the form submit listener.
I understand event.preventDefault(); needs to be used and return false removed but don't know how to implement this. The current javascript I have is:
function GenerateWords(F) {
var strWords = F.words.value;
if ... condition is false
return false;
}
if ... condition is false
return false;
}
vars declared
for (var i = 0; i < ctLines; i++) {
var strLine = arrLines[i];
strLine = Trim(strLine.replace(/[\r]/g,""));
if successful condition
}
}
F.result.value = oResult.join("");
F.result.focus();
}
Any help would be appreciated. Thanks.
Try this in javascript:
function GenerateWords(F,ev) { // event object
...
if(someCondition) // condition when the form should not be submitted.
ev.preventDefault();
}
and you may remove return false; from the form tag and pass the event reference
<form id="3Form" onsubmit="GenerateWords(this,event);">
i have a page on which i want to confirm if the user wants to leave.
i have to confirm only when a certain condition is met so i wrote code like this
var back=false;
back=//check if user pressed back button
window.onbeforeunload = function (e) {
alert(back); //this alerts true
if(back==true)
return false;
//e.preventDefault; --this does not work too
};
but this does not work. i mean when i click on back button this onbeforeunload still fires and i still get the confirmation message even when i m returning false.Whats can be wrong?
Thanks
Return a string if you want to offer an option to the user to abort the unload. Return nothing in other cases.
var back = false;
back = true; //Somewhere, the condition is set to true
window.onbeforeunload = function (e) {
if(back == true)
return "Are you sure to exit?";
}
$(window).bind('beforeunload',function() {
return "'Are you sure you want to leave the page. All data will be lost!";
});
$('#a_exit').live('click',function() {
$(window).unbind('beforeunload');
});
Try this. Above code is working in most of conditions.
For the sake of completeness here a more modern, recommended approach:
let warn = false;
window.addEventListener('beforeunload', e => {
if (!warn) return;
// Cancel the event
e.preventDefault();
// Chrome requires returnValue to be set
e.returnValue = '';
});
warn = true; // during runtime you change warn to true
Typically, it is better to use window.addEventListener() and the
beforeunload event, instead of onbeforeunload.
Source
The reason why your originally posted code didn't work is that false is a non-null value. If you would have returned null or undefined in the situation where you don't want to spawn a pop-up warning your code would have worked as expected.
The currently accepted answer works because JavaScript implicitly returns undefined at the end of the function.
Condition for back-end
var confirmExist = function (e) {
return true;
}
window.onbeforeunload = confirmExist;
http get, post request
.then(function(r)) {
window.onbeforeunload = null;
}
You could also consider not setting the window.beforeunload event untill your list of conditions are met.
var confirmUserToLeave = function () {
if (/* conditions are met */) {
window.unbeforeunload = function (e) {
/* whatever you want to do here */
};
} else {
window.unbeforeunload = undefined;
}
};
Then just call that method on certain events that might change the outcome of your 'conditions are met'.