我正在构建自己的自定义输入字段。我想使用ControlValueAccessor
将FormGroup
与FormControlName
以及ngModel
一起使用。
问题是我在一个表单中有两个输入字段。这些输入不同步,但FormGroup
值同步。
以下是示例应用:https://stackblitz.com/edit/angular-9krudy
如果您在输入字段中更改值,则它不会反映在组件的值上,而是反映在FormGroup
值中。
如果使用my-input
组件更改值("随机更改值"按钮),则会更改组件中的值,但不会更改输入中的值。如前所述,FormGroup
中的值正在发生变化。
当我使用FormGroup
更改patchValue
值时,一切正常。
如何修复我的代码以始终保持同步?
我希望my-input
与ngModel
一起使用,因此传递FormGroup
并且取决于它不是一种选择。
修改
我发现在Angular
您不能拥有两个具有相同formNameControl
的输入字段:https://stackblitz.com/edit/angular-y2sj5g(好的,你可以但他们可以不同步)。所以这个问题无效。
编辑:代码
AppComponent:
import { Component } from '@angular/core';
import {FormControl, FormGroup} from "@angular/forms";
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
formGroup: FormGroup = new FormGroup({
text: new FormControl('text')
});
constructor() {
}
ngOnInit() {
}
onChange() {
this.formGroup.get('text')
.patchValue('New value');
}
}
AppComponentHtml
<form [formGroup]="formGroup">
<input type="text" [formControlName]="'text'">
<my-input [formControlName]="'text'"></my-input>
</form>
MyInputComponent:
import {Component, forwardRef, OnInit} from '@angular/core';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from "@angular/forms";
@Component({
selector: 'my-input',
template: `<hr>
In component
<p>
<a (click)="onChange()" href="javascript:void(null)">Change value randomly</a>
</p>
Value in component: <b>{{value}}</b>
<hr>`,
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => MyInputComponent),
multi: true
}
]
})
export class MyInputComponent implements ControlValueAccessor, OnInit {
protected _value: any;
constructor() {
}
ngOnInit() {
}
onChange() {
this.value = Math.random();
}
get value(): any {
return this._value;
}
set value(value: any) {
this._value = value;
this.propagateChange(this._value);
}
writeValue(value: any) {
console.log('Out from component', value);
if (value !== undefined) {
this._value = value;
}
}
propagateChange = (_: any) => {
};
registerOnChange(fn) {
this.propagateChange = fn;
}
registerOnTouched() {
}
}
答案 0 :(得分:0)
您的代码存在两个问题:
您的my-input
组件应在其模板中包含输入元素
@Component({
selector: 'my-input',
template: `
<input [value]="value"
(change)="onValueChanged($event)"
(keyup)="onValueChanged($event)"/>
...
其中onValueChanged
方法用于设置存储在组件中的值
onValueChanged(event) {
this.value = event.target.value;
}
您有两个具有相同formControlName
值的表单控件。将其更改为其他内容,例如
<form [formGroup]="formGroup">
Input: <input formControlName="otherInput"/> <br/>
My input: <my-input formControlName="text"></my-input>
</form>
formGroup: FormGroup = new FormGroup({
text: new FormControl('text'),
otherInput: new FormControl('otherText')
});
工作演示:https://stackblitz.com/edit/angular-t3qbaz?file=app/app.component.ts
答案 1 :(得分:0)
我发现在Angular中你不能有两个具有相同formNameControl的输入字段:https://stackblitz.com/edit/angular-y2sj5g(好的,你可以,但它们不同步)。所以这个问题无效。
修改强>
这是Angular's
功能:https://github.com/angular/angular/issues/10036