[英]Angular - Reactive Form: How to correctly get values of dynamical and reusable sub-forms
I am working on a form as below我正在制作如下表格
My code我的代码
nested-form.component.ts嵌套-form.component.ts
public nestedForm: FormGroup;
constructor(
private formBuilder: FormBuilder) {
this.calibrationForm = this.buildFormGroup(formBuilder);
}
buildFormGroup(formBuilder: FormBuilder): FormGroup {
return new FormGroup({
motor: new FormControl('', Validators.required),
properties: new FormControl(""),
});
}
save() {
console.log(this.nestedForm.value);
}
nested-form.component.html嵌套形式.component.html
<form [formGroup]="nestedForm" >
<mat-select class="field-select" [(ngModel)]="_selectedMotor"
(selectionChange)="selectMotor($event.value)" formControlName="motor">
<mat-option class="select-option" *ngFor="let item of motors" [value]="item">
item</b>
</mat-option>
</mat-select>
<app-properties formControlName="properties" [type] = "_selectedMotor"></app-properties>
...
</form>
properties.component.ts属性.component.ts
@Component({
...
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => PropertiesComponent),
multi: true
},
{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => PropertiesComponent),
multi: true
}
]
})
export class PropertiesComponent implements OnInit, ControlValueAccessor {
@Input() type: string = null;
public propertiesForm: FormGroup;
ngOnInit(): void {
this.propertiesForm = this.buildFormGroup(this.formBuilder);
}
ngOnChanges(changes): void {
this.propertiesForm = this.buildFormGroup(this.formBuilder);
}
buildFormGroup(formBuilder: FormBuilder): FormGroup {
switch (this.type) {
case "OLD":
return new FormGroup(
{
tilt: new FormControl(0, [Validators.required]),
fine_tilt: new FormControl(0, [Validators.required]),
rotate: new FormControl(0, [Validators.required]),
fine_rotate: new FormControl(0, [Validators.required])
});
case "VINTEN":
return new FormGroup(
{
vinten_tilt: new FormControl(0, [Validators.required]),
vinten_rotate: new FormControl(0, [Validators.required])
});
}
}
public onTouched: () => void = () => { };
writeValue(val: any): void {
val && this.propertiesForm.setValue(val, { emitEvent: false });
}
registerOnChange(fn: any): void {
this.propertiesForm.valueChanges.subscribe(fn);
}
registerOnTouched(fn: any): void {
this.onTouched = fn;
}
setDisabledState?(isDisabled: boolean): void {
isDisabled ? this.propertiesForm.disable() : this.propertiesForm.enable();
}
validate(c: AbstractControl): ValidationErrors | null {
return this.propertiesForm.valid ? null : { invalidForm: { valid: false, message: "propertiesForm fields are invalid" } };
}
...
}
properties.component.html属性.component.html
<form *ngIf="type" class="col" [formGroup]="propertiesForm" [ngSwitch]="type">
<div *ngSwitchCase="OLD">
<input type="number" class="field-input" id="rotate" formControlName="rotate" />
<input type="number" class="field-input" id="fine_rotate" formControlName="fine_rotate" />
<input type="number" class="field-input" id="tilt" formControlName="tilt" />
<input type="number" class="field-input" id="fine_tilt" formControlName="fine_tilt" />
</div>
<div *ngSwitchCase="VINTEN">
<input type="number" class="field-input" id="rotate" formControlName="vinten_rotate" />
<input type="number" class="field-input" id="tilt" formControlName="vinten_tilt" />
</div>
</form>
Result:结果:
Let's say OLD is a default, when the form is loaded.假设加载表单时,OLD 是默认值。
I entered all fields and click Save button for OLD, the form values is collected correctly as expected.我输入了所有字段并单击 OLD 的保存按钮,表单值按预期正确收集。
However, when I switched from OLD to VINTEN, the form UI is updated but valid/invalid state of Save button is not working any more, and after clicking Save button, the form values are still the OLD properties values, not VINTEN properties values.但是,当我从 OLD 切换到 VINTEN 时,表单 UI 已更新,但保存按钮的有效/无效 state 不再起作用,并且单击保存按钮后,表单值仍然是 OLD 属性值,而不是 VINTEN 属性值。
Did I miss something or make something wrong?我错过了什么或做错了什么吗? Any suggestion is appreciated.任何建议表示赞赏。
To notify parent control about internal changes you have to listen propertiesForm.valueChanges()
.要通知父控件内部更改,您必须侦听propertiesForm.valueChanges()
。
And call fn
that you were given by registerOnChange(fn: any): void
并调用 registerOnChange( fn
registerOnChange(fn: any): void
给你的 fn
onModelChange = () => {}
ngOnInit(): void {
this.propertiesForm = this.buildFormGroup(this.formBuilder);
this.propertiesForm.valueChanges().subscribe(value => this.onModelChange(value))
}
registerOnChange(fn: any): void {
this.onModelChange = fn;
}
Thanks Yuriry,谢谢尤里,
Though his answer didn't resolve my issue directly and fully, it's a main lead for me to the final solution of my issue.虽然他的回答并没有直接彻底地解决我的问题,但它是我最终解决问题的主要线索。 Just leave here for any reference:留在这里以供参考:
export class PropertiesComponent implements OnInit, ControlValueAccessor {
@Input() type: string = null;
subscriptions: Subscription[] = [];
...
ngOnChanges(changes): void {
this.subscriptions.forEach(s => s.unsubscribe());
this.propertiesForm = this.buildFormGroup(this.formBuilder);
this.subscriptions.push(
this.propertiesForm.valueChanges.subscribe(value => {
this.onChange(value);
this.onTouched();
})
);
}
...
onChange: any = () => {};
registerOnChange(fn: any): void {
this.onChange = fn;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.