这个问题非常明显。我想拦截FormControl的value属性的传入值,并能够截取它与其连接的HTML控件的传出值。
我们说我有一个名为" firstName"的FormControl。然后我将它连接到文本框:
<input type="text" formControlName="firstName" />
默认情况下,当用户在文本框中输入值并提交时,FormControl的值将设置为文本框中的值。有没有什么方法可以拦截设置的值并在设置之前修改它?
同样,有没有办法拦截FormControl发送给HTML控件的值?例如,如果我将FormControl的值设置为某个值,但我想修改文本框中显示的值。
我知道我可以使用ngModel充当表单和控件之间的中介,但是当使用多个控件时,这会变得很麻烦。我也知道你可以创建自己的控件并实现ControlValueAccessor,但这也很麻烦,因为我必须为我想要使用的每个控件创建一个相应的控件。
有关我提出此问题的原因的详情,请参阅https://github.com/ionic-team/ionic/issues/7121
答案 0 :(得分:1)
您可以使用onBlur来调用函数(即modifyValue()
),然后利用patchValue来修改值:
<input type="text" onblur="modifyValue()" formControlName="firstName" />
modifyValue() {
this.form.patchValue({
firstName: this.form.firstName //modify firstName here
})
}
如果可行,您可以创建一个通用函数并传递键/值以便对其进行修补,而无需创建一堆特定函数
<input type="text" onblur="modifyValue('firstName')" formControlName="firstName" />
modifyValue(key) {
this.form.controls[key].patchValue(this.form.controls[key] // modify value here)
}
答案 1 :(得分:1)
您可以编写一个可重用的指令,以拦截来自视图和进入视图的值:
const MODIFIER_CONTROL_VALUE_ACCESSOR: Provider = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => ValueModifierDirective),
multi: true,
};
@Directive({
selector: '[valueModifier]',
host: { '(keyup)': 'doSomething($event)' },
providers: [MODIFIER_CONTROL_VALUE_ACCESSOR],
})
export class ValueModifierDirective implements ControlValueAccessor {
@Input() valueModifier: [Function, Function];
private writeToForm;
constructor(public _el: ElementRef) { }
doSomething(event: Event) {
const viewToForm = this.valueModifier[0];
this.writeToForm(viewToForm(event.target.value));
}
registerOnChange(fn: (value: any) => void) {
this.writeToForm = fn;
}
registerOnTouched(fn: any) {
// nothing to do
}
writeValue(value: any) {
const formToView = this.valueModifier[1];
this._el.nativeElement.value = formToView(value);
}
}
要使用它,只需将指令添加到在其上应用formControlName的同一元素上并传递transform-functions:
@Component({
selector: 'my-app',
template: `
<form [formGroup]="form">
<input [valueModifier]="[viewToForm, formToView]" name="value" type="text" formControlName="input" />
<button (click)="random()">Set Random Value</button>
</form>
`,
styleUrls: ['./app.component.css']
})
export class AppComponent {
form = new FormGroup({
input: new FormControl(1)
});
viewToForm = (text: string) => "toForm" + text;
formToView = (text: string) => "toView" + text;
constructor() {
this.form.valueChanges.subscribe(value => console.log(value));
}
random () {
this.form.patchValue({
input: Math.random()
})
}
}
实时示例(Stackblitz):
https://stackblitz.com/edit/angular-afmkxl?file=src%2Fapp%2Fapp.component.ts
以上内容适用于文本输入。我认为您可以为其他类型的输入编写类似的指令。
答案 2 :(得分:0)
您可以创建指令 inject the formControl in the directive,然后使用 emitModelToViewChange
的 emitViewToModelChange
和 setValue
选项。
像这样:
@Directive({
selector: '[valueModifier]',
})
export class ValueModifierDirective {
constructor(private control: NgControl) {}
private setValueOfModel() {
this.control.control!.setValue('Custom Value', { emitModelToViewChange: false });
}
}
此解决方案适用于任何类型的表单输入(输入、选择、复选框等)。