角反应形式,基于另一种形式的FormControl验证一种形式

时间:2019-10-20 09:43:53

标签: angular validation angular-reactive-forms

考虑一下,我在页面上有两个表单,并实现了一个类似于stepper的向导,并将我的每个表单都放在了stepper的每个步骤上。现在,如果要选择第一种形式的某些值,我想在第二种形式上创建一个字段。

请参阅以下代码,第二种形式的rechargeCode与以第一种形式选择的运算符有关。并且如果选择了某些特定的运营商,则rechargeCode应该是必填项。

<mat-vertical-stepper class="mat-elevation-z4" [linear]="true">
<mat-step [stepControl]="verticalStepperStep1">
    <div fxLayout="row" fxLayoutAlign="center">
         <form fxLayout="column" [formGroup]="verticalStepperStep1" fxFlex="50">
            <ng-template matStepLabel>operator select</ng-template>
            <div fxFlex="1 1 auto" fxLayout="column">
                <mat-form-field appearance="" class="right-align" fxFlex="100">
                    <mat-label>operator</mat-label>
                    <mat-select formControlName="operator" (selectionChange)="operatorChanged()" required>
                        <mat-option *ngFor="let item of operatorList" value="{{item.value}}">
                            {{item.name}}
                        </mat-option>
                    </mat-select>
                </mat-form-field>
            </div>
            <div fxLayout="row" fxLayoutAlign="center center">
                <button fxFlex="20" fxFlex.lt-md="50" mat-raised-button matStepperNext type="button" color="accent">
                    next
                </button>
            </div>
        </form>
    </div>
</mat-step>

<mat-step [stepControl]="verticalStepperStep2">
    <div fxLayout="row" fxLayoutAlign="center">
        <form fxLayout="column" [formGroup]="verticalStepperStep2" fxFlex="50">
            <ng-template matStepLabel>mobile number</ng-template>
            <div fxFlex="1 0 auto" fxLayout="row" fxLayoutAlign="center">
                <mat-form-field appearance="" class="right-align" fxFlex="100">
                    <mat-label>mobile number</mat-label>
                    <input matInput type="tel" formControlName="msisdn" required>
                </mat-form-field>
                <mat-form-field class="right-align" fxFlex="100">
                    <mat-select formControlName="rechargeCode">
                        <mat-option *ngFor="let item of rechargeCodeList" value="{{item.value}}">
                            {{item.name}}
                        </mat-option>
                    </mat-select>
                </mat-form-field>
            </div>
            <div fxLayout="row" fxLayoutAlign="center center">
                <button fxFlex="20" fxFlex.lt-md="50" mat-raised-button matStepperPrevious type="button" color="accent">
                    previous
                </button>
                <button fxFlex="20" fxFlex.lt-md="50" mat-raised-button matStepperNext type="button" color="accent">
                    next
                </button>
            </div>
        </form>
    </div>
</mat-step>
<mat-step>
    <ng-template matStepLabel>final step</ng-template>
    <div class="h2 m-16" fxLayout="row" fxLayoutAlign="center center">
        <div class="card-preview">
            <div class="fuse-card">
                <div class="p-16">
                    <div class="h1">final</div>
                </div>
                <div class="card-divider"></div>
                <div class="p-16 pt-4">
                    <div class="mb-12" fxLayout="row" fxLayoutAlign="space-between center">
                        <div>
                            <div *ngIf="this.verticalStepperStep2.get('msisdn')" class="h2 secondary-text">شماره موبایل: {{this.verticalStepperStep2.get('msisdn').value}}</div>
                        </div>
                    </div>
                    <div class="mb-12" fxLayout="row" fxLayoutAlign="space-between center">
                        <div>
                            <div *ngIf="this.verticalStepperStep1.get('amount')" class="h2 secondary-text">مبلغ قابل پرداخت: {{this.verticalStepperStep1.get('amount').value}} ريال</div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</mat-step>

我该怎么办?

1 个答案:

答案 0 :(得分:1)

有很多选项,例如 您可以检查第一个表单的字段,并使用setVAlidataors作为第二个表单来分配新的验证器,例如

if (this.firstForm.get('formControlThatYouNeed').value) {
    this.secondForm.get('formControlYouNeedToUpdate').setValidators([Validator.required]);
}

不要忘记在setVAlidataors数组中包含其他验证器(如果有此控件的话),因为此方法会删除旧的验证器。 您还可以创建自定义验证程序,例如

customValidator(firstFormFieldValue: any): ValidatorFn {
    return (control: AbstractControl | null) => {
        if (firstFormFieldValue.notSelected) {
            return null;
        }

        const error = Validators.required(control);
        if (error) {
           const firstError = Object.keys(error)[0];
           return { [firstError]: { message } };
        }
        return null;
    }
}

并像这样使用它

this.fb.group({
      field: ['fieldValue', [this.customValidator(this.firstFormFieldValue)]],
}));