Programing

여러 양식 필드에 의존하는 Angular2 유효성 검사기

crosscheck 2020. 8. 9. 09:47
반응형

여러 양식 필드에 의존하는 Angular2 유효성 검사기


내 필드가 유효한지 결정하기 위해 여러 값을 사용할 수있는 유효성 검사기를 만들 수 있습니까?

예를 들어 고객이 선호하는 연락 방법이 이메일 인 경우 이메일 필드가 필요합니다.

감사.


예제 코드로 업데이트 됨 ...


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

}

다른 사람들이 게시 한 방법을 반복하기 위해 이것이 FormGroup여러 그룹을 포함하지 않는 유효성 검사기를 만드는 방법 입니다.

이 예에서는 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')})

위해서는 Validators매개 변수를 적용하려면, 그들은을 반환해야 function와 함께 중 하나 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반환 할 오류와 동일한 이름을 지정하는 것을 선호합니다 . 반환 된 오류의 키 이름을 나타내는 세 번째 매개 변수를 사용하도록 함수를 수정할 수 있습니다.

2016 년 12 월 6 일 업데이트 됨 (v2.2.4)

전체 예 : https://embed.plnkr.co/ukwCXm/


Dave의 대답 은 매우, 매우 도움이되었습니다. 그러나 약간의 수정이 일부 사람들에게 도움이 될 수 있습니다.

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

여러 양식 필드에 대한 유효성 검사기를 구현할 때 각 양식 컨트롤이 업데이트 될 때 유효성 검사기가 다시 평가되는지 확인해야합니다. 대부분의 예제는 이러한 시나리오에 대한 솔루션을 제공하지 않지만 데이터 일관성과 올바른 동작을 위해 매우 중요합니다.

이를 고려한 Angular 2 용 사용자 정의 유효성 검사기 구현을 참조하십시오 : https://gist.github.com/slavafomin/17ded0e723a7d3216fb3d8bf845c2f30 .

내가 사용하고 otherControl.valueChanges.subscribe()다른 컨트롤의 변화를 수신하고 thisControl.updateValueAndValidity()다른 제어가 변경 될 때 검증의 또 다른 라운드를 트리거 할 수 있습니다.


향후 참조를 위해 아래 코드를 복사하고 있습니다.

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;

  }

}

용법

반응 형과 함께 사용하는 방법은 다음과 같습니다.

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

더 많은 최신 유효성 검사기는 moebius-mlm / ng-validators 에서 찾을 수 있습니다 .


Angular 2 RC.5를 사용하고 있지만 Dave의 유용한 답변을 기반으로 ControlGroup을 찾을 수 없습니다. 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에서 테스트하지 않았습니다.


정확히 정확하지 않기 때문에 matthewdaniel의 대답을 확장합니다. 다음은 유효성 검사기를 .NET Framework에 올바르게 할당하는 방법을 보여주는 예제 코드입니다 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


각도 소스를 많이 파고 있지만 더 나은 방법을 찾았습니다.

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>

여기에 전체 또는 하위에 의존하지 않고 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컨트롤에 연결된 유효성 검사가 없으면을 null로 설정할 수 있다고 생각합니다 .

업데이트 : 모델 변경을 캡처 (ngModelChange)=changeFunctionName($event)하거나 제어 값 변경을 사용하여 구독하는 다른 방법이 있습니다.this.form.controls["employee"].valueChanges.subscribe(data => ...))


나는이 대답의 대부분을 시도했지만 그들 중 어느 것도 나를 위해 일하지 않았습니다. 여기에서 작동하는 예제를 찾았습니다 https://scotch.io/@ibrahimalsurkhi/match-password-validation-with-angular-2


이것도 찾고 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>

다음은 한 필드의 연령이 다른 필드의 연령보다 크거나 같은지 확인하는 데 사용한 버전입니다. 양식 그룹도 사용하고 있으므로 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')
    });

현재로서는 가장 좋은 방법은 컨트롤을 보유 할 폼 그룹을 만드는 것입니다. 컨트롤을 인스턴스화 할 때 함수의 유효성을 검사합니다. 예:

    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에 대해 테스트되었습니다.

사용자 지정 유효성 검사기 (가장 좋은 방법 일 수 있음)를 작성하는 것과 같은 더 나은 제안이 있다면 환영합니다.

편집하다

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

도메인에 따라 메시지를 편집하십시오.


Louis Cruz의 답변 은 저에게 매우 도움이되었습니다.

완료하려면 else에 setErrors reset을 추가하십시오. return passwordConfirmationInput.setErrors (null);

그리고 모두 잘 작동합니다!

감사합니다,

문안 인사,

TGA


나는 도서관을 사용하는 것이 좋습니다 ng-form-rules. 구성 요소에서 분리 된 유효성 검사 논리를 사용하여 모든 다른 종류의 양식을 생성하고 양식의 다른 영역의 값 변경에 따라 달라질 수있는 멋진 라이브러리입니다. 그들은 그것의 기능을 보여주는 훌륭한 문서 , 예제비디오를 가지고 있습니다 . 이와 같은 유효성 검사를 수행하려는 작업은 간단합니다.

README 에서 높은 수준의 정보와 기본 예를 확인할 수 있습니다 .


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

그런 다음이 메서드를 constructorLike 메서드에서 선언해야합니다 .

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>

참고 URL : https://stackoverflow.com/questions/31788681/angular2-validator-which-relies-on-multiple-form-fields

반응형