AngularJS clientside validation: Changing validation requirements depending on other fields? - javascript

I want to validate my fields using AngularJS's own form validation. However, I only want to check some of the fields when other fields have data. E.g.
<form novalidate name="myForm" ng-submit="submitThisForm()">
<h1>Shipping address</h1>
<!-- These are the inputs -->
<input name="sAddress1" type="text" ng-model="sAddress1" required>
<input name="sAddress2" type="text" ng-model="sAddress2" required>
<input name="sAddress3" type="text" ng-model="sAddress3">
<!-- These are the errors -->
<div class="error" ng-show='(myForm.sAddress1.$invalid) && myForm.submitted'>Required</div>
<div class="error" ng-show='(myForm.sAddress2.$invalid) && myForm.submitted'>Required</div>
<h1>Billing address (if different)</h1>
<!-- These are the inputs -->
<input name="bAddress1" type="text" ng-model="bAddress1" required>
<input name="bAddress2" type="text" ng-model="bAddress2" required>
<input name="bAddress3" type="text" ng-model="bAddress3">
<!-- These are the errors -->
<div class="error" ng-show='(myForm.bAddress1.$invalid) && myForm.submitted'>Required</div>
<div class="error" ng-show='(myForm.address2.$invalid) && myForm.submitted'>Required</div>
</form>
Basically, the Billing address is optional, but once any part of it is filled in, bAdress1 and bAddress2 become Required. How do I achieve this?
(The variable myForm.submitted is set to false on page load, and then set to true when the form is submitted, so it only shows once validation has taken place.) I prefer vanilla JS answers, but I am using jQuery for this project, so that is also okay.
EDIT: Here's the answer with a pretty, formatted layout:
In the HTML file:
<input name="bAddress1" type="text" ng-model="bAddress1" ng-required="doWeNeedThis()"/>
<input name="bAddress2" type="text" ng-model="bAddress2" ng-required="doWeNeedThis()"/>
<input name="bAddress3" type="text" ng-model="bAddress3"/>
In the JS file:
$scope.doWeNeedThis = function() {
if((document.getElementsByName("bAddress1")[0].value != "")
|| (document.getElementsByName("bAddress2")[0].value != "")
|| (document.getElementsByName("bAddress3")[0].value != "")) {
return true;
} else {
return false;
}
};
Many thanks to Davin for the quick (and complete) answer.

ng-required will allow you to run an expression to determine whether the field is required or not.
<input name="bAddress1" type="text" ng-model="bAddress1" ng-required="doWeNeedThis()">
ng-required is documented with form.
So, in your example, you could implement doWeNeedThis() function in your controller and check the values of your model to determine if the input should be required or not.
Otherwise, in simple cases, you can just write the expression directly into the ng-required expression:
<input name="bAddress1" type="text" ng-model="bAddress1" ng-required="bAddress1 || bAddress2">

Related

Custom javascript to check if fields are required

I have a some custom validation for a small input form, that checks if a field is required. If it is a required field it alerts the user, if there is no value. At the moment it will validate all inputs other than check boxes.
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form>
<div class="ss-item-required">
<label>Question: What is your name?</label>
<input type="text" name="name" id="name"></input>
</div>
<div class="ss-item-required">
<label>Question: What is your email?</label>
<input type="text" name="email" id="email"></input>
</div>
<div class="ss-item-required">
<label>Question: What is your address?</label>
<textarea name="address" rows="8" cols="75" id="address"></textarea>
</div>
<div class="ss-item-required">
<label>Do you agree to out terms?</label>
<input type="checkbox" name="Check_0">
</div>
Submit
</form>
<script>
function formcheck() {
var fields = $(".ss-item-required")
.find("select, textarea, input").serializeArray();
$.each(fields, function(i, field) {
if (!field.value)
alert(field.name + ' is required');
});
console.log(fields);
}
</script>
If anyone can work out how to include validation of check boxes, it would be much appreciated.
Even though some answers already provide a solution, I've decided to give mine, that will validate every required input in your form, regardless of being a checkbox (maintaining your each loop).
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form>
<div class="ss-item-required">
<label>Question: What is your name?</label>
<input type="text" name="name" id="name">
</div>
<div class="ss-item-required">
<label>Question: What is your email?</label>
<input type="text" name="email" id="email">
</div>
<div class="ss-item-required">
<label>Question: What is your address?</label>
<textarea name="address" rows="8" cols="75" id="address"></textarea>
</div>
<div class="ss-item-required">
<label>Do you agree to out terms?</label>
<input type="checkbox" name="Check_0">
</div>
Submit
</form>
<script>
function formcheck() {
var fields = $(".ss-item-required")
$.each(fields, function(i, field) {
field=$(field).find('input, select, textarea')[0]
if (!field.value || (field.type=='checkbox' && !field.checked))
alert(field.name + ' is required');
});
}
</script>
The problems were:
serializeArray() would try to get the value from your checkbox, and because it returned nothing, the checkbox input was never added to fields!
Checkboxes don't have a property value, instead they are checked
There is more than one way to determine this:
Check the length of the JQuery wrapped set that queries for only checked checkboxes and see if it is 1:
if($("input[name='Check_0']:checked").length === 1)
Check the checked property of the DOM element itself (which is what I'm showing below) for false. To extract the DOM element from the JQuery wrapped set, you can pass an index to the wrapped set ([0] in this case), which extracts just that one item as a DOM element and then you can use the standard DOM API.
if(!$("input[type='checkbox']")[0].checked)
NOTE: It's important to understand that all client-side validation can be easily bypassed by anyone who really wants to. As such, you
should always do a second round of validation on the server that will
be receiving the data.
FYI: You have some invalid HTML: There is no closing tag for input elements and for label elements, you must either nest the element that the label is "for" inside of the label or you must add the for attribute to the label and give it a value of the id of the element that the label is "for". I've corrected both of these things below:
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form>
<div class="ss-item-required">
<label for="userName">Question: What is your name?</label>
<input type="text" name="userName" id="userName">
</div>
<div class="ss-item-required">
<label for="email">Question: What is your email?</label>
<input type="text" name="email" id="email">
</div>
<div class="ss-item-required">
<label for="address">Question: What is your address?</label>
<textarea name="address" rows="8" cols="75" id="address"></textarea>
</div>
<div class="ss-item-required">
<label for="Check_0">Do you agree to out terms?
<input type="checkbox" name="Check_0">
</label>
</div>
Submit
</form>
<script>
function formcheck() {
var fields = $(".ss-item-required")
.find("select, textarea, input").serializeArray();
$.each(fields, function(i, field) {
if (!field.value){
alert(field.name + ' is required');
}
});
// Check to see if the input is a checkbox and if it's checked
if(!$("input[type='checkbox']")[0].checked){
alert("You must agree to the terms to continue.");
}
}
</script>
Personally (and I'm far from alone on this), the use of JQuery is way overused in today's world. When it came out, the standard DOM API wasn't as mature as it is now and JQuery made DOM element selection and manipulation very simple. Back then, JQuery was a Godsend.
Today, the DOM API has matured and much of what we use to rely on JQuery to make easy, can be done just as easily without JQuery. This means you don't have to reference the JQuery library at all (faster page loading) and you're code follows standards.
If you're interested, here's your code without JQuery:
<form>
<div class="ss-item-required">
<label for="userName">Question: What is your name?</label>
<input type="text" name="name" id="userName">
</div>
<div class="ss-item-required">
<label for="email">Question: What is your email?</label>
<input type="text" name="email" id="email">
</div>
<div class="ss-item-required">
<label for="address">Question: What is your address?</label>
<textarea name="address" rows="8" cols="75" id="address"></textarea>
</div>
<div class="ss-item-required">
<label for="Check_0">Do you agree to out terms?
<input type="checkbox" name="Check_0">
</label>
</div>
Submit
</form>
<script>
function formcheck() {
// Get all the required elements into an Array
var fields = [].slice.call(document.querySelectorAll(".ss-item-required > *"));
// Loop over the array:
fields.forEach(function(field) {
// Check for text boxes or textareas that have no value
if ((field.type === "text" || field.nodeName.toLowerCase() === "textarea")
&& !field.value){
alert(field.name + ' is required');
// Then check for checkboxes that aren't checked
} else if(field.type === "checkbox" && !field.checked){
alert("You must agree to the terms to continue.");
}
});
}
</script>

Adding *Required next to an empty input

So I was wondering how I could implement required fields into my code. I tried just using required="" in the <input> tag, however, this doesn't work across all browsers. I was wondering if someone could explain how to add "* Required" next to the input if the user tries to submit and the field is empty.
Here's my form code:
contact.html
<form class="contact_form" name="Form" onsubmit="return validateForm()" action="contactform.php" method="post">
<label>Name *</label><br/>
<input type="text" name="name" id="noName" placeholder="Full Name"><br/>
<label>Email *</label><br/>
<input type="text" name="email" id="a" placeholder="Email"><br/>
<label>Subject *</label><br/>
<input type="text" name="subject" id="b" placeholder="Subject"><br/>
<label>Message *</label><br/>
<textarea type="text" name="message" id="c" placeholder="Message"></textarea>
<button type="submit" name="submit" class="submit">Submit</button>
</form>
formvalidate.js
function validateForm()
{
var a=document.forms["Form"]["email"].value;
var b=document.forms["Form"]["subject"].value;
var c=document.forms["Form"]["message"].value;
if (a==null || a=="",b==null || b=="",c==null || c=="")
{
alert("Please Fill All Required Field");
return false;
}
}
var input = document.getElementById('a');
if(input.value.length == 0)
input.value = "Anonymous";
First of all this is wrong:
if (a==null || a=="",b==null || b=="",c==null || c=="")
Presumably you lifted that from here and as noted in the comments, it doesn't do what it claims and will only check the last field.
To add the message you can modify your validation function to check each field and insert some text. The snippet below should give you a basic idea - and since you're new to javascript I've commented each bit with an explanation. Hope this helps:
function validateForm() {
// start fresh, remove all existing warnings
var warnings = document.getElementsByClassName('warning');
while (warnings[0]) {
warnings[0].parentNode.removeChild(warnings[0]);
}
// form is considered valid until we find something wrong
var has_empty_field = false;
// an array of required fields we want to check
var fields = ['email', 'subject', 'message'];
var c = fields.length;
// iterate over each field
for (var i = 0; i < c; i++) {
// check if field value is an empty string
if (document.forms["Form"][fields[i]].value == '') {
// create a div with a 'warning' message and insert it after the field
var inputField = document.forms["Form"][fields[i]];
var newNode = document.createElement('div');
newNode.style = "color:red; margin-bottom: 2px";
newNode.className = "warning";
newNode.innerHTML = fields[i] + ' is required!';
inputField.parentNode.insertBefore(newNode, inputField.nextSibling);
// form is now invalid
has_empty_field = true;
}
}
// do the alert since form is invalid - you might be able to skip this now
if (has_empty_field) {
alert("Please Fill All Required Field");
return false;
}
}
<form class="contact_form" name="Form" onsubmit="return validateForm()" action="contactform.php" method="post">
<label>Name *</label><br/>
<input type="text" name="name" id="noName" placeholder="Full Name"><br/>
<label>Email *</label><br/>
<input type="text" name="email" id="a" placeholder="Email"><br/>
<label>Subject *</label><br/>
<input type="text" name="subject" id="b" placeholder="Subject"><br/>
<label>Message *</label><br/>
<textarea type="text" name="message" id="c" placeholder="Message"></textarea>
<button type="submit" name="submit" class="submit">Submit</button>
</form>
And of course you always need server side validation as well! Client side is really only to help get a snappy UIX and can be easily fail or becircumvented by any user who has a mind to do so. Any data you send to the server needs to be checked over and if something's wrong an error should be returned and handled properly on the form page.
The input field becomes a required field when you specify inside the field that it is a required field. Just placing an asterisk * or placing the word required next to it will not make it required.
Here is how to make an input field required in HTML5
Username *: <input type="text" name="usrname" required>
It is the attribute "required" of the element itself that makes it required.
Secondly.. when using the HTML5 validation you will not need javascript validation because the form will not pass the html5 validation. Having both client-side and server-side is important.

Angular validations - Enabling/Disabling input fields changes validity of form

I have a form. In which I have input fields and I am doing some validation based on input. Also, there is a submit button which enables only if form is valid.
In this form I am enabling/disabling input field in one of the flow.
Initially, when the fields are enable and empty, create button is disabled. After i disable and enable the fields, create button becomes enabled. Although input fields are still empty.
More over button which is enabling/disabling this part is outside of this form.
Here is my code
`
<form method="post" novalidate id="example-widgets-form" name="mdnsCtrl.createSubDomainForm" valdr-type="SubDomain">
<div>
<label>Domain Name</label>
<input required type="text" name="subDomainName" placeholder="Domain Name" ng-model="mdnsCtrl.newDomain.name">
</div>
<div>
<label>Description</label>
<input type="text" name="subDomainDescription" placeholder="Description (Optional)" ng-model="mdnsCtrl.newDomain.description">
</div>
<button type="button" aria-label="Create" ng-click="mdnsCtrl.createDomain();"
ng-disabled="mdnsCtrl.createSubDomainForm.$invalid">
<span class="ng-scope">Create</span>
</button>
</div>
</form>
Tried few things like using $setUntouched() and $setPristine(). But nothing is working. Any help will be appreciated.
Adding a codepen example for this: code
Much Thanks.
`
Its not good practice to mix Angular with jQuery. Please read this great post: “Thinking in AngularJS” if I have a jQuery background?
You can easily achieve requested behavior by using ng-disabled="mdnsCtrl.formDisabled"
JS
var ctrl = this;
ctrl.formDisabled = false;
this.disable = function(){
ctrl.formDisabled = true;
};
this.enable = function(){
ctrl.formDisabled = false;
};
HTML
<div>
<label>Domain Name</label>
<input class="input-field" required type="text" name="subDomainName" placeholder="Domain Name"
ng-disabled="mdnsCtrl.formDisabled"
ng-model="mdnsCtrl.name" >
</div>
<div>
<label>Description</label>
<input class="input-field" type="text" name="subDomainDescription"
ng-disabled="mdnsCtrl.formDisabled"
placeholder="Description (Optional)" ng-model="mdnsCtrl.description">
</div>
Fixed Demo Codepen
I think you missed required attribute for Description input..
<input type="text" name="subDomainDescription" required ng-model="mdnsCtrl.newDomain.description">

How do I show/hide a div on field validation with parsley.js

So I guess for context, here is an example from the parsley.js documentation.
<form id="demo-form" data-parsley-validate>
<div class="first">
<label for="firstname">Firstname:</label>
<input type="text" name="firstname" data-parsley-range="[4, 20]" data-parsley-group="block1" />
<label for="lastname">Lastname:</label>
<input type="text" name="lastname" data-parsley-range="[4, 20]" data-parsley-group="block1" />
</div>
<hr></hr>
<div class="second">
<label for="fullname">Fullname:</label>
<input type="text" name="fullname" data-parsley-range="[8, 40]" data-parsley-group="block2" />
</div>
<div class="invalid-form-error-message"></div>
<input type="submit" class="btn btn-default validate" />
</form>
<script type="text/javascript">
$(document).ready(function () {
$('#demo-form').parsley().subscribe('parsley:form:validate', function (formInstance) {
// if one of these blocks is not failing do not prevent submission
// we use here group validation with option force (validate even non required fields)
if (formInstance.isValid('block1', true) || formInstance.isValid('block2', true)) {
$('.invalid-form-error-message').html('');
return;
}
// else stop form submission
formInstance.submitEvent.preventDefault();
// and display a gentle message
$('.invalid-form-error-message')
.html("You must correctly fill the fields of at least one of these two blocks!")
.addClass("filled");
return;
});
});
</script>
Let's say I have a hidden div called "checkmark". How would I show this div upon validation of the firstname field?
I should also clarify that I have read the documentation, but still don't understand how to accomplish what I'm trying to do here, so posting a link to the documentation is not really going to be helpful unless you are using it in your answer.
You should use Parsley's Events. Since you want to display or hide something based on a field validation, you should use parsley:field:success and parsley:field:error.
Working example (with jsfiddle):
<form id="demo-form" data-parsley-validate>
<div class="first">
<label for="firstname">Firstname:</label>
<input type="text" name="firstname" data-parsley-range="[4, 20]" data-parsley-group="block1" required />
<div class="hidden" id="checkmark">This message will be shown when the firstname is not valid </div>
<label for="lastname">Lastname:</label>
<input type="text" name="lastname" data-parsley-range="[4, 20]" data-parsley-group="block1" />
</div>
<hr></hr>
<div class="second">
<label for="fullname">Fullname:</label>
<input type="text" name="fullname" data-parsley-range="[8, 40]" data-parsley-group="block2" />
</div>
<div class="invalid-form-error-message"></div>
<input type="submit" class="btn btn-default validate" />
</form>
<script>
$(document).ready(function () {
$('#demo-form').parsley().subscribe('parsley:form:validate', function (formInstance) {
// if one of these blocks is not failing do not prevent submission
// we use here group validation with option force (validate even non required fields)
if (formInstance.isValid('block1', true) || formInstance.isValid('block2', true)) {
$('.invalid-form-error-message').html('');
return;
}
// else stop form submission
formInstance.submitEvent.preventDefault();
// and display a gentle message
$('.invalid-form-error-message')
.html("You must correctly fill the fields of at least one of these two blocks!")
.addClass("filled");
return;
});
$.listen('parsley:field:error', function(ParsleyField) {
if(ParsleyField.$element.attr('name') === 'firstname') {
$("div#checkmark").addClass('show').removeClass('hidden');
}
});
$.listen('parsley:field:success', function(ParsleyField) {
if(ParsleyField.$element.attr('name') === 'firstname') {
$("div#checkmark").addClass('hidden').removeClass('show');
}
});
});
</script>
And here's what I did:
Added a div with ìd=checkmark after the firstname field (with a hidden class, since you're using Bootstrap).
Added this block of javascript:
$.listen('parsley:field:error', function(ParsleyField) {
if(ParsleyField.$element.attr('name') === 'firstname') {
$("div#checkmark").addClass('show').removeClass('hidden');
}
});
$.listen('parsley:field:success', function(ParsleyField) {
if(ParsleyField.$element.attr('name') === 'firstname') {
$("div#checkmark").addClass('hidden').removeClass('show');
}
});
This code will listen to the validation of every input validated by Parsley. This means that when the field lastname fails, the code inside $.listen('parsley:field:error', function(ParsleyField) { will be executed. This is why I used an if to check if the attr name is firstname.
Then you show or hide the div based on the validation result.
Added required to the field, so the message is displayed when you click on the button.

How to validate form fields on its default values using serializeArray().?

Have a basic registration form, trying to validate it.
I am using form serializeArray() method and loop trough the form and find if the values are null.
HTML CODE
<form name="reg" id="regform">
<fieldset>
<label for="firstname">First Name</label>
<input type="text" name="firstname" value="First Name"/>
</fieldset>
<fieldset>
<label for="lastname">Last name</label>
<input type="text" name="lastname" value="Last Name"/>
</fieldset>
<fieldset>
<label for="date">Age</label>
<input type="text" name="age"/>
</fieldset>
</form>
JQUERY Code
var formElements = $("#regform").serializeArray();
$(formElements).each(function(x)
{
if(formElements[x]["value"] == "")
{
$("[name='" + formElements[x]['name'] +"']").addClass('error');
}
});
From the above code i am able to add the class ".error" when the value is null.
Now i want the code to check the text fields values are not the default values like in my case the default values are "First Name" "Last Name"..
So i want to check even for the default values and add error class to respective element and even focus back the cursor on the first null value text field
Thanks in advance
I highly suggest using http://docs.jquery.com/Plugins/Validation. You can test for various things, such as blank values, and even extend it to detect default values.
For example:
$.validator.addMethod("name", function(value) {
return value != "First Name";
}, 'Please enter your first name.');
Alternatively you can just test against a default value with jQuery's data() function:
Working Demo: http://jsfiddle.net/WpQ2n/2/
var input = $(".name"),
defaultval = input.data("default", input.val());
// Can't submit forms in jsfid, so i just used a click event.
// Change to .submit()
$("input[type='submit']").on("click",function(e){
if(input.val()== input.data("default")){
input.addClass("error");
}
else{
// Yay it validated...
input.removeClass("error");
}
e.preventDefault();
});

Categories