【问题标题】:Angular reactive forms, validating one form based on a FormControl on another formAngular 反应式表单,基于另一个表单上的 FormControl 验证一个表单
【发布时间】:2019-10-20 09:43:53
【问题描述】:

考虑我在页面上有两个表单,并实现了一个类似步进器的向导,并将我的每个表单放在步进器的每个步骤上。现在,如果选择了第一个表单中的某个值,我想在第二个表单上设置一个字段。

见下面的代码,第二种形式的rechargeCode,与第一种形式选择的运营商有关。如果选择了某个特定的运营商,那么chargedCode应该是强制性的。

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

我能做什么?

【问题讨论】:

  • 创建一个自定义验证器,如果未选择特定运算符,则返回 null,如果已选择,则委托给 Validators.required。
  • 当我阅读自定义验证器时,有一个输入是表单本身,但在这里,我需要另一个表单的值。请分享一些示例代码。
  • validate(control: FormControl) { if (this.isSpecificFieldSelected()) { ... } else { ... } }

标签: angular validation angular-reactive-forms


【解决方案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)]],
}));

【讨论】:

  • 我会尝试这种方法,如果它可以解决我的问题,我会投票赞成
  • @VahiD 好的,让我知道结果
猜你喜欢
  • 2021-01-09
  • 2017-11-03
  • 2019-05-04
  • 2018-02-01
  • 1970-01-01
  • 2018-01-14
  • 1970-01-01
相关资源
最近更新 更多