首页 文章

如何在设置或获取之前拦截FormControl的值?

提问于
浏览
5

这个问题非常明显 . 我想拦截FormControl的value属性的传入值,并能够截取它连接到的HTML控件的传出值 .

假设我有一个名为“firstName”的FormControl,我把它连接到文本框,如下所示:

<input type="text" formControlName="firstName" />

默认情况下,当用户在文本框中输入值并提交时,FormControl的值将设置为文本框中的值 . 有没有什么方法可以拦截设置的值并在设置之前修改它?

同样,有没有办法拦截FormControl发送到HTML控件的值?例如,如果我将FormControl的值设置为某些内容,但我想修改文本框中显示的值 .

我知道我可以使用ngModel作为表单和控件之间的中介,但是当使用多个控件时,这会变得很麻烦 . 我也知道你可以创建自己的控件并实现ControlValueAccessor,但这也很麻烦,因为我必须为我想要使用的每个控件创建一个相应的控件 .

有关我提出此问题的原因的详细信息,请参阅https://github.com/ionic-team/ionic/issues/7121

2 回答

  • 0

    您可以使用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

    您可以编写一个可重用的指令来拦截来自和进入视图的值:

    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

    以上工作用于文本输入 . 我认为你可以为其他类型的输入编写类似的指令 .

相关问题