Angular2 validator ซึ่งอาศัยช่องฟอร์มหลายช่อง


119

เป็นไปได้ไหมที่จะสร้างตัวตรวจสอบความถูกต้องซึ่งสามารถใช้หลายค่าเพื่อตัดสินใจว่าฟิลด์ของฉันถูกต้องหรือไม่

เช่นหากวิธีการติดต่อที่ลูกค้าต้องการคือทางอีเมลควรต้องระบุฟิลด์อีเมล

ขอบคุณ


อัปเดตด้วยโค้ดตัวอย่าง ...


    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 };
            }
        }

    }

ใช่. และหากคุณแสดงรหัสของคุณให้เราเห็นเราสามารถเพิ่มคำตอบที่ต้องการได้
michelem

ฉันได้เพิ่มตัวอย่างพื้นฐาน ในโค้ดตัวอย่างฉันจะตรวจสอบความถูกต้องของรหัสไปรษณีย์ได้อย่างไรหากตัวควบคุม validateZip ก่อนหน้านี้มี "ใช่"
Simon

ไซมอนทำไมไม่ส่งเสริมคำตอบสำหรับคำถามของคุณหรือไม่
superjos

6
ตกลงบันทึกผู้เข้าชมในอนาคตของคำถามนี้มากแห้วผมขอแนะนำให้ใช้แพคเกจนี้ NPM: npmjs.com/package/ng2-validation มีการสร้างequalและequalToวิธีการและเอกสารที่ดี!
Michelangelo

คำตอบ:


148

เพื่อเป็นการย้ำเกี่ยวกับวิธีการอื่น ๆ ที่โพสต์ไว้นี่คือวิธีที่ฉันสร้างตัวFormGroupตรวจสอบความถูกต้องที่ไม่เกี่ยวข้องกับหลายกลุ่ม

สำหรับตัวอย่างนี้เพียงแค่ระบุชื่อคีย์ของฟิลด์passwordและconfirmPassword

// 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')})

ในValidatorsการรับพารามิเตอร์พวกเขาจำเป็นต้องส่งคืน a functionด้วย a FormGroupหรือFormControlเป็นพารามิเตอร์ ในกรณีนี้ฉันกำลังตรวจสอบไฟล์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
      };
    }
  }
}

ในทางเทคนิคฉันสามารถตรวจสอบค่าสองค่าใด ๆ ได้หากฉันรู้คีย์ของพวกเขา แต่ฉันชอบตั้งชื่อValidatorsให้เหมือนกับข้อผิดพลาดที่จะส่งคืน ฟังก์ชันนี้สามารถแก้ไขได้เพื่อรับพารามิเตอร์ที่สามที่แสดงถึงชื่อคีย์ของข้อผิดพลาดที่ส่งคืน

อัปเดตเมื่อวันที่ 6 ธันวาคม 2559 (v2.2.4)

ตัวอย่างเต็ม: https://embed.plnkr.co/ukwCXm/


@Dave << ที่ไม่เกี่ยวข้องกับหลายกลุ่ม >> คุณหมายถึง << ที่เกี่ยวข้องกับหลายกลุ่ม >> หรืออะไร? ขอบคุณ
superjos

นี้ดูเหมือนจะไม่เอามาร์กอัปแจ้งเตือนเมื่อรหัสผ่านที่ตรงกับเชิงมุม 2 RC.1
datatype_void

"ControlGroups" ไม่มีอยู่ใน 2.0 ฉันใช้ 'FormGroup'
Stephen

@superjos ฉันตั้งใจจะพูดแบบนั้น นักพัฒนาบางรายเลือกที่จะสร้างแบบซ้อนFormGroupเพื่อจัดการกับการตรวจสอบความถูกต้องแบบหลายฟิลด์แทนที่จะใส่ข้อมูลValidatorทั้งหมด
cyber_dave

1
จะเกิดอะไรขึ้นหากเรามีรหัสผ่านยืนยันรหัสผ่านและอีเมลและยืนยันอีเมล [{validator: matchingPasswords('password', 'confirmPassword')},{validator: matchingEmail('email', 'confirmemail')}] ฉันลองแล้ว แต่มันไม่ได้ผล ข้อเสนอแนะใด ๆ ? @Dave
Sharan Ainapurapu

51

คำตอบของเดฟเป็นอย่างมากที่เป็นประโยชน์มาก อย่างไรก็ตามการปรับเปลี่ยนเล็กน้อยอาจช่วยบางคนได้

ในกรณีที่คุณต้องการเพิ่มข้อผิดพลาดในControlฟิลด์คุณสามารถคงโครงสร้างของแบบฟอร์มและตัวตรวจสอบความถูกต้องไว้ได้:

// 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')})

แทนที่จะตั้งค่าข้อผิดพลาดให้ControlGroupทำในฟิลด์จริงดังนี้:

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
ใช้passwordConfirmationInput.setErrors(passwordConfirmationInput.validator(passwordConfirmationInput))ในelseสาขาเพื่ออัปเดตอย่างถูกต้องเมื่อมีการเปลี่ยนแปลงเพื่อpasswordInputทำให้ข้อมูลถูกต้อง
andraaspar

@andraaspar ฉันพยายามที่ TypeError: passwordConfirmationInput.validator is not a functionแต่ฉันได้ข้อผิดพลาด เป็นเพราะฉันไม่ได้สร้าง FormControl ด้วย Validators.required อย่างชัดเจน ฉันเว้นตัวตรวจสอบความถูกต้องว่างไว้และใช้แอตทริบิวต์ "required" ในอินพุตแทน
beardedlinuxgeek

6
สิ่งนี้มีประโยชน์ แต่ฉันสังเกตว่าเอกสารเชิงมุมมีประเภทการส่งคืน{[key: string]: any}ซึ่งsetErrors(...)ไม่ส่งคืน (อีกต่อไป?) นอกจากนี้ยังsetErrors(...)เขียนทับข้อผิดพลาดใด ๆ ที่มีอยู่แล้วในปัจจุบันดังนั้นฉันผนวกเข้ากับวัตถุที่ผิดพลาดในปัจจุบันที่ชอบ: let errors = formGroup.controls[passwordConfirmationKey].errors;และif(!errors) errors={};และerrors['notEquivalent'] = true;และformGroup.controls[dateControlFirst].setErrors(errors);
สตีเฟ่น

32

เมื่อใช้ตัวตรวจสอบความถูกต้องสำหรับฟิลด์แบบฟอร์มหลายฟิลด์คุณจะต้องตรวจสอบให้แน่ใจว่าตัวตรวจสอบความถูกต้องได้รับการประเมินอีกครั้งเมื่อมีการอัปเดตตัวควบคุมฟอร์มแต่ละรายการ ตัวอย่างส่วนใหญ่ไม่ได้ให้คำตอบสำหรับสถานการณ์ดังกล่าว แต่สิ่งนี้สำคัญมากสำหรับความสอดคล้องของข้อมูลและพฤติกรรมที่ถูกต้อง

โปรดดูการดำเนินงานของฉันเครื่องมือตรวจสอบที่กำหนดเองสำหรับเชิงมุม 2 ซึ่งจะใช้เวลานี้ในบัญชี: https://gist.github.com/slavafomin/17ded0e723a7d3216fb3d8bf845c2f30

ฉันใช้otherControl.valueChanges.subscribe()เพื่อฟังการเปลี่ยนแปลงในการควบคุมอื่น ๆ และthisControl.updateValueAndValidity()เพื่อเริ่มการตรวจสอบอีกรอบเมื่อการควบคุมอื่นมีการเปลี่ยนแปลง


ฉันกำลังคัดลอกรหัสด้านล่างเพื่อใช้อ้างอิงในอนาคต:

ตรงกับ-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;

  }

}

การใช้

นี่คือวิธีที่คุณสามารถใช้กับรูปแบบปฏิกิริยา:

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

ขึ้นไปวันที่ validators อาจจะพบได้ที่นี่: อุซ-MLM / NG-validators


ตอบดี !! ฉันหาวิธีแก้ปัญหาแบบนี้มาหลายชั่วโมงแล้ว! โปรดพิจารณาการเปลี่ยนแปลงเล็กน้อย: แทนที่จะสูญเสียการอ้างอิง "this" เมื่อส่งคืนฟังก์ชันให้ส่งคืนฟังก์ชันเช่นนี้ return (control: FormControl) => {/ * code * /}
Vingtoft

ดีใจที่ช่วยได้ ทำไมคุณถึงต้องการข้อมูลอ้างอิงthisสำหรับ? จริงๆแล้วมันเป็นเรื่องดีที่จะมีฟังก์ชันที่ตั้งชื่อเพื่อวัตถุประสงค์ในการดีบัก
สลาวาโฟมิน II

ประสิทธิภาพ? มันใช้งานได้ แต่มีประสิทธิภาพฉันไม่คิดว่ามันจะเป็นทางออกที่ดี การอัปเดต 'thisControl' เมื่อ 'ค่าของ theOtherControl มีการเปลี่ยนแปลงจะสร้างลูปใช่หรือไม่?
nightElf91

ควรยกเลิกการสมัครเมื่อใด othercontrol.valuechanges.subscribeไม่ได้รับการยกเลิกการสมัครใด ๆ
juana pu

@juanapu ฉันคิดว่า Angular จะยุติการvalueChangesสังเกตเมื่อotherControlจะถูกทำลายซึ่งจะทำให้การสมัครสมาชิกสิ้นสุดลงด้วย อย่างไรก็ตามข้อกังวลของคุณอาจถูกต้อง ฉันขอแนะนำให้ทำการดีบักโค้ดนี้อย่างละเอียดด้วย Angular เวอร์ชันล่าสุดโดยใช้กรณีทดสอบต่างๆ โปรดรายงานกลับหากคุณพบปัญหาใด ๆ
Slava Fomin II

23

ฉันใช้ Angular 2 RC.5 แต่ไม่พบ ControlGroup จากคำตอบที่เป็นประโยชน์จาก Dave ฉันพบว่า FormGroup ทำงานแทน ดังนั้นฉันจึงอัปเดตโค้ดของ Dave เล็กน้อยและคิดว่าจะแชร์กับคนอื่น ๆ

ในไฟล์คอมโพเนนต์ของคุณเพิ่มการนำเข้าสำหรับ FormGroup:

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

กำหนดอินพุตของคุณในกรณีที่คุณต้องการเข้าถึงตัวควบคุมฟอร์มโดยตรง:

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

ในตัวสร้างของคุณสร้างแบบฟอร์มของคุณ:

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

เพิ่มฟังก์ชัน matchingPasswords ในคลาสของคุณ:

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})
    }
  }
}

หวังว่านี่จะช่วยให้ผู้ที่ใช้ RC.5 โปรดทราบว่าฉันยังไม่ได้ทดสอบกับ RC.6


@ แซมคุณเปลี่ยนแปลงอะไรบางอย่างเพื่อให้ใช้งานได้กับเวอร์ชันสุดท้ายหรือไม่? มันใช้ไม่ได้สำหรับฉัน .. มันบอกว่า: Argument of type '{validator: (group: FormGroup) => void; } 'ไม่สามารถกำหนดให้กับพารามิเตอร์ประเภท' ValidatorFn '
xtof

ไม่ฉันไม่จำเป็นต้องเปลี่ยนแปลงอะไรเลย - สำหรับฉันแล้วโค้ดตัวอย่างด้านบนใช้ได้กับ Angular2 final คุณใช้รหัสตรงตามข้างบนหรือไม่?
แซม

ทางออกดีๆ @ ช้าง. หากคุณเปลี่ยนรหัสผ่านหลังจากกรอกรหัสผ่านยืนยันแล้ว การตรวจสอบความถูกต้องไม่ทำงาน คุณสามารถลองif (passwordInput.value !== passwordConfirmationInput.value) { return passwordConfirmationInput.setErrors({ notEquivalent: true }); } else { return passwordConfirmationInput.setErrors(null); }
Mario Shtika

16

การขุดในแหล่งเชิงมุมมากมาย แต่ฉันพบวิธีที่ดีกว่า

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
    };
}

ส่วน HTML สำหรับกลุ่มรหัสผ่าน

<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>

เมื่อมีการเรียกใช้การตรวจสอบความถูกต้องสำหรับ matching_password ตัวควบคุม firstName จะประเมินด้วยหรือไม่ ซึ่งฉันไม่ต้องการ!
Pascal

16

หากต้องการขยายคำตอบของแมทธิวดาเนียลเนื่องจากไม่ถูกต้อง นี่คือตัวอย่างโค้ดบางส่วนที่แสดงวิธีกำหนด validator ให้กับไฟล์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
    };
  }
}

นี่คือตัวอย่างการทำงาน: http://plnkr.co/edit/Zcbg2T3tOxYmhxs7vaAm?p=preview


จะเกิดอะไรขึ้นถ้าเราเพิ่มปุ่มเรดิโอและช่องทำเครื่องหมายจะรับค่าของทั้งสองนี้ได้อย่างไร?
Pardeep Jain

2
ControlGroupจะถูกลบออกFormGroupสำหรับทุกคนที่กำลังมองหาสิ่งนี้ เอกสารและเรียนรู้ Angular2 ตัวอย่าง
นุ่มนวล

2

นี่เป็นอีกทางเลือกหนึ่งที่ฉันสามารถสร้างขึ้นมาได้ซึ่งไม่ได้ขึ้นอยู่กับทั้งหมดหรือย่อยControlGroupแต่เชื่อมโยงโดยตรงกับแต่ละรายการControlรายการ

ปัญหาที่ฉันมีคือการควบคุมที่พึ่งพาซึ่งกันและกันไม่ได้อยู่ร่วมกันตามลำดับชั้นดังนั้นฉันจึงไม่สามารถสร้าง ControlGroup . นอกจากนี้ CSS ของฉันยังได้รับการตั้งค่าที่แต่ละตัวควบคุมจะใช้ประโยชน์จากคลาสเชิงมุมที่มีอยู่เพื่อพิจารณาว่าจะแสดงรูปแบบข้อผิดพลาดหรือไม่ซึ่งซับซ้อนกว่าเมื่อจัดการกับการตรวจสอบความถูกต้องของกลุ่มแทนที่จะเป็นการตรวจสอบความถูกต้องเฉพาะของตัวควบคุม การพยายามตรวจสอบว่าการควบคุมเดียวถูกต้องหรือไม่เนื่องจากการตรวจสอบความถูกต้องเชื่อมโยงกับกลุ่มของการควบคุมไม่ใช่การควบคุมแต่ละรายการ

ในกรณีของฉันฉันต้องการค่าของกล่องเลือกเพื่อพิจารณาว่าจะต้องใช้ฟิลด์อื่นหรือไม่

สิ่งนี้สร้างขึ้นโดยใช้ Form Builder บนคอมโพเนนต์ สำหรับโมเดลที่เลือกแทนที่จะผูกโดยตรงกับค่าของอ็อบเจ็กต์คำขอฉันได้ผูกมันเพื่อรับ / ตั้งค่าฟังก์ชันที่จะช่วยให้ฉันจัดการกับเหตุการณ์ "เมื่อเปลี่ยนแปลง" สำหรับคอนโทรล จากนั้นฉันจะสามารถตั้งค่าการตรวจสอบความถูกต้องสำหรับตัวควบคุมอื่นด้วยตนเองโดยขึ้นอยู่กับค่าใหม่ที่เลือกควบคุม

นี่คือส่วนมุมมองที่เกี่ยวข้อง:

<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" />

ส่วนส่วนประกอบที่เกี่ยวข้อง:

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();
    }
  }
}

ในกรณีของฉันฉันมักจะมีการตรวจสอบความถูกต้องของรูปแบบที่เชื่อมโยงกับตัวควบคุมดังนั้นค่าvalidatorนี้จึงถูกตั้งค่าเป็นบางอย่างเสมอ แต่ฉันคิดว่าคุณสามารถตั้งค่าเป็นvalidatorโมฆะได้หากคุณไม่มีการตรวจสอบความถูกต้องที่เชื่อมโยงกับการควบคุม

อัปเดต: มีวิธีอื่นในการจับการเปลี่ยนแปลงโมเดลเช่น(ngModelChange)=changeFunctionName($event)หรือสมัครสมาชิกเพื่อควบคุมการเปลี่ยนแปลงค่าโดยใช้this.form.controls["employee"].valueChanges.subscribe(data => ...))



1

กำลังมองหาสิ่งนี้เช่นกันและลงเอยด้วยการใช้equalToจากแพ็คเกจ ng2-validation ( https://www.npmjs.com/package/ng2-validation )

นี่คือตัวอย่าง: เทมเพลตที่ขับเคลื่อน:

<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>

โมเดลขับเคลื่อน:

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

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

แม่แบบ:

<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

นี่คือเวอร์ชันของฉันที่ฉันใช้เพื่อตรวจสอบว่าอายุในฟิลด์หนึ่งมากกว่าหรือเท่ากับอายุในอีกฟิลด์หนึ่ง ฉันใช้กลุ่มฟอร์มเช่นกันดังนั้นฉันจึงใช้group.getฟังก์ชันนี้แทน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 })
        }
    }
}

และในส่วนประกอบ:

    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

ฉันคิดว่าทางออกที่ดีที่สุดของคุณในตอนนี้คือการสร้างกลุ่มฟอร์มเพื่อควบคุมการทำงานของคุณ เมื่อคุณสร้างอินสแตนซ์ Control pass ของคุณในฟังก์ชันเพื่อตรวจสอบความถูกต้อง ตัวอย่าง:

    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;
    });

ฉันรู้ว่าสิ่งนี้ขึ้นอยู่กับเวอร์ชันของ angularjs2 ที่คุณใช้งานอยู่ ทดสอบกับ 2.0.0-alpha.46

หากใครมีข้อเสนอแนะที่ดีกว่าเช่นการเขียน custom validator (ซึ่งอาจเป็นวิธีที่ดีที่สุด) ก็ยินดี

แก้ไข

คุณยังสามารถใช้ ControlGroup และตรวจสอบความถูกต้องของกลุ่มนั้นได้ทั้งหมด

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;
    });

เพียงแก้ไขข้อความตามโดเมนของคุณ


0

คำตอบของ Louis Cruzมีประโยชน์มากสำหรับฉัน

หากต้องการดำเนินการให้เสร็จสมบูรณ์เพียงเพิ่มในส่วนอื่น setErrors reset: return passwordConfirmationInput.setErrors (null);

และใช้งานได้ดี!

ขอบคุณ,

ความนับถือ,

TGA


0

Angular 8 ตัวอย่างการตรวจสอบความถูกต้องในฟิลด์ยืนยันรหัสผ่าน

FYI: สิ่งนี้จะไม่อัปเดตการตรวจสอบความถูกต้องในฟิลด์ passwordConfirm หากฟิลด์ "รหัสผ่าน" หลักมีการเปลี่ยนแปลงหลังจากผ่านการตรวจสอบนี้แล้ว แต่คุณสามารถทำให้ฟิลด์ยืนยันรหัสผ่านเป็นโมฆะเมื่อผู้ใช้พิมพ์ลงในช่องรหัสผ่าน

<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
    ])
  });
}

รหัสผ่านยืนยัน-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

ng-form-rulesผมขอแนะนำให้ใช้ห้องสมุด เป็นไลบรารีที่ยอดเยี่ยมสำหรับการสร้างรูปแบบต่างๆด้วยตรรกะการตรวจสอบที่แยกออกจากส่วนประกอบและขึ้นอยู่กับการเปลี่ยนแปลงค่าของพื้นที่อื่น ๆ ในรูปแบบ พวกเขามีเอกสารที่ดี , ตัวอย่างและวิดีโอที่แสดงให้เห็นพวงของการทำงานของมัน การตรวจสอบความถูกต้องเช่นนี้สิ่งที่คุณกำลังพยายามทำนั้นเป็นเรื่องเล็กน้อย

คุณสามารถตรวจสอบ README ของพวกเขาสำหรับข้อมูลระดับสูงและตัวอย่างพื้นฐาน


2
ฉันไม่ชอบความคิดที่ว่ามีห้องสมุดสำหรับทุกสิ่ง ... ห้องสมุดไม่ใช่วิธีแก้ปัญหานี้ บ่อยครั้งที่คุณจะสร้างปัญหาใหม่ ๆ กับการใช้ไลบรารีอื่นนอกจากนี้คุณต้องอัปเดตข้อมูลให้ทันสมัยอยู่เสมอเมื่ออัปเดต Angular ทำไมไม่ใช้รูปแบบเชิงมุมตามที่กรอบต้องการ?
Nadine

-3

กฎการตรวจสอบความถูกต้องของรหัสผ่าน Angular 4

หากคุณต้องการข้อผิดพลาดในการควบคุมฟิลด์คุณสามารถทำได้

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')});
  }

จากนั้นคุณจำเป็นต้องประกาศวิธีนี้ในconstructorวิธีการเช่นเดียวกับ

constructor(
    private fb: FormBuilder

    ) {
    this.createForm();
  }

แทนที่จะตั้งค่าข้อผิดพลาดบน ControlGroup ให้ทำในฟิลด์จริงดังนี้:

    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
      };
    }
  }
}

ส่วน HTML สำหรับกลุ่มรหัสผ่าน

<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>
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.