I've been writing a web application and i've got three different forms.
I've put some validation on them but it seems that after a recent update everything gets ignored.
Validation that still works:
-checks if input isn't empty
-Maxlength
Validation that stopped working:
-Patterns
-input type email ( This is the one that surprises me the most), it doesn't
check for an '#' anymore or any other checks it does if you put your input
type to email.
example code = `
<div class="form-group" [ngClass]="{ 'has-error': submitted && (!trainer.email || emailExists)}">
<label for="email">E-mail*</label>
<input [(ngModel)]="trainer.email" type="email" class="form-control" name="email" maxlength="50" placeholder="Enter e-mail adress" />
<div *ngIf="submitted && !trainer.email" class="help-block">E-mail adress is required</div>
<div *ngIf="submitted && emailExists" class="help-block">E-mail adress "{{emailInUse}}" is already in use</div>
</div>
`
I've removed everything from the html and put in just a single email input type and it still doesn't work. I guess it goes wrong somewhere else in my code but I don't know where to start looking. This example is for my trainer class but I have 2 other html files that also suddenly stopped working so that adds to my conclusion that the problem isn't in the HTML.
Is there any common bug that causes these kinds of problems?
Thanks
Related
I cant seem to figure out what the issue is I have a form input like so..
<div class="form-group">
<label class="form-label" for="password">Change Password</label>
<input type="password" class="form-control" id="password" name="password" [(ngModel)]="password" pattern="^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$#$!%*?&])[A-Za-z\d$#$!%*?&]{8,}">
</div>
and then below it I have..
<div *ngIf="!password.valid && (password.dirty || password.touched)" class="password-reminder">
<p>Your password must be over 8 characters and include an uppercase letter, a number and a special character</p>
</div>
now if I dont have a valid password and its been touched nothing happens, but I do know the validation is working because the button on my form is disabled until I put the password In correctly..
Not sure what I'm doing wrong? why wont the div show itself??
EDIT
It works if I take away && (password.dirty || password.touched) but I only want to show the message If they enter a not valid password and untouch..
I can see in my dev tools that the classes are being applied
but it doesnt dissapear when my password is valid..
EDIT 2
I am using template driven forms
Any help would be appreciated.
Create a template reference variable on your Input field.
<input #passwordField="ngModel" type="password" class="form-control" id="password" name="password" [(ngModel)]="password" pattern="^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$#$!%*?&])[A-Za-z\d$#$!%*?&]{8,}">
Make sure to update the references to password with passwordField in your template.
<div *ngIf="!passwordField.valid && (passwordField.dirty || passwordField.touched)" class="password-reminder">
<p>Your password must be over 8 characters and include an uppercase letter, a number and a special character</p>
</div>
Since you are using template driven forms, there is no corresponding password property in your component, and hence most use a template reference variable. You can find a demonstration of this method here.
Try this.
Add this part to the input field(a template reference variable)
#passwordField="ngModel"
<div class="form-group">
<label class="form-label" for="password">Change Password</label>
<input type="password" class="form-control" id="password" name="password" [(ngModel)]="password" pattern="^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$#$!%*?&])[A-Za-z\d$#$!%*?&]{8,}" #passwordField="ngModel">
</div>
<div *ngIf="!passwordField.valid && (passwordField.dirty || passwordField.touched)" class="password-reminder">
<p>Your password must be over 8 characters and include an uppercase letter, a number and a special character</p>
</div>
Then it should work. Read more about template driven forms in here.
As Others said You should use an element variable like #passwordElement="ngModel"
have a look at stackblitz
As others have said, you need to provide the template reference in your password div:
#password=ngModel
Also add required to your password tag like so:
<input type="password" class="form-control" id="password" name="password" [(ngModel)]="password" #password=ngModel pattern="^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$#$!%*?&])[A-Za-z\d$#$!%*?&]{8,}" required>
I just tested it out and it works on my end.
Create a temp reference variable. something like
<input #password=ngModel />
then use #password to do validation. Also make sure you are applying touched and dirty class correctly.
I have Custom input component with validation with ngMessages,FormController and ng-required:
<div class="col-sm-9 col-xs-12">
<input
id="{{$ctrl.fieldName}}"
name="{{$ctrl.fieldName}}"
class="form-control"
type="text"
minlength="{{$ctrl.minLength}}"
maxlength="{{$ctrl.maxLength}}"
ng-required="{{$ctrl.isRequired === 'true'}}"
ng-model="$ctrl.value"
ng-change="$ctrl.form.$submitted = false;"
>
<div
ng-messages="$ctrl.form[$ctrl.fieldName].$error"
ng-if="$ctrl.form.$submitted"
>
<span class="help-block" ng-message="required">
Field is required
</span>
<span class="help-block" ng-message="minlength">
Minimum length of field: {{$ctrl.minLength}}
</span>
<span class="help-block" ng-message="maxlength">
Maximum length of field: {{$ctrl.maxLength}}
</span>
</div>
</div>
Which is used in this way:
<act-text-field
form="heroAddForm"
field-name="name"
min-length="3"
max-length="15"
is-required="true"
errors="$ctrl.errors.name"
ng-model="$ctrl.hero.name">
</act-text-field>
What I want to achieve is validation fires when user clicks submit button. And it works, validation fires also for required field name, but also for field description which is not required:
<act-text-field
form="heroAddForm"
field-name="description"
max-length="50"
is-required="false"
errors="$ctrl.errors.description"
ng-model="$ctrl.hero.description"
></act-text-field>
Also for this field validation messages are visible, although field description is valid, cause I add class has-error to invalid fields:
<div class="form-group"
ng-class="{'has-error': $ctrl.form.$submitted && (!$ctrl.form[$ctrl.fieldName].$valid)}"
>
<!-- rest of code -->
You can easily reproduced this wrong behaviour in my Plunker: Custom input demo app with validation states (I know it has other mistakes). I think ng-message="required" should not be visible, because field description is not required. I know I can add some ng-ifs to code to by-pass it, but I think I make a mistake somewhere which I can't see. Do you see where I made a mistake? Thank you in advance for every help.
I found a solution, again I forgot to include ngMessages. Without it, my code went crazy, I apologize for wasting your time :)
I use angular ng-messages to display validation messages
Consider the following code:
<ul ng-messages="formToValidate.fieldToValidate.$error" ng-messages-multiple>
<li ng-message="pattern">Invalid pattern</li>
<li ng-message="minlength, maxlength">Should contain no less than 7 and no more than 100 chars</li>
<li ng-message="!pattern && !minlength && !maxlength && onlyAfterAllOtherPassedValidation">
This validation message is shown only when all the other validations have passed and validation fails on onlyAfterAllOtherPassedValidation
</li>
</ul>
I want to show the last validation message only if all other validations have passed and validation fails on onlyAfterAllOtherPassedValidation.
And I do not know whether it's possible at all to pass complex condition to ng-message
Any suggestions as well as workarounds are welcomed as long as I still can use ng-messages
You could use ng-if on the element holding the message, eg
<li ng-if="!formToValidate.fieldToValidate.$error.required && !formToValidate.fieldToValidate.$error.minLength && !formToValidate.fieldToValidate.$error.maxLength" ng-message="onlyAfterAllOtherPassedValidation">
This validation message is shown only when all the other validations have passed and validation fails on onlyAfterAllOtherPassedValidation
</li>
The solution proposed by JonMac1374 of course work. But it is better to solve this problem once and for all. I advise you to pay attention to the directive use-form-error. It helps to build their own check.
Live example on jsfiddle.
<form name="ExampleForm">
<label>Password</label>
<input ng-model="password" name="password" minlength="2" pattern="^\d*$" required use-form-error="onlyAfterAllOtherPassedValidation" use-error-expression="!ExampleForm.password.$error.required && !ExampleForm.password.$error.minlength && !ExampleForm.password.$error.pattern"
/>
<pre>{{ExampleForm.password.$error|json}}</pre>
<div ng-messages="ExampleForm.password.$error" ng-messages-multiple="true" class="errors">
<div ng-message="required">
Your required is wrong
</div>
<div ng-message="pattern">
Your pattern is wrong
</div>
<div ng-message="minlength">
Your minlength is wrong
</div>
<div ng-message="onlyAfterAllOtherPassedValidation">
Your onlyAfterAllOtherPassedValidation
</div>
</div>
</form>
THE SITUATION:
I have many forms in my angular app and i need an effective error messages system. I find ngMessages useful.
But i would like that the error messages appears only when the user blur out of a field, in order to be less 'aggressive'.
ATTEMPT:
Attempt using debouncing at 1000ms
<label class="item item-input">
<span class="input-label"> Email alternative </span>
<input type="email" name="email_alternative" ng-model="profile_edited.email2" ng-model-options="{ debounce: 1000 }">
</label>
<!-- Error messages for ALTERNATIVE EMAIL -->
<label class="item item-input" ng-show="profile_edit_form.email_alternative.$error.email">
<div class="form-errors" ng-messages="profile_edit_form.email_alternative.$error" role="alert" ng-if='profile_edit_form.email_alternative.$dirty'>
<div class="form-error" ng-message="email">Your email address is invalid</div>
</div>
</label>
In this way it will properly appears the error message if the user is not typing anything for one second.
Is the closest i get to what i want.
But sometimes for some users it may take a bit more than 1 second to type the character #. The error message may then suddenly appear and confuse the user.
But if i set the debouncing time 2 or 3 seconds is way too much. It may appear when the user is already writing in another field.
I need that the error messages fire ONLY AFTER the user blur out of the field.
THE QUESTION:
How can i fire ngMessages on blur?
$dirty will evaluate to true if the text is changed in the input box. To check for the blur you can use the $touched property of the input field.
Checkout the forms documentation to see all form (input) properties: https://docs.angularjs.org/guide/forms
You can use $dirty and ng-show to display messages when input is dirty.
<input type="text" name="modelName" ng-model="modelName" required />
<div ng-messages="myForm.modelName.$error" ng-show="myForm.modelName.$dirty">
<div ng-message="required">Please Fill this model.</div>
</div>
I'm trying to toggle an error area on my form that only triggers once there is some input, it's a bit silly to have the errors all appear if the user hasn't started typing yet.
<form name="registerForm">
<input type="email" name="email" ng-model="email" required />
</form>
<span ng-show="registerForm.email.$invalid">
Invalid email.
</span>
This works fine once I'm typing but I want it to show no errors if the input is empty. I've tried using the model ng-hide="!email.length" but can't get it to work.
<span ng-show="registerForm.email.$invalid && registerForm.email.$dirty>
Try this:
<span ng-show="registerForm.email.$invalid && email>