jQuery issues on testing form elements values - javascript

Good day all.
I have a form where users must fill out some fields, and this form is created dinamically y a php script.
I've done a script that do a test on input fields to check if the users has filled everything.
It is basically a cascade test in where if an error variable is true, the form isn't submitted.
I have done some modifications and I have added a new hidden field to the form, filled by jquery when user clicks a image.
$( '.selectLogo' ).bind("click",function(e){
$( "#operator" ).val( $(this).data("opvalue") );
});
then, on the submit event, there is the whole test...
if ( !$( "#operator" ).val().length ){
$(".operatorError").show();
error=true;
} else{
$(".operatorError").hide();
}
if(error){
return false;
}
this is the last test I've added on the function, just before testing the error variable and decide if return true or false.
the problem is that:
IF i'm debugging the script, i.e. I put a breakpoint just over the if(error), everything is fine.
IF i filled the whole form, i.e. the checkForm function just go throught every test and arrive on the decision of returning true or false, everything is ok.
BUT if i filled the form partially, and I try to make a submit without selecting the operator (the new field i've added), the checkForm function stops me, display the error, but at this point, I must click on the operator logo to make the hiden field fills, then I have to click SEVERAL (read 2,3 or sometimes 4) times the submit button to have the form submitted.
It sounds like that the error variable retain the value, and the jQuery cache it... or something, does anyone has experienced a similar problem? it is possible to "force" jQuery to "really" test a variable...? Am I complitely wrong and maybe the problem is elsewhere?

Related

Is there an HTML5 validation API to set the state of an element to be invalid?

I don't want to use the HTML 5 validation API but for one thing. I will do my custom validation using JavaScript but I would like to use the nice tool-tip like thingy that the browser uses to display the validation message.
So, in short, I'd like to selectively use the element.setCustomValidity("my own message") in my own event handler, so I can avoid using a third-party tool-tip.
However, even though I set the custom validity, it won't display until I somehow invalidate the state of the controls.
If I call into the validation API (element.checkValidity()), it will start doing its own in-built validation looking for attributes on my HTML elements. But I don't want any of that.
function submitEventHandler() {
let errors = myOwnValidateFunction();
if (errors && errors.length > 0) {
let txt = document.getElementById("txt");
txt.setCustomValidity("No, no, no, no, you're doing it wrong!");
// Is there a way to invalidate an HTML element?
// ...???
}
}
Well, as always, each browser simply act differently on pretty much any new API.
To invalidate an input, its enough to set this: input.setCustomValidity('just an error');, this will let the browser know this input have an issue with it.
HOWEVER each browser will do its own things:
Chrome - Won't show any error until you try to submit the form, only than it will let the user know that the first field with an error have an error, it will ignore the rest of the inputs with errors.
Firefox - will show your custom message and highlight the input in red right away after you set it, you don't need to wait for a submit to show the errors, when submit is clicked it shows a different tooltip on the invalid input.
Edge - Will show an tooltip with custom message only after the user hover over it, and will highlight in red with different tooltip after submit
Didn't test it on other browsers, but i'm sure each browser will use its own way of showing the error, some might wait for submit, some will show right away, but all who support this API should invalid the input after you input.setCustomValidity('Some error message')
This is why you might consider showing your own tooltip to avoid this browser dependency, and make sure its working the same way on all of them.
https://jsfiddle.net/q60bwteL/17/
Update
You don't need to set any type, and the validation above works the same way for type='text', i'm not sure what you see, but the code snippet below have 2 inputs, 1 with no type and 1 with type='text', both works.
You can create a fiddle with your issue so I could take a look, but as you can see from the fiddle, its working for all type of inputs:
https://jsfiddle.net/q60bwteL/21/
But again, note that it works differently on different browsers, chrome only shows the first field with the error, not all of them and only on submit, while firefox shows errors for all of the fields (if have multiple errors) and before you click on submit.
This is why I personally never trust the implementation of the browser with stuff I could do on my own, it is very easy to implement a basic error handling stuff, from the question you already have it, you simply need to add the styling and the tooltip to it, there are many ways to create a tooltip with CSS alone on the web (for example: https://stackoverflow.com/a/25391104/8727608).
Create a function that will handle your error things:
function setError(inputElement, errorMessage) {
inputElement.setAttribute('title', 'errorMessage');
inputElement.classList.add('errorInput')
}
Create a function that will remove all the error things:
function removeError(inputElement) {
inputElement.removeAttribute('title');
inputElement.classList.remove('errorInput')
}
And style the errorInput class as you wish with CSS.
Now I assume you only return the errors in array of strings with the error messages, but you can use an array of objects that each object contain the error message and the input element which have the error:
if (errors && errors.length > 0) {
for(var i = 0; i<errors.length; i++) {
setError(errors[i].element, errors[i].message);
}
}
Before you validate the input simply call the removeError function and don't forget to return false when you submit if there are errors. (as you already do)
UPDATE 2
I don't know why I didn't think of it. but there is a way to stop validation and start it when you want:
Adding the novalidate attribute on the form will let the browser know that you don't want to perform a validation on that form, so this won't show any errors and will handle submit as you like it to.
But you still want to use that validation and for this you can call the reportValidity() on the form element, basically this function enable the validation on submit, it doesn't matter where you call it, it will run the validation when submit is clicked BUT this will show only the first input with the error message and not all of them (even on firefox), it looks like there are 2 states of validation, the before and after submit, not sure why, but those are 2 different checks, and you can only control the after submit check, not the before.
check this fiddle: https://jsfiddle.net/q60bwteL/64/
So you can control when you do the validation, but there are 2 types of validation, before and after submit, you can control only after submit, and it only show the first input error not all of them.
Do we like it? no, why its like that? I have no idea, to be honest, it really looks like the firefox developers simply break the loop after first error is found.
P.S - after thinking about it, they simply implement the title attribute tooltip method, but because only 1 element can be hovered or focused they can only show 1 error message, this is how tooltips works.

disabled.bind in Aurelia not working correctly

I have a form, in the form there is a custom component that has certain fields in it. At the end of the form there is a button. The button has...
disabled.bind="!(formValid && subFromValid)"
Now, on the custom component I have a two-way binding of a variable "subFormValid" The subFormValid is only valid when the validation in the custom component is valid. So, the sub form validates some fields and sets subFormValid = true. Even though the "formValid" is false, the button is now enabled.
I can't figure out why and it is driving me nuts. I even went so far as to add a get function to a variable and add console logs in it, like so...
<button type="submit" disabled.bind="wholeFormValid">Submit</button>
Then in my class I have...
get wholeFormValid() {
console.log("validating form");
console.log(!(this.formValid && this.subFormValid));
return !(formValid && subFormValid);
}
I get a million plus lines in the console, but I was able to watch it, the entire time. When I first load the page it was logging...
validating form
true
Then I filled out the subform, and checked the console. The console showed...
validating form
true
Yet, the button was now enabled.
For some reason whenever subFormValid = true, the button is enabled, regardless of formValid.
Does anyone know how to disable a button unless 2 conditions are met? Everything I do enables the button as soon as subFormValid is true, even though the console is still logging "true", which should disable the button.
Just to help out, if anyone is wondering why there is a subform in the form it is because the address needs to be validated using Smarty Streets and we want to be able to reuse that part of the form in other places, so I created a custom component for the address section that validates the input, and validates the address. It is being called in the form like so...
<require from="components/smarty-streets"></require>
Then using like this...
<smarty-streets form-is-validated.two-way="subFormValid"></smarty-streets>
Then in smarty streets I have...
#bindable formIsValidated;
and I change the value from true to false and vice-versa depending on the validation in the component.
I have tried to recreate your problem using the following:
<input type="checkbox" checked.bind="formValid"/>
<input type="checkbox" checked.bind="subFormValid"/>
<button disabled.bind="wholeFormValid">Submit</button>
I noticed in your function that you used this.formValid in the console.log line, but in the return line you used formValid, without this. This seems to be a different variable than your actual binding variables. I think your function should look like this:
get wholeFormValid() {
console.log("validating form");
console.log(!(this.formValid && this.subFormValid));
return !(this.formValid && this.subFormValid);
}
Edit: I also strongly recommend using the #computedFrom decorator on your get() to reduce the amount of calculations aurelia does. You can read more on that here.

jquery submit form once

I am trying to write a custom magento module and i've got it all complete and working perfectly except one problem.
The module is a form with 4 radio buttons. They are all blank on the checkout page and I have them set up so that when you click one it submits the form and reloads the cart page with the "additional fees" in the subtotal.
My problem is that I need the first option to "auto submit" on page load. But I've tried ALOT of different things and can't come up with a way to use the jquery .submit() function to ONLY submit the form once. as it is now it works how I want it, except it loads the page in an endless loop.
Any way to say submit() only once?
I'd set the default radio button server-side rather than having an extra submit/refresh cycle, but if you insist on doing it client-side...
I assume on subsequent refreshes the previous selection will be retained (because your server-side code echoes back the previously selected values?), so can you perhaps test whether any radios are checked and if not assume that that is the first and only time to auto-submit?
$(document).ready(function() {
var $radios = $('#yourFormId input[name="yourRadioButtonGroupName"]');
if (!$radios.is(":checked")) {
// No radios currently checked, so check the first and submit
$radios.eq(0).prop("checked",true);
$("#yourFormId").submit();
}
});
The .is() method will "Check the current matched set of elements against a selector, element, or jQuery object and return true if at least one of these elements matches the given arguments."

Values Disappearing in Form

Well, the below snippet contains the text fields that I am filling in, whose values are used later in the JavaScript function.These are contained in a form.
The problem is when I submit the form, I get the correct value and then the contents of the fields filled in vanish after around 2 seconds. The same thing happen if I don't fill in the change in rate or change in capacity field, it gives the alert and then the value disappears. Any idea whats happening here? Im not even using 'refresh' anywhere. Thank you for your time.
You have bound your submit button a click listener. Therefore when you click the button the function runs, but the form is also submitted.
What you should do is to bind that function to form submit, like this;
<form ... onsubmit="calculateRevenue(this)">
And in that function, you should return false to prevent the form from being submitted.
if (form.ratechange.value == '')
{
alert('Please enter a value for the Change in Rate field. ');
return false;
}

Incuding "successful" buttons when calling form.submit()

I'm working on the Web GUI of an appliance-like product.
I have an HTML form that works fine: it shows a list of things with checkboxes, the user checks some of them and clicks the "remove" button which submits the form. The server gets the POST, removes the items, and refreshes the page. All fine.
There's a requirement to add an "are you sure?" confirmation to the form. If I add a call to
confirm("are you sure?");
as the onsubmit method in the FORM tag, or the onclick in the submit button tag, it works fine but uses the ugly browser-native confirm dialog.
Elsewhere in the product we have a nice custom CSS-styled confirm dialog I'd like to use, but it works like this: At the appropriate place, you put a call to
myConfirm("Confirm", "Are you sure", "Yes", "No", confirmCallback);
This puts up a clickmask, customizes a dialog, centers and displays it, and then returns FALSE and the form doesn't submit.
Later when the user decides, if they press "Yes", it calls the confirmCallback function. In the other, Ajax based pages of the product this gathers info, creates a postBody and uses Prototype's Ajax object to post it, and all is fine. (If "No", then the dialog and clickmask are removed and things continue.)
On this simpler page, with the pure HTML form, I have a confirmCallback function that looks like this:
var confirmCallback = function() {
document.myForm.submit();
}
and it fires OK, but when the form is submitted, the remove button has ALREADY been clicked, and the false returned by the custom confirm suppressed submission. Instead, this is considered a new submission, and the remove button was not actually clicked, so it is not considered "successful" in terms of W3.org's HTML 4 standard section 17.13.3. The server gets the data, no remove button, says "I got it but I dunno what you want me to do with it" and just does nothing but serve the next page.
If you're read this far, THANK YOU, and here is my actual question. How can I, in my confirmCallback javascript function, in a crossbrowser manner, cause the remove button to fire, become "successful" and submit along with the rest of the data?
Sounds like you're gonna need a hidden field to pretend to be the pressed button, and each button will require no name, but instead an onclick event to manipulate the value of the hidden field.
If the name of the buttons are all different, you might need to use DOM methods to add the hidden field because I don't think you can change the name of a field once it has been added to the DOM in all browsers.
If you require this solution to still work without JS, then you may need play around with the JS logic a little more (to do more modifications to your initial DOM tree) or modify the server code. You could even put the "Are you sure" behaviour into the response then...
Assuming that the remove button is the submit button for that form then probably the easiest solution is to give the form an id
<form id="submitForm"...
Then in your confirm call the form submit
document.getElementById("submitForm").submit()
I think that will do what you're asking but it seems like you were pretty much at that solution already so if you're asking something else let me know.
In your callback, remove the onclick handler for the button (causing the confirmation), then trigger a click on the button. This will cause the button click to submit the form and result in the button causing the submit to be posted back along with the form data.
var confirmCallback = function() {
$('submitButton').stopObserving('click');
$('submitButton').click();
}

Categories