Angular 上的间接条件必需验证(嵌套 属性)
Indirectly Conditional Required Validations (nested property) on Angular
我正在检查此 question 及其答案,以便 post。
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;
}
我跳过填充可观察对象的代码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 中,我将 Select
与之前的可观察 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
而codeEnum
等于Second
我需要申请:
fieldSlave: ['', [Validators.required, Validators.maxLength(256), Validators.minLength(1)]],
如何实现?
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
);
}
编辑:
您可以在 HTML 模板上使用:selectionChange
<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
}
我正在检查此 question 及其答案,以便 post。
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;
}
我跳过填充可观察对象的代码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 中,我将 Select
与之前的可观察 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
而codeEnum
等于Second
我需要申请:
fieldSlave: ['', [Validators.required, Validators.maxLength(256), Validators.minLength(1)]],
如何实现?
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
);
}
编辑:
您可以在 HTML 模板上使用:selectionChange
<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
}