Trình xác thực Angular2 dựa trên nhiều trường biểu mẫu


118

Có thể tạo trình xác thực có thể sử dụng nhiều giá trị để quyết định xem trường của tôi có hợp lệ không?

Ví dụ: nếu phương thức liên hệ ưa thích của khách hàng là qua email thì trường email sẽ là bắt buộc.

Cảm ơn.


Đã cập nhật mã ví dụ ...


    import {Component, View} from 'angular2/angular2';
    import {FormBuilder, Validators, formDirectives, ControlGroup} from 'angular2/forms';

    @Component({
        selector: 'customer-basic',
        viewInjector: [FormBuilder]
    })
    @View({
        templateUrl: 'app/components/customerBasic/customerBasic.html',
        directives: [formDirectives]
    })
    export class CustomerBasic {
        customerForm: ControlGroup;

        constructor(builder: FormBuilder) {
            this.customerForm = builder.group({
                firstname: [''],
                lastname: [''],
                validateZip: ['yes'],
                zipcode: ['', this.zipCodeValidator] 
                // I only want to validate using the function below if the validateZip control is set to 'yes'
            });
        }

        zipCodeValidator(control) {
            if (!control.value.match(/\d\d\d\d\d(-\d\d\d\d)?/)) {
                return { invalidZipCode: true };
            }
        }

    }

Đúng. Và nếu bạn cho chúng tôi xem mã của bạn, chúng tôi có thể thêm một câu trả lời cụ thể.
michelem

Tôi đã thêm một ví dụ cơ bản. Trong mã mẫu, làm cách nào để tôi có thể chỉ xác thực mã zip nếu điều khiển validateZip trước đó chứa 'có'?
Simon

Simon, tại sao không khuyến khích các câu trả lời cho câu hỏi của bạn?
superjos

6
Được rồi, để tránh cho những khách truy cập trong tương lai của câu hỏi này rất thất vọng, tôi thực sự khuyên bạn nên sử dụng gói NPM này: npmjs.com/package/ng2-validation . Nó có tích hợp equalequalTocác phương pháp và tài liệu tốt!
Michelangelo

Câu trả lời:


147

Để nhắc lại về các phương pháp mà người khác đã đăng, đây là cách tôi đã tạo FormGrouptrình xác thực không liên quan đến nhiều nhóm.

Đối với ví dụ này, chỉ cần cung cấp tên khóa của các trường passwordconfirmPassword.

// Example use of FormBuilder, FormGroups, and FormControls
this.registrationForm = fb.group({
  dob: ['', Validators.required],
  email: ['', Validators.compose([Validators.required,  emailValidator])],
  password: ['', Validators.required],
  confirmPassword: ['', Validators.required],
  firstName: ['', Validators.required],
  lastName: ['', Validators.required]
}, {validator: matchingPasswords('password', 'confirmPassword')})

Để Validatorsnhận tham số, chúng cần trả về a functionvới một FormGrouphoặc FormControldưới dạng tham số. Trong trường hợp này, tôi đang xác thực a FormGroup.

function matchingPasswords(passwordKey: string, confirmPasswordKey: string) {
  return (group: FormGroup): {[key: string]: any} => {
    let password = group.controls[passwordKey];
    let confirmPassword = group.controls[confirmPasswordKey];

    if (password.value !== confirmPassword.value) {
      return {
        mismatchedPasswords: true
      };
    }
  }
}

Về mặt kỹ thuật, tôi có thể đã xác thực bất kỳ hai giá trị nào nếu tôi biết khóa của chúng, nhưng tôi muốn đặt tên Validatorsgiống như lỗi mà chúng sẽ trả về. Hàm có thể được sửa đổi để lấy tham số thứ ba đại diện cho tên khóa của lỗi được trả về.

Cập nhật ngày 6 tháng 12 năm 2016 (v2.2.4)

Ví dụ đầy đủ: https://embed.plnkr.co/ukwCXm/


@Dave << không liên quan đến nhiều nhóm >> Ý của bạn là << liên quan đến nhiều nhóm >>, hay là gì? Cảm ơn
superjos

Đây dường như không để loại bỏ các đánh dấu cảnh báo khi các mật khẩu phù hợp với góc 2 RC.1
datatype_void

"ControlGroups" dường như không tồn tại trong 2.0. Tôi đã sử dụng 'FormGroup'
Stephen

@superjos Tôi thực sự muốn nói điều đó. Một số nhà phát triển chọn tạo một lồng nhau FormGroupđể xử lý xác thực nhiều trường thay vì đặt Validatortoàn bộ.
cyber_dave

1
Điều gì sẽ xảy ra nếu chúng ta có mật khẩu, xác nhận Mật khẩu và email và Xác nhận Email? [{validator: matchingPasswords('password', 'confirmPassword')},{validator: matchingEmail('email', 'confirmemail')}] Tôi đã thử điều này nhưng nó không hoạt động. Bất kỳ đề xuất ? @ Dave
Sharan Ainapurapu

51

Câu trả lời của Dave rất, rất hữu ích. Tuy nhiên, một số người có thể sửa đổi một chút.

Trong trường hợp bạn cần thêm lỗi vào các Controltrường, bạn có thể giữ nguyên cấu trúc thực tế của biểu mẫu và trình xác thực:

// Example use of FormBuilder, ControlGroups, and Controls
this.registrationForm= fb.group({
  dob: ['', Validators.required],
  email: ['', Validators.compose([Validators.required,  emailValidator])],
  password: ['', Validators.required],
  confirmPassword: ['', Validators.required],
  firstName: ['', Validators.required],
  lastName: ['', Validators.required]
}, {validator: matchingPasswords('password', 'confirmPassword')})

Thay vì đặt lỗi trên ControlGroup, hãy làm như vậy trên trường thực như sau:

function matchingPasswords(passwordKey: string, passwordConfirmationKey: string) {
  return (group: ControlGroup) => {
    let passwordInput = group.controls[passwordKey];
    let passwordConfirmationInput = group.controls[passwordConfirmationKey];
    if (passwordInput.value !== passwordConfirmationInput.value) {
      return passwordConfirmationInput.setErrors({notEquivalent: true})
    }
  }
}

6
Sử dụng passwordConfirmationInput.setErrors(passwordConfirmationInput.validator(passwordConfirmationInput))trong elsenhánh để cập nhật chính xác khi có thay đổi để passwordInputlàm cho dữ liệu hợp lệ.
andraaspar

@andraaspar Tôi đã thử nhưng gặp lỗi TypeError: passwordConfirmationInput.validator is not a function. Đó là vì tôi đã không tạo FormControl một cách rõ ràng với Validators.required. Tôi đã để trống trình xác thực và thay vào đó, tôi đã sử dụng thuộc tính "bắt buộc" trên đầu vào.
bearedlinuxgeek

6
Đây là hữu ích, nhưng tôi nhận thấy rằng các tài liệu góc có kiểu trả về của {[key: string]: any}, mà setErrors(...)không trả lại (nữa?). Cũng setErrors(...)ghi đè bất kỳ lỗi nào đã xuất hiện, vì vậy tôi nối vào đối tượng lỗi hiện tại như: let errors = formGroup.controls[passwordConfirmationKey].errors;if(!errors) errors={};errors['notEquivalent'] = true;formGroup.controls[dateControlFirst].setErrors(errors);
Stephen

32

Khi triển khai trình xác thực cho nhiều trường biểu mẫu, bạn sẽ phải đảm bảo rằng trình xác thực được đánh giá lại khi từng điều khiển biểu mẫu được cập nhật. Hầu hết các ví dụ không cung cấp giải pháp cho tình huống như vậy, nhưng điều này rất quan trọng đối với tính nhất quán của dữ liệu và hành vi chính xác.

Vui lòng xem việc triển khai trình xác thực tùy chỉnh của tôi cho Angular 2, có tính đến điều này: https://gist.github.com/slavafomin/17ded0e723a7d3216fb3d8bf845c2f30 .

Tôi đang sử dụng otherControl.valueChanges.subscribe()để lắng nghe các thay đổi trong điều khiển khác và thisControl.updateValueAndValidity()để kích hoạt một vòng xác thực khác khi điều khiển khác được thay đổi.


Tôi đang sao chép mã bên dưới để tham khảo trong tương lai:

match-other-validator.ts

import {FormControl} from '@angular/forms';


export function matchOtherValidator (otherControlName: string) {

  let thisControl: FormControl;
  let otherControl: FormControl;

  return function matchOtherValidate (control: FormControl) {

    if (!control.parent) {
      return null;
    }

    // Initializing the validator.
    if (!thisControl) {
      thisControl = control;
      otherControl = control.parent.get(otherControlName) as FormControl;
      if (!otherControl) {
        throw new Error('matchOtherValidator(): other control is not found in parent group');
      }
      otherControl.valueChanges.subscribe(() => {
        thisControl.updateValueAndValidity();
      });
    }

    if (!otherControl) {
      return null;
    }

    if (otherControl.value !== thisControl.value) {
      return {
        matchOther: true
      };
    }

    return null;

  }

}

Sử dụng

Đây là cách bạn có thể sử dụng nó với các biểu mẫu phản ứng:

private constructForm () {
  this.form = this.formBuilder.group({
    email: ['', [
      Validators.required,
      Validators.email
    ]],
    password: ['', Validators.required],
    repeatPassword: ['', [
      Validators.required,
      matchOtherValidator('password')
    ]]
  });
}

Có thể tìm thấy nhiều trình xác thực cập nhật hơn tại đây: moebius-mlm / ng-validators .


Câu trả lời hay đấy !! Tôi đã tìm kiếm một giải pháp như thế này trong nhiều giờ! Vui lòng xem xét một chút thay đổi: Thay vì mất tham chiếu "this" khi trả về một hàm, hãy trả về một hàm như sau: return (control: FormControl) => {/ * code * /}
Vingtoft

Rất vui vì tôi có thể giúp. Tại sao bạn cần tham khảo thischo? Trên thực tế, thật tốt khi có một hàm được đặt tên cho mục đích gỡ lỗi.
Slava Fomin II

Hiệu suất? nó đang hoạt động nhưng về mặt hiệu suất, tôi không nghĩ đó là giải pháp tốt. Cập nhật 'thisControl' khi giá trị của 'theOtherControl bị thay đổi sẽ tạo ra một vòng lặp, phải không?
nightElf91

Khi nào thì nên hủy đăng ký? othercontrol.valuechanges.subscribekhông bị hủy đăng ký ở bất cứ đâu.
juana pu

@juanapu Tôi cho rằng Angular sẽ chấm dứt việc valueChangesquan sát được khi di otherControlchúc bị hủy, điều này sẽ khiến đăng ký cũng bị chấm dứt. Tuy nhiên, mối quan tâm của bạn có thể có giá trị. Tôi khuyên bạn nên gỡ lỗi triệt để mã này với phiên bản Angular mới nhất bằng cách sử dụng các trường hợp thử nghiệm khác nhau. Vui lòng báo cáo lại nếu bạn tìm thấy bất kỳ vấn đề nào.
Slava Fomin II

23

Tôi đang sử dụng Angular 2 RC.5 nhưng không thể tìm thấy ControlGroup, dựa trên câu trả lời hữu ích từ Dave. Tôi thấy rằng FormGroup hoạt động thay thế. Vì vậy, tôi đã thực hiện một số cập nhật nhỏ về mã của Dave và nghĩ rằng tôi sẽ chia sẻ với những người khác.

Trong tệp thành phần của bạn, thêm nhập cho FormGroup:

import {FormGroup} from "@angular/forms";

Xác định đầu vào của bạn trong trường hợp bạn cần truy cập trực tiếp vào điều khiển biểu mẫu:

oldPassword = new FormControl("", Validators.required);
newPassword = new FormControl("", Validators.required);
newPasswordAgain = new FormControl("", Validators.required);

Trong hàm tạo của bạn, khởi tạo biểu mẫu của bạn:

this.form = fb.group({
  "oldPassword": this.oldPassword,
  "newPassword": this.newPassword,
  "newPasswordAgain": this.newPasswordAgain
}, {validator: this.matchingPasswords('newPassword', 'newPasswordAgain')});

Thêm chức năng MatchPasswords trong lớp của bạn:

matchingPasswords(passwordKey: string, passwordConfirmationKey: string) {
  return (group: FormGroup) => {
    let passwordInput = group.controls[passwordKey];
    let passwordConfirmationInput = group.controls[passwordConfirmationKey];
    if (passwordInput.value !== passwordConfirmationInput.value) {
      return passwordConfirmationInput.setErrors({notEquivalent: true})
    }
  }
}

Hy vọng điều này sẽ giúp những người đang sử dụng RC.5. Lưu ý rằng tôi chưa thử nghiệm trên RC.6.


@Sam Bạn có thay đổi điều gì đó để làm cho nó hoạt động với phiên bản cuối cùng không? nó không hoạt động đối với tôi .. Nó nói: Đối số kiểu '{validator: (group: FormGroup) => void; } 'không thể gán cho tham số kiểu' ValidatorFn '.
xtof 22/02/17

Không, tôi không cần thay đổi bất cứ điều gì - đối với tôi, mã mẫu ở trên đã hoạt động với Angular2 cuối cùng. Bạn có đang sử dụng mã chính xác như trên không?
Sam

Giải pháp tốt @Chang. Nếu bạn thay đổi mật khẩu sau khi điền mật khẩu xác nhận. Việc xác nhận không hoạt động. Bạn có thể thửif (passwordInput.value !== passwordConfirmationInput.value) { return passwordConfirmationInput.setErrors({ notEquivalent: true }); } else { return passwordConfirmationInput.setErrors(null); }
Mario Shtika

16

Đã đào rất nhiều nguồn góc nhưng tôi đã tìm ra cách tốt hơn.

constructor(...) {
    this.formGroup = builder.group({
        first_name:        ['', Validators.required],
        matching_password: builder.group({
            password: ['', Validators.required],
            confirm:  ['', Validators.required]
        }, this.matchPassword)
    });

    // expose easy access to passworGroup to html
    this.passwordGroup = this.formGroup.controls.matching_password;
}

matchPassword(group): any {
    let password = group.controls.password;
    let confirm = group.controls.confirm;

    // Don't kick in until user touches both fields   
    if (password.pristine || confirm.pristine) {
      return null;
    }

    // Mark group as touched so we can add invalid class easily
    group.markAsTouched();

    if (password.value === confirm.value) {
      return null;
    }

    return {
      isValid: false
    };
}

Phần HTML cho nhóm mật khẩu

<div ng-control-group="matching_password" [class.invalid]="passwordGroup.touched && !passwordGroup.valid">
    <div *ng-if="passwordGroup.touched && !passwordGroup.valid">Passwords must match.</div>
    <div class="form-field">
        <label>Password</label>
        <input type="password" ng-control="password" placeholder="Your password" />
    </div>
    <div class="form-field">
        <label>Password Confirmation</label>
        <input type="password" ng-control="confirm" placeholder="Password Confirmation" />
    </div>
</div>

Khi xác thực cho match_password được chạy thì điều khiển firstName có được đánh giá không? Điều mà tôi không muốn!
Pascal

16

Để mở rộng câu trả lời của matthewdaniel vì nó không chính xác. Dưới đây là một số mã ví dụ cho thấy cách chỉ định đúng trình xác thực cho a ControlGroup.

import {Component} from angular2/core
import {FormBuilder, Control, ControlGroup, Validators} from 'angular2/common'

@Component({
  selector: 'my-app',
  template: `
    <form [ngFormModel]="form">
      <label for="name">Name:</label>
      <input id="name" type="text" ngControl="name">
      <br>
      <label for="email">Email:</label>
      <input id="email" type="email" ngControl="email">
      <br>
      <div ngControlGroup="matchingPassword">
        <label for="password">Password:</label>
        <input id="password" type="password" ngControl="password">
        <br>
        <label for="confirmPassword">Confirm Password:</label>
        <input id="confirmPassword" type="password" ngControl="confirmPassword">
      </div>
    </form>
    <p>Valid?: {{form.valid}}</p>
    <pre>{{form.value | json}}</pre>
  `
})
export class App {
  form: ControlGroup
  constructor(fb: FormBuilder) {
    this.form = fb.group({
      name: ['', Validators.required],
      email: ['', Validators.required]
      matchingPassword: fb.group({
        password: ['', Validators.required],
        confirmPassword: ['', Validators.required]
      }, {validator: this.areEqual})
    });
  }

  areEqual(group: ControlGroup) {
    let val;
    let valid = true;

    for (name in group.controls) {
      if (val === undefined) {
        val = group.controls[name].value
      } else {
        if (val !== group.controls[name].value) {
          valid = false;
          break;
        }
      }
    }

    if (valid) {
      return null;
    }

    return {
      areEqual: true
    };
  }
}

Đây là một ví dụ hoạt động: http://plnkr.co/edit/Zcbg2T3tOxYmhxs7vaAm?p=preview


Điều gì sẽ xảy ra nếu chúng ta thêm các nút radio và hộp kiểm làm thế nào để nhận giá trị của hai nút này?
Pardeep Jain

2
ControlGroupđược xóa để có lợi FormGroupcho bất kỳ ai nhìn vào điều này. Ví dụ về Docs and Learn Angular2
sofly 23/02

2

Đây là một tùy chọn khác mà tôi có thể đưa ra không phụ thuộc vào toàn bộ hoặc phụ ControlGroupnhưng được liên kết trực tiếp với từng tùy chọn Control.

Vấn đề tôi gặp phải là các điều khiển phụ thuộc vào nhau không được phân cấp cùng nhau nên tôi không thể tạo ControlGroup. Ngoài ra, CSS của tôi đã được thiết lập rằng mỗi điều khiển sẽ tận dụng các lớp góc cạnh hiện có để xác định xem có hiển thị kiểu lỗi hay không, điều này phức tạp hơn khi xử lý xác thực nhóm thay vì xác thực cụ thể điều khiển. Việc cố gắng xác định xem một kiểm soát duy nhất có hợp lệ hay không là không thể thực hiện được vì quá trình xác nhận được gắn với nhóm kiểm soát chứ không phải từng kiểm soát riêng lẻ.

Trong trường hợp của tôi, tôi muốn giá trị của một hộp chọn để xác định xem trường khác có được yêu cầu hay không.

Điều này được xây dựng bằng cách sử dụng Trình tạo biểu mẫu trên thành phần. Đối với mô hình chọn thay vì liên kết trực tiếp với giá trị của đối tượng yêu cầu, tôi đã ràng buộc nó với các hàm get / set sẽ cho phép tôi xử lý các sự kiện "khi thay đổi" cho điều khiển. Sau đó, tôi sẽ có thể thiết lập thủ công xác thực cho một điều khiển khác tùy thuộc vào giá trị mới của điều khiển đã chọn.

Đây là phần xem có liên quan:

<select [ngFormControl]="form.controls.employee" [(ngModel)]="employeeModel">
  <option value="" selected></option>
  <option value="Yes">Yes</option>
  <option value="No">No</option>
</select>
...
<input [ngFormControl]="form.controls.employeeID" type="text" maxlength="255" [(ngModel)]="request.empID" />

Phần thành phần có liên quan:

export class RequestComponent {
  form: ControlGroup;
  request: RequestItem;

  constructor(private fb: FormBuilder) {
      this.form = fb.group({
        employee: new Control("", Validators.required),
        empID: new Control("", Validators.compose([Validators.pattern("[0-9]{7}"]))
      });

  get employeeModel() {
    return this.request.isEmployee;
  }

  set employeeModel(value) {
    this.request.isEmployee = value;
    if (value === "Yes") {
      this.form.controls["empID"].validator = Validators.compose([Validators.pattern("[0-9]{7}"), Validators.required]);
      this.form.controls["empID"].updateValueAndValidity();
    }
    else {
      this.form.controls["empID"].validator = Validators.compose([Validators.pattern("[0-9]{7}")]);
      this.form.controls["empID"].updateValueAndValidity();
    }
  }
}

Trong trường hợp của tôi, tôi luôn có xác thực mẫu gắn với điều khiển vì vậy điều khiển validatorluôn được đặt thành một cái gì đó nhưng tôi nghĩ bạn có thể đặt thành validatornull nếu bạn không có bất kỳ xác thực nào gắn với điều khiển.

CẬP NHẬT: Có các phương pháp khác để nắm bắt sự thay đổi của mô hình như (ngModelChange)=changeFunctionName($event)hoặc đăng ký để kiểm soát các thay đổi giá trị bằng cách sử dụngthis.form.controls["employee"].valueChanges.subscribe(data => ...))



1

Cũng đang tìm kiếm điều này và kết thúc bằng cách sử dụng equalTogói ng2-validation ( https://www.npmjs.com/package/ng2-validation )

Đây là một ví dụ: Theo hướng mẫu:

<input type="password" ngModel name="password" #password="ngModel" required/>
<p *ngIf="password.errors?.required">required error</p>
<input type="password" ngModel name="certainPassword" #certainPassword="ngModel" [equalTo]="password"/>
<p *ngIf="certainPassword.errors?.equalTo">equalTo error</p>

Mô hình điều khiển:

let password = new FormControl('', Validators.required);
let certainPassword = new FormControl('', CustomValidators.equalTo(password));

this.form = new FormGroup({
  password: password,
  certainPassword: certainPassword
});

Bản mẫu:

<form [formGroup]="form">
  <input type="password" formControlName="password"/>
  <p *ngIf="form.controls.password.errors?.required">required error</p>
  <input type="password" formControlName="certainPassword"/>
  <p *ngIf="form.controls.certainPassword.errors?.equalTo">equalTo error</p>
</form>

1

Đây là phiên bản của tôi, tôi đã sử dụng để đảm bảo tuổi trong một trường lớn hơn hoặc bằng tuổi trong trường khác. Tôi cũng đang sử dụng các nhóm biểu mẫu, vì vậy tôi sử dụng group.gethàm thay vìgroup.controls[]

import { FormGroup } from '@angular/forms';

export function greaterThanOrEqualTo(sourceKey: string, targetKey: string) {
    return (group: FormGroup) => {
        let sourceInput = group.get(sourceKey);
        let targetInput = group.get(targetKey);

        console.log(sourceInput);
        console.log(targetInput);

        if (targetInput.value < sourceInput.value) {
            return targetInput.setErrors({ notGreaterThanOrEqualTo: true })
        }
    }
}

Và trong thành phần:

    this.form = this._fb.group({

        clientDetails: this._fb.group({
            currentAge: ['', [Validators.required, Validators.pattern('^((1[89])|([2-9][0-9])|100)$')]],
            expectedRetirementAge: ['', [Validators.required]]
        }),

    },
    {
        validator: greaterThanOrEqualTo('clientDetails.currentAge', 'clientDetails.expectedRetirementAge')
    });

0

Tôi nghĩ rằng đặt cược tốt nhất của bạn, bây giờ, là tạo một nhóm định dạng để giữ các quyền kiểm soát của bạn. Khi bạn khởi tạo thẻ Kiểm soát của mình trong hàm để xác thực nó. thí dụ:

    this.password = new Control('', Validators.required);
    let x = this.password;
    this.confirm = new Control('', function(c: Control){
        if(typeof c.value === 'undefined' || c.value == "") return {required: "password required"};
        if(c.value !== x.value)
            return {error: "password mismatch"};
        return null;
    });

tôi biết điều này phụ thuộc nhiều vào phiên bản anglejs2 bạn đang chạy. Điều này đã được thử nghiệm dựa trên 2.0.0-alpha.46

Nếu bất kỳ ai có cách hiểu tốt hơn như viết trình xác thực tùy chỉnh (có thể là cách tốt nhất để thực hiện) thì được hoan nghênh.

BIÊN TẬP

bạn cũng có thể sử dụng ControlGroup và xác thực toàn bộ nhóm đó.

this.formGroup = new ControlGroup({}, function(c: ControlGroup){
        var pass: Control = <Control>c.controls["password"];
        var conf: Control = <Control>c.controls["confirm"];
        pass.setErrors(null, true);
        if(pass.value != null && pass.value != ""){
            if(conf.value != pass.value){
                pass.setErrors({error: "invalid"}, true);
                return {error: "error"};
            }
        }
        return null;
    });

Chỉ cần chỉnh sửa tin nhắn theo miền của bạn.


0

Câu trả lời của Louis Cruz rất hữu ích cho tôi.

Để hoàn thành, chỉ cần thêm vào cái khác thiết lập lại setErrors: return passwordConfirmationInput.setErrors (null);

Và tất cả đều hoạt động tốt!

Cảm ơn bạn,

Trân trọng,

TGA


0

Angular 8 Ví dụ về xác thực trên trường xác nhận mật khẩu

FYI: điều này sẽ không cập nhật xác thực trên trường passwordConfirm nếu trường "mật khẩu" chính bị thay đổi sau khi quá trình xác nhận này đã qua. Tuy nhiên, bạn có thể làm mất hiệu lực trường xác nhận mật khẩu khi người dùng nhập vào trường mật khẩu

<input
  type="password"
  formControlName="password"
  (input)="registerForm.get('passwordConfirm').setErrors({'passwordMatches': true})"
/>

register.component.ts

import { PasswordConfirmValidator } from './password-confirm-validator';
export class RegisterComponent implements OnInit {
  registerForm: FormGroup = this.createRegisterForm({
    username: new FormControl('', [Validators.required, Validators.email]),
    password: new FormControl('', [
      Validators.required,
      Validators.pattern('^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9]).{8,}$'),
      Validators.minLength(8)
    ]),
    passwordConfirm: new FormControl('', [
      Validators.required,
      PasswordConfirmValidator //custom validator
    ])
  });
}

password-verify-validator.ts

import { AbstractControl } from '@angular/forms';

export function PasswordConfirmValidator(control: AbstractControl) {
  if(void 0 === control){ return null; }
  if(
    void 0 !== control.parent &&
    void 0 !== control.parent.controls &&
    void 0 !== control.parent.controls['password'] &&
    control.parent.controls['password'].value === control.value
  ){
    return null;
  }
  return {passwordMatches: true};
}

register.component.html

{{registerForm.get('passwordConfirm').hasError('passwordMatches')}}

-2

Tôi sẽ đề nghị sử dụng thư viện ng-form-rules. Nó là một thư viện tuyệt vời để tạo tất cả các loại biểu mẫu khác nhau với logic xác thực được tách rời khỏi thành phần và điều đó có thể phụ thuộc vào sự thay đổi giá trị của các vùng khác trong biểu mẫu. Họ có tài liệu tuyệt vời , ví dụvideo cho thấy một loạt chức năng của nó . Thực hiện xác thực như thế này những gì bạn đang cố gắng làm là tầm thường.

Bạn có thể xem README của họ để biết một số thông tin cấp cao và một ví dụ cơ bản.


2
Tôi không thích ý tưởng rằng có một thư viện cho mọi thứ ... thư viện không phải là giải pháp cho vấn đề này. Thường thì bạn sẽ tạo ra các vấn đề mới khi chỉ sử dụng một thư viện khác, bạn cũng phải cập nhật nội dung khi Angular cập nhật. Tại sao không sử dụng các hình thức góc như dự định của khuôn khổ?
Nadine

-3

Quy tắc xác thực đối sánh mật khẩu Angular 4.

Nếu bạn cần kiểm soát các trường lỗi thì bạn có thể làm điều đó.

createForm() {
    this.ngForm = this.fb.group({
       'first_name': ["", Validators.required ],
       'last_name' : ["", Validators.compose([Validators.required, Validators.minLength(3)]) ],
       'status' : ['active', Validators.compose([Validators.required])],
       'phone':[null],
       'gender':['male'],
       'address':[''],
       'email':['', Validators.compose([
          Validators.required, 
          Validators.email])],
       'password':['', Validators.compose([Validators.required])],
       'confirm_password':['', Validators.compose([Validators.required])]
    }, {validator: this.matchingPassword('password', 'confirm_password')});
  }

Sau đó, bạn cần khai báo phương thức này trong constructorphương thức Like as.

constructor(
    private fb: FormBuilder

    ) {
    this.createForm();
  }

Thay vì đặt lỗi trên ControlGroup, hãy làm như vậy trên trường thực tế như sau:

    matchingPassword(passwordKey: string, confirmPasswordKey: string) {
  return (group: FormGroup): {[key: string]: any} => {
    let password = group.controls[passwordKey];
    let confirm_password = group.controls[confirmPasswordKey];

    if (password.value !== confirm_password.value) {
      return {        
        mismatchedPasswords: true
      };
    }
  }
}

Phần HTML cho nhóm mật khẩu

<form [formGroup]="ngForm" (ngSubmit)="ngSubmit()">
    <div class="form-group">
            <label class="control-label" for="inputBasicPassword"> Password <span class="text-danger">*</span></label>
                <input type="password" class="form-control" formControlName="password" placeholder="Password" name="password" required>
                <div class="alert text-danger" *ngIf="!ngForm.controls['password'].valid && ngForm.controls['password'].touched">This Field is Required.</div>
            </div>
            {{ngForm.value.password | json}}
            <div class="form-group">
            <label class="control-label" for="inputBasicPassword">Confirm Password <span class="text-danger">*</span></label>
                <input type="password" class="form-control" name="confirm_password" formControlName="confirm_password" placeholder="Confirm Password" match-password="password">

    <div class='alert text-danger' *ngIf="ngForm.controls.confirm_password.touched && ngForm.hasError('mismatchedPasswords')">
              Passwords doesn't match.
      </div>
    </div>
<button type="submit" [disabled]="!ngForm.valid" class="btn btn-primary ladda-button" data-plugin="ladda" data-style="expand-left" disabled="disabled"><span class="ladda-label">
            <i class="fa fa-save"></i>  Create an account
        <span class="ladda-spinner"></span><div class="ladda-progress" style="width: 0px;"></div>
        </span><span class="ladda-spinner"></span></button>
</form>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.