Angular - $viewValue or $modelValue in validation? - angularjs

I'm new to Angular and I want to check I am doing form validation right. I want to display an appropriate message when the user has entered more than 100 characters in an input field.
For this I am using $viewValue. Would $modelValue be better for validation since it is what has been 'saved' in the controller? Is there a better way to do this kind of specific validation?
<div class="form-group">
<label for="Forename" class="control-label col-md-2">Forename</label>
<div class="col-md-10">
<input id="forename" type="text" class="form-control"
name="detailsForename"
required
ng-maxlength="100"
ng-model="vm.customer.Forename" />
</div>
</div>
<li ng-show="detailsForm.detailsForename.$error.required">
Forename must be filled in
</li>
<li ng-show="!detailsForm.detailsForename.$valid">
Forename was not valid
</li>
<li ng-show="detailsForm.detailsForename.$viewValue.length > 100">
Forename must be no more than 100 characters
</li>
UPDATE: I had tried vm.person.Forename but for whatever reason it was not working. If it should work I shall revisit that as a possibility.
Using $valid is not enough because if the input field is empty I will get the error message for Required, and for > 100 (because $valid=false)

As noted in the ngMaxlength docs: "The validator sets the maxlength error key if the ngModel.$viewValue is longer than the integer ..."
So in your case that would be: detailsForm.detailsForename.$error.maxlength
You should never need to access an ngModel's $viewValue or $modelValue from the template.

Related

Deletion Error with Email Validation in Angular

So I've recently taken over an Angular Giving Form Application. I am running validation on the email field using ng-pattern and displaying the errors on blur with ngMessages. The validation works great, however once the validation passes as $valid if the user decides they need to make a change in their email and begin to delete part of the first deletion deletes the last character of the email as expected, but the second deletion deletes the entire field forcing the user to start from scratch.
The regex for ng-pattern is being set in the controller scope with the variable $scope.emailre
The files are much to large to place here but here is the link to the site I am working on for my client.
https://epiqa.moodyglobal.org/corporate/
Snippet of Angular controller:
myApp.controller('mainCtrl', function($scope, localStorageService, $http) {
$scope.emailre = /^(([^<>()\[\]\\.,;:\s#"]+(\.[^<>()\[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
Snippet of HTML Form:
<div class="row form-group">
<div class="col-sm-6">
<div>
<label class="label" for="txt_donorEmail">E-mail:</label>
<input ng-class="{ 'submitted-error' : givingForm.email.$invalid && submitted }" ng-model="email" type="text" id="email" name="email" class="textbox required full form-control" maxlength="50" ng-pattern="emailre" required />
</div>
<div ng-messages="givingForm.email.$error" ng-if="givingForm.email.$touched || submitted">
<div class="errorText" ng-message="required">This field is required</div>
<div class="errorText" ng-message="pattern">Enter a valid email</div>
</div>
</div>
</div>
I have tried changing the input type from type="text" to type="email" but when doing that any time the user types two (.) periods the field gets immediately deleted.
Please help any ideas are very welcome.
The behavior is caused by this section
$scope.$watch('email', function(value){
localStorageService.set('email',value);
$scope.emailValue = localStorageService.get('email');
});
By Angular documentation
The default behaviour in ngModel is that the model value is set to undefined when the validation determines that the value is invalid. By setting the allowInvalid property to true, the model will still be updated even if the value is invalid.
I'm not sure whether you want to save the invalid email into localStorage, though. Maybe you can add a check only update when the value is valid.

How do I dynamically set element name for form validation?

I have a form with input fields generated with an ng-repeat. The field names are set dynamically from the model. I cannot get validation to work.
Here is the input field that is repeated within ng-repeat:
<input class="form-control input" type="number" id="item.id" name="item.name" ng-change="ctrl.updateSub(item)" ng-model="item.qty" max="item.maxqty" min="0">
I am trying to validate against the max value, which is also set dynamically.
What I cannot find anywhere is how to set the name within the ng-show classes.
<div class="col-sm-2 error" ng-show="form.{{item.name}}.$invalid">
<small class="error" ng-show="form.{{item.name}}.$error.max">
You exceeded the maximum allowed
</small>
</div>
How am I supposed to handle the {{item.name}} bit?
Thanks in advance for any help or pointers.
Angular 1.3.12
Firstly form is a reserved keyword, you cannot use that as your form name.
Coming to your problem, unfortunately as of right now it is not possible to generate dynamic names for form inputs.
You can achieve what you want with the help of ng-form
Have a look at this example :
<form name="yourForm" >
<div ng-repeat="field in fields" ng-form="myInnerForm">
<input type="text" name="dynamic_input" ng-model="field.name"/>
<div ng-show="myInnerForm.dynamic_input.$dirty && myInnerForm.dynamic_input.$invalid">
The field is required.
</div>
</div>
</form>

Why name attribute required in AngullarJs validation

Friends, I am new to angularjs please explain why name attribute required for angularjs validation
<form name="lform" novalidate>
<input type="text" name="userName" ng-model="userName" required novalidate/>
<span style="color:red" ng-show="lform.userName.$dirty && lform.userName.$invalid">
<span ng-show="lform.userName.$error.required">Username is required.</span>
</span>
<br/>
</form>
If I remove name="userName" code not working, please explain this.
Update: If I remove "ng-model" it is not working, but I can change "ngmodel='newName'" is working, please explain this reason also.
This is just how HTML form works, name describe the parameter that will be sent to the server.
Angular's approach is to extend HTML and its behaviour, instead of inventing the wheel. Angular encapsulates "form" (see ngForm directive) and extend it. Because name is the unique id of an input in a form, it is also the unique id of the input in ngForm's collection.
ng-model is another directive that bind the value of the input into a variable in the current scope, it doesn't have to hold the same value as name.
Let's take your example and change ng-model:
<form name="lform" novalidate>
<input type="text" name="userName" ng-model="object.name" required novalidate/>
<span style="color:red" ng-show="lform.userName.$dirty && lform.userName.$invalid">
<span ng-show="lform.userName.$error.required">Username is required.</span>
</span>
<br/>
</form>
The validation will work, but the variable that will be updated in your scope is "object.name".
To sum it up, lform.userName holds the metadata and object.name will hold the actual data.
The answer is in your code.
<span ng-show="lform.userName.$error.required">Username is required.</span>
Angular is using the input name to store the error related information.
lform – your form name
username – your input name

angularjs ng-minlength validation is not working, form still being submitted

I am trying to submit the form on only successful validation.
validation is working for required but not working for ng-minlength
form input is invalid but form is still being submitted.
<form name="myForm" ng-submit="count = count + 1" ng-init="count=0" ng-app>
<div class="control-group" ng-class="{error: myForm.mobile.$invalid}">
<label class="control-label" for="mobile">Mobile</label>
<div class="controls">
<input type="text" name="mobile" placeholder="07XXXXXXXXX" ng-model="mobile" ng-minlength="11" required />
<span ng-show="myForm.mobile.$error.required" class="help-inline">Required</span>
<span ng-show="myForm.mobile.$error.minlength" class="help-inline">Mobile number should be minimum 11 character starting from 07</span>
</div>
</div>
<div class="control-group">
<div class="controls">
<input class="btn" type="submit" value ="submit" />
</div>
count: {{count}}<br />
<tt>myForm.$invalid = {{myForm.$invalid}}</tt><br/>
</div>
</form>
http://jsfiddle.net/pMMke/9/
what am I doing wrong.
I don't want to use submit button disable method.
This is what you are doing wrong: you are mixing two concepts, Angular validators and
HTML5 validators.
The required HTML5 validators, for instance, states that:
When present, it specifies that an input field must be filled out before submitting the form.
So, if you try to submit a form that has an input with this attribute, it will show a message explaining this to the user, and it will prevent the form from being sent. This is the behavior you want. Why isn't working for ng-minlength? Because ng-minlength is an Angular validator (you can tell because it begins with ng-), and it doesn't add any special behavior to the form. It simply set the input where it is located to invalid (and hence, the form), and let you decide what to do with it.
You have an option: you can use the pattern HTML5 validator, to specify the field requires at least 11 characters. It would like this:
<input type="text" pattern=".{11,}">
So when you submit a form containing this input, it will no be sent if the user has enter less than 11 characters.
But since we are it, and you are already using the pattern validator, you could use the regular expression in its full potential, and define something like:
<input type="text" pattern="07[0-9]{9}" />
Which will only admit values of 11 characters, that start by "07" and that contains only digits. I have modified your fiddle to show you how it would work: http://jsfiddle.net/helara/w35SQ/
I mistakenly used ngMaxlength="12" ngMinlength="6" instead of ng-minlength="6" ng-maxlength="12", it's working fine now.
Both ng-minlength & mg-maxlength works in AngularJS.
I've tested this in AngularJS version 1.3.
Make sure to use novalidate with <form> to disable browser's native validation.
This should work:
To enter mobile number
ng-show="myForm.mobile.$touched && myForm.mobile.$error.required"
For minimum length
ng-show="myForm.mobile.$touched && myForm.mobile.$error.minlength"
For maximum length
ng-show="myForm.mobile.$touched && myForm.mobile.$error.maxlength"
This work for me guys
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input ng-minlength="11" class="mdl-textfield__input" type="text" name="cpf" id="cpf" ng-model="avaliacao.cpf" ng-required="true" ng-pattern="/^\d+$/">
<label class="mdl-textfield__label" for="cpf">CPF *</label>
</div>
<p style="color: #d50000;" ng-show="myForm.cpf.$error.required && myForm.cpf.$dirty">Field Required</p>
<p style="color: #d50000;" ng-show="myForm.cpf.$error.pattern">Only numbers</p>
<p style="color: #d50000;" ng-show="myForm.cpf.$error.minlength">Min 11 Chars</p>
I'm facing the same issue, and I think you can only disable the button or ignore the entered value by yourself. You can also check the $valid property in your controller and ignore the value... It is not so nice, but I found no other way.

How to show 'invalid date' validation message for AngularStrap datetimepicker

I am able to validate my AngularStrap datetimepicker, but I cannot differentiate between a required validation failure and an invalid date failure. The only error that ever shows on screen is the required error, whether it is required or an invalid string. Is it possible in cases where a string has been entered that is invalid to show a different validation message? Here is my code :
<div class="control-group" ng-class="{error: form.BirthDate.$invalid}">
<label class="control-label" for="BirthDate">{{'_BirthDate_' | i18n}}</label>
<div class="controls">
<input id="BirthDate" name="BirthDate" title="BirthDate" type="text" ng-model="user.BirthDate" data-date-format="dd/mm/yyyy" bs-datepicker required>
<span ng-show="form.BirthDate.$dirty && form.BirthDate.$error.required">{{'_BirthDateRequired_' | i18n}}</span>
<!--<span ng-show="form.BirthDate.$dirty && form.BirthDate.$error.pattern">{{'_BirthDateInvalid_' | i18n}}</span>-->
</div>
</div>
What I want is something similar to the ng-pattern check but specific to the datetimepicker.
first of all, I think this has no real link with the date picker or not, if I understand your problem, you are trying to display different messages according to the error that lead to the $invalid for the form
If it's the case, the code you provided will only show a message when the date is invalid (but only because you commented the part for the pattern ;) )
I was super lazy while testing, so I didn't use the datepicker, you'll have to enter a date manually, but I did this fiddle : http://jsfiddle.net/DotDotDot/ELf5A/2/
As I didn't know exactly in what context you were using it, I used different methods to display validation error messages
The HTML part is simple. There is a form, two fields required, one with a pattern check for the date, the other only for the required validation. I added 2 error messages for the date, one displayed when the form hasn't been touched, telling you what format is expected, the other only shows up when the pattern is wrong.
You can click on the button to check the whole validation and then show another message, which will tell you if the form is valid or not, and if not, if it's because of the pattern of the date.
<div ng-controller='theCtrl'>
<form name='theForm'>
Enter something here : <input type='text' ng-model='someField' name='someField' required /> <br/>
Enter a date here : <input type='text' ng-model='theDate' name='theDate' ng-pattern='datePattern' required />
<span ng-show='theForm.theDate.$error.pattern'>Your date format is invalid, please check it again</span>
<span ng-show='theForm.theDate.$pristine'>Enter a valid date here : DD/MM/YYYY</span>
<br/> <input type='button' ng-click='validation(theForm)' value='Try to validate me!' />
<br /> {{errorMsg}}
</form>
</div>
The JS part is not very complicated either. When you click on the button, the form is being sent to the validation function, which will actually do all the checks you want, I only did the one corresponding to the pattern, but you could totally check whatever you want about the validation
$scope.validation=function(aForm){
//console.log(aForm)
if(aForm.theDate.$error.pattern)
$scope.errorMsg='The pattern you entered isn\'t good enough, try again !'
else{
if(aForm.$invalid)
$scope.errorMsg='Something is invalid, please check all the fields !'
else//valid
{
$scope.errorMsg='Not bad !'
alert("good job !")
//maybe you can also submit this form here ;)
}
}
}
This validation function could totally be used as the trigger in a ng-show/ng-hide too, this is why I also added another function :
$scope.whatToDisplay=function(aForm){
if(aForm.$valid)
return 'valid';
if(aForm.theDate.$error.pattern)
return 'date';
if (aForm.$invalid)
return 'notdate';
}
This will return a string corresponding to what is happening during the validation, which will be handled with ng-show :
<span ng-show='whatToDisplay(theForm)=="date"'>Displayed if the date is wrong</span>
<span ng-show='whatToDisplay(theForm)=="notdate"'>This is displayed if the form is invalid, but not because of the date format</span>
<span ng-show='whatToDisplay(theForm)=="valid"'>Displayed if the form is valid</span>
To summarize a bit, you can use 4 different methods
A validation function triggered with a click (useful for submit buttons), corresponding to the validation() function in my fiddle
A function associated with some ng-show, which will automatically watch every change, like the whatToDisplay() function
The ng-show associated with only the form attributes, like what you were doing with your code
The class automatically applied to the form ( I didn't explain it, but you can see it in the fiddle, the border change if the pattern is wrong or if it's only invalid )
Sorry, I had some difficulties to make this short, I let you play with the code, it's easier to understand that way, I hope this will help you
You should use ngMessages in AngularJS 1.3 to do the error messaging with less code and complexity. The bs-angular directive creates a message for the "date" string value of ng-message in your list of messages.
<div class="control-group" ng-class="{error: form.BirthDate.$invalid}">
<label class="control-label" for="BirthDate">
{{'_BirthDate_' | i18n}}
</label>
<div class="controls">
<input id="BirthDate" name="BirthDate" title="BirthDate" type="text"
ng-model="user.BirthDate" data-date-format="dd/mm/yyyy"
bs-datepicker required>
<span ng-show="form.BirthDate.$dirty && form.BirthDate.$error.required">{{'_BirthDateRequired_' | i18n}}</span>
</div>
<div class='alert alert-danger' ng-messages='myForm.BirthDate.$error'
ng-if='!myForm.BirthDate.$valid'>
<div ng-message="date">Please enter a valid date</div>
<div ng-message="required">Birthdate is required</div>
</div>
</div>
This code helps to show the invalid datetime error message
$scope.date=='Invalid Date'
{
err('Your error message');
}

Resources