6

I got a form with Password and Confirm Password fields and I would like to validate that they got the same value without extra buttons.

Here is my code:

    <input type="password" id="password" name="password" ng-model="password" placeholder='Password'
    ng-pattern="/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$@$!%*?&])[A-Za-z\d$@$!%*?&]{6,20}/";
    ng-blur="focused4 = false" ng-focus="focused4 = true"
    ng-minlength="6" ng-maxlength="20" required>
    <span ng-show="focused4 && !regForm.password.$valid"><error>6 to 20 characters, one numeric digit, one upper case letter, one lower case letter and a special character</error></span>
</td>
<td align="left">
    <span ng-show="regForm.password.$valid"><valid>&#10004;</valid></span>
    <span ng-show="!regForm.password.$valid"><error>&#10060;</error></span>
</td>
</tr>
<tr>
<td align="left">
    <input type="password" id="passwordConfirm" name="passwordConfirm" ng-model="passwordConfirm" placeholder="Confirm Password" 
    ng-pattern="/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$@$!%*?&])[A-Za-z\d$@$!%*?&]{6,20}/";
    ng-blur="focused5 = false" ng-focus="focused5 = true"
    ng-minlength="6" ng-maxlength="20" required>
    <span ng-show="focused5 && !regForm.passwordConfirm.$valid" ><error>Passwords are not correct or don't match</error></span>
    <span ng-show="regForm.password.value != regForm.passwordConfirm.value"> NOT MATCHED </span>
    <span ng-show="regForm.password.value == regForm.passwordConfirm.value"> MATCHED </span>
</td>

And this how it looks like (I think, there are no updates while I'm changing the value): enter image description here

I researched:

Comparing two input values in a form validation with AngularJS

Angularjs check and compare two input field values

but itlooks like something not working in my case... I also researched directive AngularJS compare password fields but I would like to make the page as simple as possible.

Any advises?

UPDATE 1

If I'm changing my password confirmation field to:

<td align="left">
    <input type="password" id="passwordConfirm" name="passwordConfirm" ng-model="passwordConfirm" placeholder="Confirm Password" 
    ng-pattern="password";
    ng-blur="focused5 = false" ng-focus="focused5 = true"
    ng-minlength="6" ng-maxlength="20" required>
    <span ng-show="focused5 && !regForm.passwordConfirm.$valid" ><error>Passwords are not correct or don't match</error></span>
    <span ng-show="!regForm.passwordConfirm.$valid"> NOT MATCHED </span>
                        <span ng-show="regForm.passwordConfirm.$valid"> MATCHED </span>
</td>

there is a one small bug there: 1) Add password 2) Add Confirmation password == password 3) Delete password 4) System still shows matching 5) Add password which is not valid (like too short) 5) System still shows that they are matching

enter image description here

But, it's ok for me, cause when the password validation passed - confirmation shows error again and I can't save value. If there is better solution, just let me know.

Community
  • 1
  • 1
Aleksey Kiselev
  • 331
  • 1
  • 7
  • 21
  • We lack informations, maybe the call of checkPasswordMatch(value) is incorrect ? Don't you need to call it with the password: checkPasswordMatch(password) ? What does this function do ? – Groben Apr 06 '17 at 15:33
  • oops, `data-validate-function='checkPasswordMatch(value)' ` left our my experiments, updated (same result) – Aleksey Kiselev Apr 06 '17 at 15:57

3 Answers3

10

I accomplished client-side form validation with AngularJS like this:

<form name="userForm">
    <div class="form-group">
      <div>
        <input type="text" class="form-control" placeholder="Username" ng-model="formData.username" required />
      </div>
      <div>
        <input type="email" id="email" name="email" class="form-control" placeholder="Email Address" ng-model="formData.email" required />
      </div>
      <div>
        <input name="password" type="password" class="form-control" placeholder="Password" ng-model="formData.password" ng-pattern="/(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z])/" required />
        <span ng-show="!userForm.password.$error.required &&  userForm.password.$error.pattern && userForm.password.$dirty">Must contain one lower &amp; uppercase letter, and one non-alpha character (a number or a symbol.)</span>
      </div>
      <div>
        <input name="confirm_password" type="password" class="form-control" placeholder="Confirm Password" ng-model="formData.confirmPassword" ng-pattern="formData.password" required />
        <span ng-show="formData.password != formData.confirmPassword">Your passwords must match.</span>
      </div>
      <div>
        <button type="submit" id="create-user-button" ng-disabled="formData.password != formData.confirmPassword" ng-click="createUser()">Create User</button>
      </div>
    </div>
  </form>

The first step is to add the required to each form input. I had some issues getting this to activate and I believe you must also end your input fields with /> for this to work properly. This will prevent the <button type="submit"... from functioning without those fields being filled. The required attribute will prevent submission of the form on most browsers using browser provided error messages to the user.

If you wish to include symbol/number and capitalization requirements in your password fields, you can add ng-pattern="/(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z])/" to your first password input field.

The span that follows <span ng-show="!userForm.password.$error.required && userForm.password.$error.pattern && userForm.password.$dirty">Must contain one lower &amp; uppercase letter, and one non-alpha character (a number or a symbol.)</span> displays a message to the user that the PW field requires those parameters to be valid.

Next, include ng-pattern="formData.password" in the password confirmation input field, and this validates that the string typed in that field matches the string in the first password field.

The span beneath that <span ng-show="formData.password != formData.confirmPassword">Your passwords must match.</span> displays when the original password is not valid, I.E. doesn't include special characters or caps and/or doesn't match. The beauty here is that even if the two passwords match, but don't pattern match the original, they both won't be valid.

The last step is to disable the submit button altogether when the form is invalid which is done here: <button type="submit" id="create-user-button" ng-disabled="formData.password != formData.confirmPassword" ng-click="createUser()">Create User</button>. The ng-disable in the button field checks that both the original password and password confirmation match. I would recommend changing the styling of the submit button when it contains the attribute disabled="disabled" that is created by the ng-disabled property.

I achieved that by doing this:

#create-user-button:disabled,
#create-user-button[disabled]{
  border: 0;
  background-color: #cccccc;
  color: #666666;
}

I completed this today after spending a solid day reading about writing directives and other functions to handle this logic. Granted, this is only a client side validation to ensure that the form is complete and passwords are matching, but it works pretty well.

  • 1
    Hi Nicholas, your code inspired me to come up with another solution, please check my answer. Thanks – slevin Jun 27 '18 at 20:29
5

You can try this

 <input type="password" id="password" name="password" ng-model="password"/>
 <input type="password" id="confirmpassword" name="confirmpassword" ng-model="confirmpassword" ng-pattern="password"/>

And i think you should use ng-message . It make your code clearly and clean

Akashii
  • 2,251
  • 3
  • 17
  • 29
  • Yes, but I'll lose `ng-pattern="/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$@$!%*?&])[A-Za-z\d$@$!%*?&]{6,20}/";` validation for the password confirm. I don't think this is a critical thing cause users often starts with the password field, but are there any way to keep both validations? – Aleksey Kiselev Apr 06 '17 at 15:54
  • I cant test now but i dont think you will lose it , just use in input password , or if not work you can try `ng-pattern="/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$@$!%*?&])‌​[A-Za-z\d$@$!%*?&]{6‌​,20}/ &&password "` – Akashii Apr 06 '17 at 16:01
  • I found one bug at this solution, made an update for my post – Aleksey Kiselev Apr 06 '17 at 16:31
0

How about using two-way binding with interpolation? I am using angular 6, but I dont think that does any major difference.

here is the code :

      pass
     <input type="password" id="password" [(ngModel)]="password" name="password" #passwordvalidityMsg="ngModel" >

      pass confirm
     <input type="password" id="confPass" pattern="{{password}}"  [(ngModel)]="confPass"  name="confPass" #confPassvalidityMsg="ngModel" >
      <div *ngIf="confPassvalidityMsg.invalid && (confPassvalidityMsg.dirty || confPassvalidityMsg.touched)" >
        <div *ngIf="confPassvalidityMsg.errors.pattern"> not the same</div>
      </div>

Since there is two-way binding, I can get the password value and put it in the confPass pattern , and then check the pattern as with any other error.

This works for me, but, since I am an Angular newbie, please advice if there is something wrong. Thank you

slevin
  • 4,166
  • 20
  • 69
  • 129