Input and checkbox validation using AngularJS - angularjs

I have a page with a check box representing "All dates" and two input fields which represent the start date and end dates. When the page first loads the check box is unchecked. The requirement is if the check box is unchecked and there is nothing in the start and end date fields a message must display to the user.
This is what I have for the check box and input fields and the error message:
<input name="dateSelectAll" type="checkbox" ng-model="$parent.vm.selectAllDates" ng-required="$parent.vm.selectedReport.Parameters.StartDate == null || $parent.vm.selectedReport.Parameters.EndDate == null" />All Available Dates
<input name="beginningDate" type="text" class="form-control form-field" datepicker-popup="dd-MMM-yyyy"
ng-disabled="$parent.vm.selectAllDates"
ng-model="$parent.vm.selectedReport.Parameters.StartDate"
is-open="beginningDateOpened"
ng-required="$parent.vm.selectAllDates == false"
close-text="Close" />
<input name="endDate" type="text" class="form-control form-field" datepicker-popup="dd-MMM-yyyy"
ng-disabled="$parent.vm.selectAllDates"
ng-model="$parent.vm.selectedReport.Parameters.EndDate"
is-open="endDateOpened"
ng-required="$parent.vm.selectAllDates == false"
close-text="Close" />
Please select
This is what I have in the controller at the beginning:
vm.selectAllDates = false;
This is what I have in the submit function:
if ($scope.reportForm.$valid) {
//do stuff
}
else
{
$scope.reportForm.submitted = true;
}
If the form is "valid" when I hit the submit button a modal window will display.
What's happening is the page loads and if I don't enter in dates or check the check box and I hit submit, the message appears and I can't submit which is fine.
When I check off the check box the message stays but I can submit.
When I uncheck the check box and enter dates the message stays but I can submit.
How do I hide the message once any of the conditions have been met? Sorry! I'm still a newbie at Angular.

I'm not sure this is "best practice", but you could use your form's validity to show/hide the message (since you've already setup the validation conditions).
You should be able to use something like
<p ng-show='reportForm.$valid'>Error Message</p>
Alternatively, you can manually setup a $watch on your form's validity to do any other logic you might need
$scope.$watch('reportForm.$valid', function(isValid) {
//change some value to show/hide the message
//any other logic for a change in validity
});

Okay, I figured it out.
For the checkbox I put this:
<input name="dateSelectAll" type="checkbox" ng-model="$parent.vm.selectAllDates" ng-required="vm.selectedReport.Parameters.StartDate == null && vm.selectedReport.Parameters.EndDate == null" />All Available Dates
For the start date I put this:
<input name="beginningDate" type="text" class="form-control form-field" datepicker-popup="dd-MMM-yyyy"
ng-disabled="$parent.vm.selectAllDates"
ng-model="$parent.vm.selectedReport.Parameters.StartDate"
is-open="beginningDateOpened"
ng-required="$parent.vm.selectAllDates == false"
close-text="Close" />
For the end date I put this:
<input name="endDate" type="text" class="form-control form-field" datepicker-popup="dd-MMM-yyyy"
ng-disabled="$parent.vm.selectAllDates"
ng-model="$parent.vm.selectedReport.Parameters.EndDate"
is-open="endDateOpened"
ng-required="$parent.vm.selectAllDates == false"
close-text="Close" />
And for the message I put this:
<div ng-show="reportForm.submitted || reportForm.dateSelectAll.$touched || reportForm.beginningDate.$touched
|| reportFrom.endDate.$touched">
<span class="error" ng-show="reportForm.dateSelectAll.$error.required || reportForm.beginningDate.$error.required || reportFrom.endDate.$error.required">Please select a Dissolved date</span>
</div>
I kept the code in the controller the same as what I put in my original post.
Thanks #ryanyuyu for answering so quickly. And thanks #DrCord for the info. I'll have to remember that!

Related

How to reset the value of validation error based on radio button

I have the below code to select Yes\No for selecting the options from Multi Select dropdown. But It is required only when I select the Yes Option from radio. Otherwise the validation message should disappear when I move from Yes to No. (I am disabling the Multi Select in script when the user selects the No optio)
<input id="Option1" name="MyRadio" ng-model="MyRadioData" type="radio" title="Yes" value="Yes" ng-click="Flip('Yes')" />Yes
<input id="Option2" name="MyRadio" ng-model="MyRadioData" type="radio" title="No" value="No" ng-click="Flip('No')" />No
<select id="MultiSelect1" kendo-multi-select name="MultiSelect1" k-value-primitive="true" k-max-selected-items="30" k-placeholder="multiPlaceHolderVendor"
k-ng-model="MyOptions" k-data-source="MyOptionsDS" ng-required="MyRadioData == 'Yes'" validationmessage="Required"></select>
<span data-for="MultiSelect1" data-role="validator"></span>
But the above code is not working though I have used ng-required option for multi select.
Appreciate any help.
If <span data-for="MultiSelect1" data-role="validator"></span> is where messages put, you can handle with ng-show ng-hide like this:
UPDATE
<!-- if you choose no it hide-->
<span ng-hide="MyRadioData == 'No'" data-for="MultiSelect1" data-role="validator"></span>
<!-- if you choose yes it hide-->
<span ng-hide="MyRadioData == 'Yes'" data-for="MultiSelect1" data-role="validator"></span>
Here is a plnkr with a button but it does the same, i will help you how this work.

ng-invalid after selecting date from datepicker

ng-invalid after selecting date from datepicker, but becomes valid if typed. Please help.
I worked around this by hiding the datepicker and showing an empty input text field when the value is null and then swapping/showing the datepicker when it is clicked.
<input
ng-if="my_date || set_my_date"
type="text"
id="my_date"
name="my_date"
datetime-picker="MM/dd/yyyy h:mma"
is-open="my_date"
ng-focus="set_my_date = true"
class="form-control"
ng-model="my_date"
placeholder="my date"
ng-readonly="true"
ng-required="true"
/>
<input
ng-if="!my_date && !set_my_date"
class="form-control"
placeholder="my date"
ng-click="set_my_date = true"
/>
ng-invalid class is added from angular when a required field is invalid (e.g empty), make sure the ng-model relative field , formvalue.workshopeDate, is correctly populated when you trigger the click.

$dirty vs $invalid: What is the difference?

I am a novice in angular. I am confused by $dirty and $invalid, they almost sound the same.
What is the difference between $dirty and $invalid used in email ng-model? Below is the scenario. It's an example form W3Schools.
<form ng-app="myApp" ng-controller="validateCtrl" name="myForm" novalidate>
<p>
Username:<br>
<input type="text" name="user" ng-model="user" required>
<span style="color: red" ng-show="myForm.user.$dirty && myForm.user.$invalid">
<span ng-show="myForm.user.$error.required">Username is required.</span>
</span>
</p>
<p>
Email:<br>
<input type="email" name="emaill" ng-model="email" required>
<span style="color: red" ng-show="myForm.email.$dirty && myForm.email.$invalid">
<span ng-show="myForm.email.$error.required">Email is required.</span>
<span ng-show="myForm.email.$error.email">Invalid email address.</span>
</span>
</p>
<p>
<input type="submit" ng-click="Count()"
ng-disabled="myForm.$invalid" title="Submit" value="Submit">
</p>
</form>
EDIT 1:
I am wondering if I change the ng-model name from email to email8 it's not working anymore.
<input type="email" name="emaill" ng-model="email8" required>
Whether the validation is doing by myForm HTML element name which is not defined using ng attribute. How does it work?
ng-show="myForm.email.$dirty && myForm.email.$invalid"
$dirty: It will be TRUE, if the user has already interacted with the form.
$invalid: It will be TRUE, if at least one containing form and control is invalid.
Source
Also on Angular Docs
After the update in the Question...The validation is being done on the form element name. All the ng-models inside a form is tracked and that is how it is working.
Also changing a ng-model name will have no impact on validation. I tried your link and it works for me. That has to work.
$dirty means the user has changed the input value, $invalid means the address itself is invalid. Therefore the error is only shown if the user has actively changed the input value to either an empty or invalid value.
$dirty is True if user has already interacted with input. And $invalid is true if the the input is not a valid email address
$error is the object of errors where the key is the field validation name and value is the actual error message
<input type="email" name="emailName" ng-model="email" required>
for this example myForm.emailName.$error.email = true if email is not matched with format.
myForm.emailName.$error.required = true if you haven't added anyhting in input field
you can check valid or not of the field directly by using myForm.emailName.$valid but
the problem in your case is they want to show the user what is the error by having two cases. so they entered into $error object to check for the error is required email or invalid email
1.Email is required.
2.Invalid email address.
so they used $error object.
this is how myForm.emailName looks:
{"$viewValue":"ss","$validators":{},"$asyncValidators":{},"$parsers":[],"$formatters":[null],"$viewChangeListeners":[],"$untouched":false,"$touched":true,"$pristine":false,"$dirty":true,"$valid":false,"$invalid":true,"$error":{"email":true},"$name":"emailName","$options":null}
I think the example provide by you explains a lot.
You have done mistake That is why it was not working , can you see below code which you have written
<pre>
<input type="email" name="emaill" ng-model="email8" required>
<ng-show="myForm.email.$dirty && myForm.email.$invalid">
</pre>
Why it was not working because input name you have given "emaill" and in myForm.email.$dirty you have given "email" If both names should be same then it will work fine
<pre>
<input type="email" name="emaill" ng-model="email8" required>
<ng-show="myForm.emaill.$dirty && myForm.emaill.$invalid"></pre>

Clear input fields when checkbox is checked

I have a check box and two input fields. Either the check box has to be checked or the two input fields have to be filled in. I'm doing validation using Angular i.e. ng-show, ng-required.
When the checkbox is checked the two input fields are disabled i.e. ng-disabled="$parent.vm.selectAllDates".
Now I also have to clear any data that may have been entered into the textboxes.
The check box is not checked on page load. It is set in the controller like this: vm.selectAllDates = false;
Is there some way to clear the input fields when the check box is checked in Angular?
EDIT
I've added what I tried doing using your example
Check box:
<input name="dateSelectAll" type="checkbox"
ng-model="$parent.vm.selectAllDates"
ng-required="vm.selectedReport.Parameters.StartDate == null && vm.selectedReport.Parameters.EndDate == null" />All Available Dates
Start date input:
<input name="beginningDate" type="text" class="form-control form-field" datepicker-popup="dd-MMM-yyyy"
ng-disabled="$parent.vm.selectAllDates"
ng-model="$parent.vm.selectedReport.Parameters.StartDate"
is-open="beginningDateOpened"
ng-required="$parent.vm.selectAllDates == false"
ng-change="$parent.vm.selectedReport.Parameters.StartDate = $parent.vm.selectAllDates ? '' : $parent.vm.selectedReport.Parameters.StartDate"
close-text="Close" />
End date:
<input name="endDate" type="text" class="form-control form-field" datepicker-popup="dd-MMM-yyyy"
ng-disabled="$parent.vm.selectAllDates"
ng-model="$parent.vm.selectedReport.Parameters.EndDate"
is-open="endDateOpened" ng-change="$parent.vm.selectedReport.Parameters.EndDate = $parent.vm.selectAllDates ? '' : $parent.vm.selectedReport.Parameters.EndDate"
ng-required="$parent.vm.selectAllDates == false && $parent.vm.selectedReport.Parameters.EndDate == null"
close-text="Close" />
One really odd thing was I wanted to see what was happening so I added
{{$parent.vm.selectedReport.Parameters.StartDate = $parent.vm.selectAllDates ? '' : $parent.vm.selectedReport.Parameters.StartDate}}
after the StartDate input field. When I selected a date, the date was added to the input field as well as underneath the input. When I clicked the check box, the date was removed from the input field as well as from under the input field. So it worked! But the minute I removed the above code from under the input field it stopped working...I was like wha?
The simple approach is to use ngChange directive on checkbox and set text input model to empty string if checkbox is checked. Something like this:
<input type="text" ng-model="data.test" ng-disabled="data.check">
<input type="checkbox" ng-model="data.check" value="one"
ng-change="data.test = data.check ? '' : data.test">
Demo: http://plnkr.co/edit/pKGui2LkP487jP0wOfHf?p=preview
I ended up building off of what you showed me #dfsq. Thank you very much for your help!
I ended up creating a function for ng-change and putting it on the check box:
<input name="dateSelectAll" type="checkbox"
ng-model="$parent.vm.selectAllDates"
ng-change="vm.clearFields()"
ng-required="vm.selectedReport.Parameters.StartDate == null && vm.selectedReport.Parameters.EndDate == null" />All Available Dates
Then in my controller I added the code to clear both start and end date input fields:
vm.clearFields = function () {
vm.selectedReport.Parameters.StartDate = vm.selectAllDates ? '' : vm.selectedReport.Parameters.StartDate;
vm.selectedReport.Parameters.EndDate = vm.selectAllDates ? '' : vm.selectedReport.Parameters.EndDate;
}
If there is a better way, please let me know. Thanks again!

Angular.js: Set form fields "dirty" upon submission

How can I make a form input to become dirty as the form is submitted?
This is needed so that the input fields with an $error can be
Example:
name: <input type="text"
ng-model="user.name"
ng-model-options="{ updateOn: 'blur' }"
name="uName"
required /><br/>
As the form is submitted, I want this field - if left blank - to be rendered using the "invalid & dirty" style:
.css-form input.ng-invalid.ng-dirty {
background-color: #FA787E;
}
Disable the submission button until form is dirty and the form items are valid.
<button type="submit" class="btn btn-primary" ng-disabled="myFrmName.$invalid || !myFrmName.$dirty">Submit Form</button>
Using ng-disabled will disable the form submission button while the form is $invalid or the form has yet to be touched (not $dirty).
EDIT
I usually do something like this to display an error next to the required field:
<input type="text" name="myField" required ng-class="{true : 'has-error'}[hasError(myFrmName.myField.$error.required,myFrmName.myField.$dirty)]>
<span ng-if="hasError(myFrmName.myField.$error.required,myFrmName.myField.$dirty)">Required!</span>
Then in your controller:
$scope.hasError = function(e,d){ // e = $error, d = $dirty
if(angular.isDefined(e))
return e && d;
return false;
} // end hasError
Example with ngMessages (Angular 1.3)
<input type="text" name="myField ng-model="fields.myField" ng-class="{true : 'has-error'}[hasError(myFrmName.myField.$error.required,myFrmName.myField.$dirty)] required>
<ng-messages for="myFrmName.myField.$error" ng-if="myFrmName.myField.$dirty">
<ng-message when="required" class="text-danger">The field is required!</ng-message>
</ng-messages>
The great thing about ngMessages is that all you need to do is add more <ng-message> tags for each type of validation for the field and just change the when attribute approrpriately.
<ng-message when="minlength">Your entry is too short.</ng-message>
Angular will display the correct message based upon whether or not the when is in the $error object for the field.
You can use $submitted flag of the form to highlight the field if the form is submitted and is empty.
<input type="text"
ng-model="user.name"
ng-model-options="{ updateOn: 'blur' }"
name="uName"
ng-class={'has-error': yourFormName.$submitted && !yourFormName.uName.$valid}
required />
Or I guess just setting the form's dirty flag to true in your controller might do the same work. But I believe this implicitly changes the DOM as it adds a class to form which is not a good practice in angular.
$scope.yourForm.$dirty = true;
in case you would like to do that programatically, there is a method named "$setDirty()" you could use for that purpose.
https://docs.angularjs.org/api/ng/type/form.FormController

Resources