反应式表单不适用于 ControlValueAccessor
Reactive Forms Not Working with ControlValueAccessor
我构建了一个名为TextBox
的控件,为了简单起见,我将post控件的相关部分放在这里。
@Component({
selector: 'app-textbox',
template:
`
<input [(ngModel)]="value" [disabled]="disabled" />
`,
styleUrls: ['./textbox.component.css']
})
export class TextboxComponent implements OnInit, ControlValueAccessor {
constructor() { }
writeValue(obj: any): void {
this._value = obj;
}
registerOnChange(fn: any): void {
this.onChange = fn;
}
registerOnTouched(fn: any): void {
this.onTouch = fn;
}
setDisabledState?(isDisabled: boolean): void {
this.disabled = isDisabled;
}
disabled = false;
onChange:()=>{}
onTouch:()=>{};
private _value:string;
public get value():string {
return this._value
}
public set value(value:string){
this._value = value;
}
ngOnInit(): void {
}
我的 app.component.ts 看起来像:
@Component({
selector: 'app-root',
template:
`
<form [formGroup]="form" novalidate>
<div>
<label >Name</label>
<app-textbox formControlName="name"></app-textbox>
</div>
</form>
`,
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit{
/**
*
*/
constructor(private formBuilder:FormBuilder) {
}
form = this.formBuilder.group({
name:['', Validators.required]
})
model:NameModel = {
name:'test'
}
ngOnInit(): void {
this.form.get('name').setValue(this.model.name);
}
}
interface NameModel{
name:string;
}
当我 运行 应用程序时,我希望文本框会填充值 test。
有人可以解释为什么不是吗?
我会在添加时添加 this.form.get('name')?.value
我得到正确的值。
在writeValue(obj)
中,您需要将收到的输入obj
分配给this._value
writeValue(obj: any): void {
if (obj !== this._value) {
this._value = obj;
}
}
并且不要忘记为 NG_VALUE_ACCESSOR
添加提供程序和多提供程序以扩展现有提供程序。 (参考参考文献1)
@Component({
selector: 'app-textbox',
template: `
<input [(ngModel)]="value" [disabled]="disabled" />
`,
styleUrls: ['./textbox.component.css'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => TextboxComponent),
multi: true
}
]
})
export class TextboxComponent implements OnInit, ControlValueAccessor {
writeValue(obj: any): void {
if (obj !== this.value) {
this._value = obj;
}
}
...
}
参考资料
Connect your custom control to ngModel with Control Value Accessor.
您只需将值 this.form.get('name').setValue(this.model.name);
设置为 ngAfterViewInit
而不是 ngOnInit
,或者您必须在它之后调用:
this.form.updateValueAndValidity();
顺便说一句,这里有两个注意事项您应该注意:
- 在
TextboxComponent
中更改值后,您错过了将值写回表单控件,因此您必须在值 setter 中调用已注册的 onChange
方法像下面这样:
private _value: string;
public get value(): string {
return this._value;
}
public set value(value: string) {
this._value = value;
this.onChange(value);
}
- 你的情况最好在
ngOnInit
中初始化FormGroup
,直接设置name
的默认值,如下所示:
form: FormGroup;
ngOnInit(): void {
this.form = this.formBuilder.group({
name: [this.model.name, Validators.required],
});
}
我构建了一个名为TextBox
的控件,为了简单起见,我将post控件的相关部分放在这里。
@Component({
selector: 'app-textbox',
template:
`
<input [(ngModel)]="value" [disabled]="disabled" />
`,
styleUrls: ['./textbox.component.css']
})
export class TextboxComponent implements OnInit, ControlValueAccessor {
constructor() { }
writeValue(obj: any): void {
this._value = obj;
}
registerOnChange(fn: any): void {
this.onChange = fn;
}
registerOnTouched(fn: any): void {
this.onTouch = fn;
}
setDisabledState?(isDisabled: boolean): void {
this.disabled = isDisabled;
}
disabled = false;
onChange:()=>{}
onTouch:()=>{};
private _value:string;
public get value():string {
return this._value
}
public set value(value:string){
this._value = value;
}
ngOnInit(): void {
}
我的 app.component.ts 看起来像:
@Component({
selector: 'app-root',
template:
`
<form [formGroup]="form" novalidate>
<div>
<label >Name</label>
<app-textbox formControlName="name"></app-textbox>
</div>
</form>
`,
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit{
/**
*
*/
constructor(private formBuilder:FormBuilder) {
}
form = this.formBuilder.group({
name:['', Validators.required]
})
model:NameModel = {
name:'test'
}
ngOnInit(): void {
this.form.get('name').setValue(this.model.name);
}
}
interface NameModel{
name:string;
}
当我 运行 应用程序时,我希望文本框会填充值 test。
有人可以解释为什么不是吗?
我会在添加时添加 this.form.get('name')?.value
我得到正确的值。
在writeValue(obj)
中,您需要将收到的输入obj
分配给this._value
writeValue(obj: any): void {
if (obj !== this._value) {
this._value = obj;
}
}
并且不要忘记为 NG_VALUE_ACCESSOR
添加提供程序和多提供程序以扩展现有提供程序。 (参考参考文献1)
@Component({
selector: 'app-textbox',
template: `
<input [(ngModel)]="value" [disabled]="disabled" />
`,
styleUrls: ['./textbox.component.css'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => TextboxComponent),
multi: true
}
]
})
export class TextboxComponent implements OnInit, ControlValueAccessor {
writeValue(obj: any): void {
if (obj !== this.value) {
this._value = obj;
}
}
...
}
参考资料
Connect your custom control to ngModel with Control Value Accessor.
您只需将值 this.form.get('name').setValue(this.model.name);
设置为 ngAfterViewInit
而不是 ngOnInit
,或者您必须在它之后调用:
this.form.updateValueAndValidity();
顺便说一句,这里有两个注意事项您应该注意:
- 在
TextboxComponent
中更改值后,您错过了将值写回表单控件,因此您必须在值 setter 中调用已注册的onChange
方法像下面这样:
private _value: string;
public get value(): string {
return this._value;
}
public set value(value: string) {
this._value = value;
this.onChange(value);
}
- 你的情况最好在
ngOnInit
中初始化FormGroup
,直接设置name
的默认值,如下所示:
form: FormGroup;
ngOnInit(): void {
this.form = this.formBuilder.group({
name: [this.model.name, Validators.required],
});
}