【发布时间】:2021-11-30 10:10:10
【问题描述】:
使用 Angular 12,我想验证和检测列表中的更改。
我有一个属性网格(键/值对表,列出具有可编辑值的属性,但每个值可以是不同的类型,字符串/布尔值/int/等)。
我想为该属性网格添加验证和更改检测。
应该对每个项目进行验证,并且只需要对整个列表进行更改检测(不关心更改了哪一行/项目)。
我已经构建了这样的东西:
export class InnerSetting {
key!: string;
displayName!: string;
originalValue?: string;
value?: string;
type!: PropertyTypeEnum; //string | int | boolean | ...
validation?: string;
minValue?: number;
maxValue?: number;
isNullable!: boolean
}
constructor(private formBuilder: FormBuilder) {
this.form = this.formBuilder.group({
properties: new FormArray([])
});
}
ngOnInit(): void {
this.settings.forEach(item => this.formArray.push(this.formBuilder.group(
{
key: [item.key],
type: [item.type],
name: [item.displayName],
value: [ item.value, [Validators.required, Validators.minLength(2)] ], //Depends on type and validation stuff, will be added later.
originalValue: [ item.originalValue ]
}
)));
//Not sure which of these will work, so added both for now.
this.form.valueChanges.pipe(debounceTime(500)).subscribe(changes => {
this.areChangesDetected = changes != null;
});
this.formArray.valueChanges.pipe(debounceTime(500)).subscribe(changes => {
this.areChangesDetected = changes != null;
});
}
get formArray() {
return this.form.controls.properties as FormArray;
}
在使用Form 之前,我只是使用InnerSetting 列表,所以请记住,我刚开始用表单替换列表。
setting 属性是一个 InnerSetting 对象。
<form [formGroup]="form" class="group-wrapper">
<div class="d-flex item-row" *ngFor="let setting of formArray.controls; let i = index">
<div class="item flex-fill d-flex" [ngSwitch]="setting.type" [formGroupName]="i">
<span>{{setting.name}}</span>
<select *ngSwitchCase="'boolean'" class="flex-grow-1" name="role" id="role-select" [(ngModel)]="setting.value">
<option [value]="'0'">False</option>
<option [value]="'1'">True</option>
</select>
<div contenteditable *ngSwitchDefault class="flex-grow-1" type="text" [id]="setting.key" [innerText]="setting.value"></div>
</div>
<button class="remove-relation" (click)="reset(setting)">
<fa-icon [icon]="faUndo"></fa-icon>
</button>
</div>
</form>
问题
因为我需要根据设置类型(布尔值、字符串、数字等)显示不同的元素。如何从formArray.controls 访问该信息?
另外,如何使用contenteditable 绑定到非标准输入控件,例如我的div?
编辑
我注意到formArray.controls 是FormGroup 的数组,我可以访问this.formArray.controls[0].controls['name'].value 中的值。
现在的问题是根据类型将该控件设置为字段(选择或 div 或输入)。
【问题讨论】:
-
这里
*ngFor="let setting of formArray.controls;你的设置是FormGroup。如果你想从setting访问displayName,你可以做setting.get('displayName').value。如果您可以在 stackblitz.com 上提供它,我可以提供更适当的帮助 -
要使用
contenteditable将formControl绑定到div,您需要通过实现https://angular.io/api/forms/ControlValueAccessor接口来创建自定义formControl -
谢谢,它通过使用
setting.get('name').value访问器工作。现在的问题是将控件绑定到输入和特殊输入。我会看看上面的链接。 -
我尝试使用
[formControl]="setting.get('value')",但它抱怨AbstractControl | null不能分配给FormControl。 -
问题是当你从 FormGroup 获取时,你会得到
AbstractControl而不是 FormControl,因为你的settingFG 不知道它的 FormControl。它只是返回我们无法分配给[formControl]的 AbstractControl。你能在stackblitz上分享吗,
标签: angular angular-reactive-forms angular-controlvalueaccessor