![](/img/trans.png)
[英]Why use function expression in Angular ControlValueAccessor implementation?
[英]Angular: custom input with ControlValueAccessor
如果自定义组件是另一个组件下的包装器,我不确定如何使用它。
喜欢:
ComponentA_withForm
|
--ComponentA1_withWrapperOfCustomInput
|
--ComponentA11_withCustomInput
如果我有这样的结构:
ComponentA_withForm
|
--ComponentA11_withCustomInput
一切安好
但是对于我的情况(大量异步数据),我需要一个包装器......是否有可能以某种方式做到这一点?
这是我的小提琴代码:
组件A:
import { Component } from '@angular/core';
import { FormBuilder } from '@angular/forms';
@Component({
selector: 'my-app',
template: `<form [formGroup]="form"><custom-input-wrapper formControlName="someInput"></custom-input-wrapper></form> <p>value is: {{formVal | json}}</p>`
})
export class AppComponent {
form = this.fb.group({
someInput: [],
});
get formVal() {
return this.form.getRawValue();
}
constructor(private fb: FormBuilder) { }
}
组件A1:
import { Component } from '@angular/core';
@Component({
selector: 'custom-input-wrapper',
template: '<custom-input></custom-input>',
})
export class CustomInputWrapperComponent {
constructor() { }
}
组件A11:
import { Component, forwardRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
@Component({
selector: 'custom-input',
template: `Hey there! <button (click)="inc()">Value: {{ value }}</button>`,
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => CustomInputComponent),
multi: true,
}],
})
export class CustomInputComponent implements ControlValueAccessor {
private value = 0;
writeValue(value: number): void {
this.value = value;
}
registerOnChange(fn: (_: any) => void): void {
this.onChangeFn = fn;
}
registerOnTouched(fn: any): void {
}
inc() {
this.value = this.value + 1;
this.onChangeFn(this.value);
}
onChangeFn = (_: any) => { };
}
在这里我有一个工作示例: https : //stackblitz.com/edit/angular-qmrj3a
所以:基本上删除和重构代码不使用CustomInputWrapperComponent
使我的代码工作。 但是我需要这个包装器,我不确定如何传递formControlName
。
我不想要通过父 formGroup 的肮脏解决方案:)
由于您不想要一个肮脏的解决方案 ;) ,您也可以在CustomInputWrapperComponent
实现ControlValueAccessor
。 这样,父项中的任何更改都将反映在子项中,子项中的任何更改也将反映在父项中,只需几行代码。
包装组件
@Component({
selector: 'custom-input-wrapper',
template: '<custom-input [formControl]="value"></custom-input>',
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => CustomInputWrapperComponent),
multi: true,
}]
})
export class CustomInputWrapperComponent implements AfterViewInit, ControlValueAccessor {
public value = new FormControl();
constructor() { }
ngAfterViewInit() {
this.value.valueChanges.subscribe((x) => {
this.onChangeFn(x);
});
}
writeValue(value: number): void {
this.value.setValue(value);
}
registerOnChange(fn: (_: any) => void): void {
this.onChangeFn = fn;
}
registerOnTouched(fn: any): void {
}
onChangeFn = (_: any) => { };
}
父模板
<form [formGroup]="form"><custom-input-wrapper formControlName="someInput"></custom-input-wrapper></form> <p>value is: {{formVal | json}}</p>
我在这里做了一个 stackbitz 演示 - https://stackblitz.com/edit/angular-csaxcz
您不能在custom-input-wrapper
上使用formControlName
,因为它没有实现ControlValueAccessor
。 在custom-input-wrapper
上实现ControlValueAccessor
可能是一个解决方案,但它似乎有点矫枉过正。 而是将控件从 formGroup 作为@Input()
传递给custom-input-wrapper
并将输入的 formControl 传递给custom-input
应用组件
@Component({
selector: 'my-app',
template: `<form [formGroup]="form"><custom-input-wrapper [formCtrl]="form.get('someInput')"></custom-input-wrapper></form> <p>value is: {{formVal | json}}</p>`
})
export class AppComponent {
form = this.fb.group({
someInput: [],
});
get formVal() {
return this.form.getRawValue();
}
constructor(private fb: FormBuilder) { }
}
custom-input-wrapper.component
@Component({
selector: 'custom-input-wrapper',
template: '<custom-input [formControl]="formCtrl"></custom-input>',
})
export class CustomInputWrapperComponent {
@Input() formCtrl: AbstractControl;
constructor() { }
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.