【问题标题】:How can I pass a FormControl to a function from the template?如何将 FormControl 从模板传递给函数?
【发布时间】:2020-03-18 18:51:58
【问题描述】:

假设我有这个:

<input formControlName="someName" (click)="onClick()">

我希望我的onClick 函数是通用的,并设置相应FormControl(我点击的那个)的值。

如何将关注的FormControl作为onClick的参数传递?

我想我可以从FormControlDirectiveFormControlNamecontrol 属性中检索它,但它们都没有exportAs 属性。

【问题讨论】:

  • 我已经添加了一个答案,希望它能完成你的任务。
  • 不,我的问题比click事件更广泛,它更多的是关于如何将FormControl作为函数的参数传递,因为FormControl可以是由以下组成的结构的任何节点多个FormGroupFormArray
  • 那么我建议您编辑您的问题并根据您的确切要求正确更新它。
  • 我已经给你留下了答案,它是否满足你的要求。
  • @SatishShrestha 是的,我支持你

标签: javascript angular angular-reactive-forms


【解决方案1】:

我认为这就是你想要实现的目标。

import { Directive, HostListener, Optional, Output, EventEmitter } from '@angular/core';
import { NgControl, FormControl } from '@angular/forms';

@Directive({
  selector: '[appOnClickControl]' // if you want to target specific form control then use custom selector else you use can use input:
                                   // selector: 'input' to target all input elements
})
export class TestDirective {
  @Output() emitFormControl = new EventEmitter<FormControl>();

  constructor(@Optional() private formControl: NgControl) {
  }


  /**
   * If your only goal is to set value to the form control  then use this
   */
  @HostListener('click')
  onClick() {
    if (this.formControl) {
      this.formControl.control.setValue('test');
    }
  }

  /**
   * If you wanna pass the form control through the function you might use this
   */
  @HostListener('click')
  getFormControl(): void {
      this.emitFormControl.emit(this.formControl.control as FormControl);
  }
}
 <input
  appOnClickControl // use this to initialize directive
  (emitFormControl)="yourMethod($event)" // $event is the clicked form control
  formControlName="test"
></input>

【讨论】:

    【解决方案2】:

    在您的 html 中:

    <input formControlName="someName" (click)="onClick($event)">
    

    然后将你的 onClick 函数定义为:

    onClick(event): void {
     alert(event.target.value)
    }
    

    编辑 获取 FormControl:

    <input formControlName="someName" (click)="onClick(Form.get('someName'))">
    

    onClick(formControl): void {
        formControl.setValue(someValue);
      }
    

    【讨论】:

    • 我不想要 HTML 元素,我想要 FormControl
    • 编辑我的答案以获得 FormControl
    【解决方案3】:

    有点重复,但很确定你只能这样做:

    <input formControlName="someName" (click)="onClick('someName')">
    

    然后在表单组上使用 someName 来查找控件

    onClick(name: string) {
      const fc = this.form.get(name);
      // do whatever
    }
    

    【讨论】:

    • 这表明我在FormGroup 结构中找到了控件,它不一定是this.form.get(name)(可能嵌套在FormGroupFormArray 等...)。所以我不能有onClick的一个独特的通用实现@
    • 您可以传递名称以获取类似“nested.property.name”以访问嵌套表单
    • 仍然不允许onClick 是通用的
    • 它与您在这种情况下的通用性大致相同,无需通过在模板中调用 get 直接传递表单控件,我认为最好在模板中少做一些,而是编写围绕“通用”函数的适配器函数
    【解决方案4】:

    不完全确定您追求的是什么,但请尝试以下方法是否适合您。它使用setValue() 方法为表单设置值。如果您只想设置表单的部分值,也可以使用patchvalue

    模板

    <form [formGroup]='groupedform' >
      <label>Name:  <br>
        <input type="text" formControlName='Name' required (mousedown)="onMouseDown(groupedform)"/>
      </label>
      <br>
      <br>
      <label>Email:  <br>
        <input type="email" formControlName='Email' required (mousedown)="setEmail(groupedform)"/>
      </label>
      <p>
      <button type="submit" [disabled]="!groupedform.valid" (click)="updateName()">Update Name</button>
      </p>
    </form>
    

    组件

    export class AppComponent  {
       name = 'Angular';
       firstname = new FormControl('');
       groupedform = this.fb.group({
        Name : ['', Validators.required],
        Email: [],
      });
    
      constructor(private fb:FormBuilder) { }
    
      updateName() {
        console.log(this.groupedform.value);
      }
    
      onMouseDown(formControl: any) {
        this.groupedform.setValue({
          'Name': 'sample',
          'Email': 'sample@example.com'
        });
      }
    
      setEmail(formControl: any) {
        this.groupedform.patchValue({
          'Email': 'sample@example.com'
        });
      }
    }
    

    工作示例:Stackblitz

    【讨论】:

      【解决方案5】:

      您可以为此使用模板变量

      <input formControlName="someName" #temp (click)="onClick(temp)">
      
      onClick(val) {
      console.log(val);}
      

      【讨论】:

      • 这将传入输入元素。而不是formControl
      【解决方案6】:

      我不确定你要设置什么类型的值,但是你可以使用属性指令来进行这种类型的常见操作(如果它很简单的话)。

      您可以创建一个属性指令并在所有表单控件上设置,属性指令逻辑会自动为您处理。您可以定义地配置传递给指令的值。

      从“@angular/core”导入{ Directive, HostListener, ElementRef, Input };

      @Directive({
        selector: '[clickMe]'
      })
      export class ClickDirective {
        @Input('clickMe') clickValue:string;
        constructor(private elementRef: ElementRef){}
      
        @HostListener('click') onClick() {
          this.elementRef.nativeElement.value = this.clickValue;
        }
      }
      

      现在只需将这些指令与表单控件一起使用并传递您的值,您也可以使用数据绑定。

      <form [formControl]="myForm">
        Firstname:<input type="text" fromControlName="firstname" [clickMe]="'first value'" />
      <br>
      Lastname:<input type="text" fromControlName="lastname" [clickMe]="'last value'" />
      </form>
      

      请在此处找到有效的 stackblitz:https://stackblitz.com/edit/angular-j1kwch

      【讨论】:

        【解决方案7】:

        您可以使用传递的事件并从中获取属性名称:

        <input type="text" class="form-control" formControlName="yourName" (blur)="yourMethod($event)" />
        

        然后在您的方法中从目标中获取formControlName 的名称:

        yourMethod(event: any) {
          const controlName = e.target.getAttribute('formcontrolname');
          this.formGroup.get(controlName); // this is your FormControl
          ....
        }
        

        【讨论】:

          猜你喜欢
          • 2014-03-11
          • 1970-01-01
          • 2017-12-25
          • 2017-03-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多