Подтвердите подтверждение пароля в Angular 6

Я хочу, чтобы выполнить пароль и подтверждение пароля валидаций используя только материальные компоненты, и сообщение об ошибке ниже поле Подтверждение пароля, если confirm password field doesn't match с А, if it is empty.Tried много ресурсов не удалось достичь.

Пробовал это видео тоже.

Это материальный компонент, который я ищу

enter image description here

HTML

     <mat-form-field >
        <input matInput  placeholder="New password" [type]="hide ? 'password' 
          : 'text'" [formControl]="passFormControl" required>
        <mat-icon matSuffix (click)="hide = !hide">{{hide ? 'visibility' : 
          'visibility_off'}}</mat-icon>
        <mat-error *ngIf="passFormControl.hasError('required')">
            Please enter your newpassword
         </mat-error>
      </mat-form-field>

      <mat-form-field >
         <input matInput  placeholder="Confirm password" [type]="hide ? 
              'password' : 'text'" [formControl]="confirmFormControl" 
                    required>
         <mat-icon matSuffix (click)="hide = !hide">{{hide ? 'visibility' : 
                'visibility_off'}}</mat-icon>
         <mat-error *ngIf="confirmFormControl.hasError('required')">
          Confirm your password
          </mat-error>
      </mat-form-field>

TS

     import {Component, OnInit } from '@angular/core';
     import {FormControl, FormGroupDirective, NgForm, Validators} from 
             '@angular/forms';
     import {ErrorStateMatcher} from '@angular/material/core';

     @Component({
            selector: 'asd-set-pass',
            templateUrl: './set-pass.component.html',
             styleUrls: ['./set-pass.component.css']
         })

       passFormControl = new FormControl('', [
            Validators.required,
        ]);
        confirmFormControl = new FormControl('', [
            Validators.required,
            ]);

             hide =true;

       }

Это подтверждает следующие условия: 1) Если поля пароля и пароля подтверждения пустые, отображается текст ошибки.

Я хочу сравнить с полями в файле (.ts), например, как его проверка для пустого поля, и ошибка, если поле подтверждения пароля пустое.

Ответ 1

Этот вопрос можно решить с помощью комбинации этих двух ответов: fooobar.com/questions/631212/... и fooobar.com/questions/2442809/...

Поэтому, прежде всего, вам понадобится специальный валидатор для проверки паролей, который может выглядеть следующим образом:

checkPasswords(group: FormGroup) { // here we have the 'passwords' group
  let pass = group.get('password').value;
  let confirmPass = group.get('confirmPass').value;

  return pass === confirmPass ? null : { notSame: true }     
}

и вы создадите группу форм для своих полей вместо двух элементов управления формой, а затем отметите этот пользовательский валидатор для вашей группы форм:

this.myForm = this.fb.group({
  password: ['', [Validators.required]],
  confirmPassword: ['']
}, {validator: this.checkPasswords })

а затем, как упоминалось в другом ответе, mat-error показывает только, если FormControl недопустим, поэтому вам нужно сопоставление состояния ошибки:

export class MyErrorStateMatcher implements ErrorStateMatcher {
  isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
    const invalidCtrl = !!(control && control.invalid && control.parent.dirty);
    const invalidParent = !!(control && control.parent && control.parent.invalid && control.parent.dirty);

    return (invalidCtrl || invalidParent);
  }
}

Выше можно настроить, когда показывать сообщение об ошибке. Я хотел бы показать сообщение только при прикосновении к полю password. Также я хотел бы выше, удалить валидатор required из поля confirmPassword, так как форма в любом случае недействительна, если пароли не совпадают.

Затем в компоненте создайте новый ErrorStateMatcher:

matcher = new MyErrorStateMatcher();

Наконец, шаблон будет выглядеть так:

<form [formGroup]="myForm">
  <mat-form-field>
    <input matInput placeholder="New password" formControlName="password" required>
    <mat-error *ngIf="myForm.hasError('required', 'password')">
        Please enter your new password
    </mat-error>
  </mat-form-field>

  <mat-form-field>
    <input matInput placeholder="Confirm password" formControlName="confirmPassword" [errorStateMatcher]="matcher">
    <mat-error *ngIf="myForm.hasError('notSame')">
        Passwords do not match
    </mat-error>  
  </mat-form-field>
</form>

Вот демонстрация для вас с кодом выше: StackBlitz

Ответ 2

Вы можете просто использовать значение поля пароля в качестве шаблона для подтверждения поля пароля. Например:

<div class="form-group">
 <input type="password" [(ngModel)]="userdata.password" name="password" placeholder="Password" class="form-control" required #password="ngModel" pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}" />
 <div *ngIf="password.invalid && (myform.submitted || password.touched)" class="alert alert-danger">
   <div *ngIf="password.errors.required"> Password is required. </div>
   <div *ngIf="password.errors.pattern"> Must contain at least one number and one uppercase and lowercase letter, and at least 8 or more characters.</div>
 </div>
</div>

<div class="form-group">
 <input type="password" [(ngModel)]="userdata.confirmpassword" name="confirmpassword" placeholder="Confirm Password" class="form-control" required #confirmpassword="ngModel" pattern="{{ password.value }}" />
 <div *ngIf=" confirmpassword.invalid && (myform.submitted || confirmpassword.touched)" class="alert alert-danger">
   <div *ngIf="confirmpassword.errors.required"> Confirm password is required. </div>
   <div *ngIf="confirmpassword.errors.pattern"> Password & Confirm Password does not match.</div>
 </div>
</div>

Ответ 3

В случае, если у вас есть больше, чем просто поля Password и Verify Password. Таким образом, поле "Подтверждение пароля" будет выделять только ошибку, когда пользователь что-то напишет в этом поле:

validators.ts

import { FormGroup, FormControl, Validators, FormBuilder, FormGroupDirective, NgForm } from '@angular/forms';
import { ErrorStateMatcher } from '@angular/material/core';

export const EmailValidation = [Validators.required, Validators.email];
export const PasswordValidation = [
  Validators.required,
  Validators.minLength(6),
  Validators.maxLength(24),
];

export class RepeatPasswordEStateMatcher implements ErrorStateMatcher {
  isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
    return (control && control.parent.get('password').value !== control.parent.get('passwordAgain').value && control.dirty)
  }
}
export function RepeatPasswordValidator(group: FormGroup) {
  const password = group.controls.password.value;
  const passwordConfirmation = group.controls.passwordAgain.value;

  return password === passwordConfirmation ? null : { passwordsNotEqual: true }     
}

register.component.ts

import { FormGroup, FormControl, Validators, FormBuilder} from '@angular/forms';
import { EmailValidation, PasswordValidation, RepeatPasswordEStateMatcher, RepeatPasswordValidator } from 'validators';

...

form: any;
passwordsMatcher = new RepeatPasswordEStateMatcher;


constructor(private formBuilder: FormBuilder) {
    this.form = this.formBuilder.group ( {
      email: new FormControl('', EmailValidation),
      password: new FormControl('', PasswordValidation),
      passwordAgain: new FormControl(''),
      acceptTerms: new FormControl('', [Validators.requiredTrue])
    }, { validator: RepeatPasswordValidator });
  }

...

register.component.html

<form [formGroup]="form" (ngSubmit)="submitAccount(form)">
    <div class="form-content">
        <div class="form-field">
            <mat-form-field>
            <input matInput formControlName="email" placeholder="Email">
            <mat-error *ngIf="form.get('email').hasError('required')">
                E-mail is mandatory.
            </mat-error>
            <mat-error *ngIf="form.get('email').hasError('email')">
                Incorrect E-mail.
            </mat-error>
            </mat-form-field>
        </div>
        <div class="form-field">
            <mat-form-field>
            <input matInput formControlName="password" placeholder="Password" type="password">
            <mat-hint class="ac-form-field-description">Between 6 and 24 characters.</mat-hint>
            <mat-error *ngIf="form.get('password').hasError('required')">
                Password is mandatory.
            </mat-error>
            <mat-error *ngIf="form.get('password').hasError('minlength')">
                Password with less than 6 characters.
            </mat-error>
            <mat-error *ngIf="form.get('password').hasError('maxlength')">
                Password with more than 24 characters.
            </mat-error>
            </mat-form-field>
        </div>
        <div class="form-field">
            <mat-form-field>
            <input matInput formControlName="passwordAgain" placeholder="Confirm the password" type="password" [errorStateMatcher]="passwordsMatcher">
            <mat-error *ngIf="form.hasError('passwordsNotEqual')" >Passwords are different. They should be equal!</mat-error>
            </mat-form-field>
        </div>
        <div class="form-field">
            <mat-checkbox name="acceptTerms" formControlName="acceptTerms">I accept terms and conditions</mat-checkbox>
        </div>
    </div>
    <div class="form-bottom">
        <button mat-raised-button [disabled]="!form.valid">Create Account</button>
    </div>
</form>

Я надеюсь, что это помогает!

Ответ 4

Самый простой способ ИМО:

(Это может также использоваться с электронными письмами например)

public static matchValues(
    matchTo: string // name of the control to match to
  ): (AbstractControl) => ValidationErrors | null {
    return (control: AbstractControl): ValidationErrors | null => {
      return !!control.parent &&
        !!control.parent.value &&
        control.value === control.parent.controls[matchTo].value
        ? null
        : { isMatching: false };
    };
}

В вашем компоненте:

this.SignUpForm = this.formBuilder.group({

password: [undefined, [Validators.required]],
passwordConfirm: [undefined, 
        [
          Validators.required,
          matchValues('password'),
        ],
      ],
});

Ответ 5

Я использую угловой 6, и я искал лучший способ совпадения пароля и подтверждения пароля. Это также можно использовать для соответствия любым двум входам в форме. Я использовал угловые директивы. Я хотел использовать их

ng gd compare-validators --spec false, и я добавлю в ваш модуль. Ниже приведена директива

import { Directive, Input } from '@angular/core';
import { Validator, NG_VALIDATORS, AbstractControl, ValidationErrors } from '@angular/forms';
import { Subscription } from 'rxjs';

@Directive({
  // tslint:disable-next-line:directive-selector
  selector: '[compare]',
  providers: [{ provide: NG_VALIDATORS, useExisting: CompareValidatorDirective, multi: true}]
})
export class CompareValidatorDirective implements Validator {
  // tslint:disable-next-line:no-input-rename
  @Input('compare') controlNameToCompare;

  validate(c: AbstractControl): ValidationErrors | null {
    if (c.value.length < 6 || c.value === null) {
      return null;
    }
    const controlToCompare = c.root.get(this.controlNameToCompare);

    if (controlToCompare) {
      const subscription: Subscription = controlToCompare.valueChanges.subscribe(() => {
        c.updateValueAndValidity();
        subscription.unsubscribe();
      });
    }

    return controlToCompare && controlToCompare.value !== c.value ? {'compare': true } : null;
  }

}

Теперь в вашем компоненте

<div class="col-md-6">
              <div class="form-group">
                <label class="bmd-label-floating">Password</label>
                <input type="password" class="form-control" formControlName="usrpass" [ngClass]="{ 'is-invalid': submitAttempt && f.usrpass.errors }">
                <div *ngIf="submitAttempt && signupForm.controls['usrpass'].errors" class="invalid-feedback">
                  <div *ngIf="signupForm.controls['usrpass'].errors.required">Your password is required</div>
                  <div *ngIf="signupForm.controls['usrpass'].errors.minlength">Password must be at least 6 characters</div>
                </div>
              </div>
            </div>
            <div class="col-md-6">
              <div class="form-group">
                <label class="bmd-label-floating">Confirm Password</label>
                <input type="password" class="form-control" formControlName="confirmpass" compare = "usrpass"
                [ngClass]="{ 'is-invalid': submitAttempt && f.confirmpass.errors }">
                <div *ngIf="submitAttempt && signupForm.controls['confirmpass'].errors" class="invalid-feedback">
                  <div *ngIf="signupForm.controls['confirmpass'].errors.required">Your confirm password is required</div>
                  <div *ngIf="signupForm.controls['confirmpass'].errors.minlength">Password must be at least 6 characters</div>
                  <div *ngIf="signupForm.controls['confirmpass'].errors['compare']">Confirm password and Password dont match</div>
                </div>
              </div>
            </div>

Я надеюсь, что это поможет

Ответ 6

Я нашел ошибку в ответе AJT_82. Поскольку у меня недостаточно репутации, чтобы комментировать ответ AJT_82, я должен опубликовать сообщение об ошибке и решение в этом ответе.

Вот ошибка:

enter image description here

Решение: в следующем коде:

export class MyErrorStateMatcher implements ErrorStateMatcher {
  isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
    const invalidCtrl = !!(control && control.invalid && control.parent.dirty);
    const invalidParent = !!(control && control.parent && control.parent.invalid && control.parent.dirty);

    return (invalidCtrl || invalidParent);
  }
}

Измените control.parent.invalid на control.parent.hasError('notSame') чтобы решить эту проблему.

После небольших изменений проблема решена.

enter image description here

Ответ 7

Просто сделайте стандартный пользовательский валидатор и сначала проверьте, определена ли сама форма, иначе он выдаст ошибку, которая говорит, что форма не определена, потому что сначала он попытается запустить валидатор до того, как форма будет построена.

// form builder
private buildForm(): void {
    this.changePasswordForm = this.fb.group({
        currentPass: ['', Validators.required],
        newPass: ['', Validators.required],
        confirmPass: ['', [Validators.required, this.passwordMatcher.bind(this)]],
    });
}

// confirm new password validator
private passwordMatcher(control: FormControl): { [s: string]: boolean } {
    if (
        this.changePasswordForm &&
        (control.value !== this.changePasswordForm.controls.newPass.value)
    ) {
        return { passwordNotMatch: true };
    }
    return null;
}

Он просто проверяет, что поле нового пароля имеет то же значение, что и поле подтверждения пароля. Является валидатором, специфичным для поля подтверждения пароля, а не для всей формы.

Вам просто нужно убедиться, что this.changePasswordForm определен, потому что в противном случае при создании формы он выдаст неопределенную ошибку.

Это работает просто отлично, без создания директив или соответствия состояний ошибок.

Ответ 8

Я бы предложил использовать библиотечные ng-form-rules. Это потрясающая библиотека для создания всех различных форм форм с логикой проверки, отделенной от компонента (и повторного использования). У них отличная документация, примеры и видео, которые показывают множество функциональных возможностей. Выполнение такой проверки (проверка равенства двух элементов управления формой) тривиально.

Вы можете проверить их README для получения информации о высоком уровне и базового примера.

Ответ 9

* Это решение для реактивной формы

Возможно, вы слышали, что подтверждающий пароль известен как проверка по всему полю. В то время как валидатор уровня поля, который мы обычно пишем, может применяться только к одному полю. Для перекрестной проверки вы, вероятно, должны написать некоторый валидатор родительского уровня. Для конкретного случая подтверждения пароля, я бы лучше сделал:

this.form.valueChanges.subscribe(field => {
  if (field.password !== field.confirm) {
    this.confirm.setErrors({ mismatch: true });
  } else {
    this.confirm.setErrors(null);
  }
});

И вот шаблон:

<mat-form-field>
      <input matInput type="password" placeholder="Password" formControlName="password">
      <mat-error *ngIf="password.hasError('required')">Required</mat-error>
</mat-form-field>
<mat-form-field>
    <input matInput type="password" placeholder="Confirm New Password" formControlName="confirm">'enter code here'
    <mat-error *ngIf="confirm.hasError('mismatch')">Password does not match the confirm password</mat-error>
</mat-form-field>

Ответ 10

Я бы не предложил установить валидатор на уровне группы форм. это может повлиять на проблему производительности, если группа форм содержит так много свойств.

Вместо написания большого количества кода для управления паролем сравнения. Я бы предложил попробовать использовать RxwebValidators для сравнения пароля. Rxwebvalidators предоставляет больше, чем 40+ валидаторы, те, которые вы должны добавить в свою группу форм. Я создал образец приложения, пожалуйста, проверьте эту ссылку

Вот код компонента.

import { Component } from '@angular/core';
import { FormGroup,FormBuilder } from "@angular/forms"
import { RxwebValidators,RxFormBuilder } from "@rxweb/reactive-form-validators"

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  userFormGroup: FormGroup

    constructor(
        private formBuilder: RxFormBuilder
    ) { }

    ngOnInit() {
        this.userFormGroup = this.formBuilder.group({
                password:['',], 
        confirmPassword:['', RxwebValidators.compare({fieldName:'password' })], 
                                });
    }
}

В приведенном выше коде я добавил подтверждение проверки RxwebValidators.compare в поле confirmPassword.

на стороне HTML писать код в соответствии со стандартами.

Вот код html.

<div>
  <div class="container">
  <main class="col-12"><h1 class="bd-title" id="content">Compare Password Example</h1>
<br>
<form  [formGroup]="userFormGroup">
<div class="form-group">
    <label>New Password</label>
    <input type="text" formControlName="password" class="form-control"  />
</div>
<div class="form-group">
    <label>Confirm Password</label>
    <input type="text" formControlName="confirmPassword" class="form-control"  />
</div>
<button [disabled]="!userFormGroup.valid" class="btn btn-primary">Submit</button>
</form></main>
</div>
</div>

Ответ 11

Я делаю это с очень небольшим кодом, делегирующим ответственность за событие Submit.

<div class="form-label-group">
    <input type="password" id="inputPassword" class="form-control" (change)="StorePassword($event)" required>
    <label for="inputPassword">Password</label>
</div>

<div class="form-label-group">
    <input type="password" id="inputConfirmaPassword" class="form-control" (invalid)="GetInvalidMessage($event)"
    [pattern]="iPassword" required>
    <label for="inputConfirmaPassword">Confirm password</label>
</div>

Я создаю шаблон на входе подтверждения, идентичный паролю (сохраняя пароль в переменной благодаря событию изменения ввода пароля).

iPassword: string = null;

StorePassword ( event: any ): void {
    this.iPassword = event.target.value != '' ? event.target.value : null;
}

Сообщение об ошибке можно настроить следующим образом:

GetInvalidMessage ( event: any ): void {
    if ( event.target.validity.patternMismatch && event.target.id == 'inputConfirmaPassword' ) {
        event.target.setCustomValidity( "Passwords do not match" );
    }
}

Ответ 12

Нет необходимости использовать вложенные группы форм и пользовательский ErrorStateMatcher для подтверждения правильности пароля. Эти шаги были добавлены для облегчения координации между полями пароля, но вы можете сделать это без лишних затрат.

Вот пример:

this.registrationForm = this.fb.group({
  username: ['', Validators.required],
  email: ['', [Validators.required, Validators.email]],
  password1: ['', [Validators.required, (control) => this.validatePasswords(control, 'password1') ] ],
  password2: ['', [Validators.required, (control) => this.validatePasswords(control, 'password2') ] ]
});

Обратите внимание, что мы передаем дополнительный контекст методу validatePasswords (независимо от того, является ли источник паролем1 или паролем2).

  validatePasswords(control: AbstractControl, name: string) {
    if (this.registrationForm === undefined || this.password1.value === '' || this.password2.value === '') {
      return null;
    } else if (this.password1.value === this.password2.value) {
      if (name === 'password1' && this.password2.hasError('passwordMismatch')) {
        this.password1.setErrors(null);
        this.password2.updateValueAndValidity();
      } else if (name === 'password2' && this.password1.hasError('passwordMismatch')) {
        this.password2.setErrors(null);
        this.password1.updateValueAndValidity();
      }
      return null;
    } else {
      return {'passwordMismatch': { value: 'The provided passwords do not match'}};
    }  

Обратите внимание, что при совпадении паролей мы согласовываемся с другим полем пароля, чтобы обновить его проверку. Это удалит все несоответствующие ошибки несоответствия пароля.

И для полноты картины, вот получатели, которые определяют this.password1 и this.password2.

  get password1(): AbstractControl {
    return this.registrationForm.get('password1');
  }

  get password2(): AbstractControl {
    return this.registrationForm.get('password2');
  }

Ответ 13

Единый метод для реактивных форм

машинопись

// All is this method
onPasswordChange() {
  if (this.confirm_password.value == this.password.value) {
    this.confirm_password.setErrors(null);
  } else {
    this.confirm_password.setErrors({ mismatch: true });
  }
}

// getting the form control elements
get password(): AbstractControl {
  return this.form.controls['password'];
}

get confirm_password(): AbstractControl {
  return this.form.controls['confirm_password'];
}

HTML

// PASSWORD FIELD
<input type="password" formControlName="password" (change)="onPasswordChange()" />

// CONFIRM PASSWORD FIELD
<input type="password" formControlName="confirm_password" (change)="onPasswordChange()" />

// SHOW ERROR IF MISMATCH
<span *ngIf="confirm_password.hasError('mismatch')">Password do not match.</span>

Ответ 14

Мой ответ очень прост> Я создал пароль и подтвердил подтверждение пароля с помощью шаблона driiven in angular 6

Мой HTML файл

<div class="form-group">
  <label class="label-sm">Confirm Password</label>
  <input class="form-control" placeholder="Enter Password" type="password" #confirm_password="ngModel" [(ngModel)]="userModel.confirm_password" name="confirm_password" required (keyup)="checkPassword($event)" />
  <div *ngIf="confirm_password.errors && (confirm_password.dirty||confirm_password.touched||signup.submitted)">
  <div class="error" *ngIf="confirm_password.errors.required">Please confirm your password</div>
  </div>
  <div *ngIf="i" class='error'>Password does not match</div>
</div>

Мой машинописный файл

      public i: boolean;

      checkPassword(event) {
        const password = this.userModel.password;
        const confirm_new_password = event.target.value;

        if (password !== undefined) {
          if (confirm_new_password !== password) {
            this.i = true;
          } else {
            this.i = false;
          }
        }
      }

при нажатии на кнопку отправки я проверяю, является ли значение я истинным или ложным

если правда

if (this.i) {
      return false;
    }

else{
**form submitted code comes here**
}

Ответ 15

Я сделал это так Надеюсь, что это поможет вам.

HTML:

<form [formGroup]='addAdminForm'>   
          <div class="form-group row">
            <label class="col-sm-3 col-form-label">Password</label>
            <div class="col-sm-7">
              <input type="password" class="form-control" formControlName='password' (keyup)="checkPassSame()">

              <div *ngIf="addAdminForm.controls?.password?.invalid && addAdminForm.controls?.password.touched">
                <p *ngIf="addAdminForm.controls?.password?.errors.required" class="errorMsg">*This field is required.</p>
              </div>
            </div>
          </div>

          <div class="form-group row">
            <label class="col-sm-3 col-form-label">Confirm Password</label>
            <div class="col-sm-7">
              <input type="password" class="form-control" formControlName='confPass' (keyup)="checkPassSame()">

              <div *ngIf="addAdminForm.controls?.confPass?.invalid && addAdminForm.controls?.confPass.touched">
                <p *ngIf="addAdminForm.controls?.confPass?.errors.required" class="errorMsg">*This field is required.</p>
              </div>
              <div *ngIf="passmsg != '' && !addAdminForm.controls?.confPass?.errors?.required">
                <p class="errorMsg">*{{passmsg}}</p>
              </div>  
            </div>
          </div>
      </form>

Файл TS:

export class AddAdminAccountsComponent implements OnInit {

  addAdminForm: FormGroup;
  password: FormControl;
  confPass: FormControl;
  passmsg: string;


  constructor(
    private http: HttpClient,
    private router: Router,
  ) { 
  }

  ngOnInit() {    
    this.createFormGroup();
  }



    // |---------------------------------------------------------------------------------------
    // |------------------------ form initialization -------------------------
    // |---------------------------------------------------------------------------------------
    createFormGroup() {    
      this.addAdminForm = new FormGroup({
        password: new FormControl('', [Validators.required]),
        confPass: new FormControl('', [Validators.required]),
      })
    }



    // |---------------------------------------------------------------------------------------
    // |------------------------ Check method for password and conf password same or not -------------------------
    // |---------------------------------------------------------------------------------------

    checkPassSame() {
      let pass = this.addAdminForm.value.password;
      let passConf = this.addAdminForm.value.confPass;
      if(pass == passConf && this.addAdminForm.valid === true) {
        this.passmsg = "";
        return false;
      }else {
        this.passmsg = "Password did not match.";
        return true;
      }
    }



}