1

我正在检查这个问题及其答案以便发布。

public isFirst = false;
public isSecond = false;

private buildFormGroup() {
    const internalFormGroup = this.formBuilder.group({
      idTypeCode: ['', [Validators.required, Validators.min(1)]],
      master: [true],
      slave: [''],
      fieldSlave: [''], // Validations depends indirectly on idTypeCode !!! HERE
    });

    return internalFormGroup;
}

private conditionalValidator(masterName: string, masterValue: any, slaveName: string, validators: any) {
    if (this.formGroup) {
      const masterControl = this.formGroup.get(masterName);
      if (masterControl) {
        masterControl.valueChanges.subscribe((value) => {
          const slaveControl = this.formGroup.get(slaveName);
          if (slaveControl) {
            if (value === masterValue) {
              slaveControl.setValidators(validators);
            } else {
              slaveControl.clearValidators();
            }
            slaveControl.updateValueAndValidity();
          }
        });
      }
    }
}


public onTypeCodeChange(event: MatSelectChange) {
    const selectedId = +event;
    const selectedTypeCode = this.typeCodes.find((typeCode) => typeCode.id === selectedId);
    this.isFirst = selectedTypeCode?.codeEnum === CodeEnum.First;
    this.isSecond = selectedTypeCode?.codeEnum === CodeEnum.Second;
}

我跳过了填充 observable 的代码typeCodes$

public readonly typeCodes$: Observable<TypeCodeDto[]>;
private typeCodes: TypeCodeDto[] = [];

public ngOnInit(): void {
    this.typeCodes$.subscribe((typeCodes) => {
      this.typeCodes = typeCodes;
    });
    this.conditionalValidator('master', false, 'slave', [Validators.required, Validators.min(1)]);
}

如您所见,conditionalValidator方法的使用很简单!!!。

但是,我有一个包含一个枚举的接口

    export interface TypeCodeDto {
      id?: number;
      name?: string;
      codeEnum?: CodeEnum;
    }

    export enum CodeEnum {
      None = 0,
      First = 1,
      Second = 2,
    }

在我的 HTML 中,我将 aSelect与之前的 observable 一起使用typeCodes$

  <mat-select
    formControlName="idTypeCode"
    [required]="formGroup.controls.idTypeCode.invalid"
    (ngModelChange)="onTypeCodeChange($event)"
  >
    <mat-option *ngFor="let typeCode of typeCodes$ | async" [value]="typeCode.id">
      {{ typeCode.name }}
    </mat-option>
  </mat-select>

现在我有一个复杂的情况,在我的 HTML 中,当Select(或idTypeCode)对应于一个TypeCodeDto等于codeEnumSecond需要应用:

fieldSlave: ['', [Validators.required, Validators.maxLength(256), Validators.minLength(1)]],

如何实施?

4

1 回答 1

2

https://stackblitz.com/edit/angular-ivy-9giuxs?file=src%2Fapp%2Fapp.component.html

添加一个可观察的:

  private subCodeEnum = new Subject<CodeEnum>();

用你的方法!

  public onTypeCodeChange(event: MatSelectChange) {
    const selectedId = +event;
    const selectedTypeCode = this.typeCodes.find(
      (typeCode) => typeCode.id === selectedId
    );
    this.subCodeEnum.next(selectedTypeCode?.codeEnum);
  }

创建(或替换您的conditionalValidator方法的代码):

  private conditionalObservableValidator(
    masterObservable: Observable<any> | null | undefined,
    masterValue: any,
    slaveControl: AbstractControl | null,
    trueValidators: ValidatorFn | ValidatorFn[] | null,
    falseValidators?: ValidatorFn | ValidatorFn[] | null
  ) {
    if (slaveControl && masterObservable) {
      masterObservable.subscribe(
        (value) => {
          if (value === masterValue) {
            slaveControl.setValidators(trueValidators || null);
          } else {
            slaveControl.setValidators(falseValidators || null);
          }
          slaveControl.updateValueAndValidity();
        }
        
      );
    }
  }

如何使用它?

  public ngOnInit(): void {
    //
    
    this.conditionalObservableValidator(
      this.formGroup.get('master').valueChanges,
      false,
      this.formGroup.get('slave'),
      [Validators.required, Validators.min(1),]
    );

    this.conditionalObservableValidator(
      this.subCodeEnum,
      CodeEnum.Second,
      this.formGroup.get('fieldSlave'),
      [Validators.required, Validators.maxLength(256), Validators.minLength(1)],
      null // Last argument is Not necessary
    );
  }

编辑:

您可以使用:selectionChange在 HTML 模板上

<mat-select
  formControlName="idTypeCode"
  [required]="formGroup.controls.idTypeCode.invalid"
  (selectionChange)="onTypeCodeChange($event.value)"
>
  <mat-option
    *ngFor="let typeCode of typeCodes$ | async"
    [value]="typeCode.id"
  >
    {{ typeCode.name }}
  </mat-option>
</mat-select>

或者在您的 HTML 模板上也(ngModelChange)没有(selectionChange)

<mat-select
  formControlName="idTypeCode"
  [required]="formGroup.controls.idTypeCode.invalid"
>
  <mat-option
    *ngFor="let typeCode of typeCodes$ | async"
    [value]="typeCode.id"
  >
    {{ typeCode.name }}
  </mat-option>
</mat-select>

稍后formGroup创建,然后订阅idTypeCode模态中的 formControl 更改:

  public ngOnInit(): void {
    // Some code thart you need

    this.formGroup = this.buildFormGroup();

    this.formGroup.get('idTypeCode')?.valueChanges.subscribe((value) => {
      // Do Here your Requirements
      console.log(`value: ${value}`);
    });

    // Your other code
  }

于 2021-11-15T07:21:35.257 回答