【问题标题】:Angular - How do I detect form events from inside a directive when they are initiated in component.ts file?Angular - 当它们在 component.ts 文件中启动时,如何从指令内部检测表单事件?
【发布时间】:2019-08-03 04:14:27
【问题描述】:

如果我有一个带有表单输入的组件,并且我想将 OnInit 块中的两个语句检测为指令中的事件,那么正确的方法是什么?我对“输入”和“ngModelChange”很幸运,但是我尝试听的任何事件都没有捕捉到模型驱动表单的 patchValue() 方法或模板驱动表单的直接分配(即使它反映在 DOM 中) .

这是我的组件:

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl } from '@angular/forms' 

@Component({
  selector: 'my-app',
  template:
  `
  <h5>Model form input</h5>
  <form [formGroup]="inputForm">
    <input patchable-input formControlName="input" />
  </form>

  <h5>Template form input</h5>
  <input patchable-input [(ngModel)]="input" />
  `
})
export class AppComponent implements OnInit {
  inputForm = new FormGroup({
    input: new FormControl('')
  })

  input = '';

  ngOnInit() {
    this.inputForm.patchValue({
      input: 'testing patch'
    })

    this.input = 'testing override'
  }
}

这是我的指令:

import { Directive, HostListener } from '@angular/core';

@Directive({
  selector: '[patchable-input]'
})
export class PatchableInputDirective  {
  @HostListener('ngModelChange', ['$event']) ngOnChanges($event) {
        console.log($event);
    }
}

还有一个minimal reproduction in StackBlitz(观看控制台)

【问题讨论】:

    标签: javascript angular angular-reactive-forms angular-directive angular-forms


    【解决方案1】:

    您必须实现AfterViewInit 而不是OnInit。原因是在生命周期的这一点上,您的指令已被初始化并通过 @HostListener 装饰器订阅了 ngModelChange 事件。

    另请参阅Angular Life Cycle Hooks documentation

    stackblitz


    import { Component, AfterViewInit } from '@angular/core';
    import { FormGroup, FormControl } from '@angular/forms' 
    
    @Component({
      selector: 'my-app',
      template:
      `
      <h5>Model form input</h5>
      <form [formGroup]="inputForm">
        <input patchable-input formControlName="input" />
      </form>
    
      <h5>Template form input</h5>
      <input patchable-input [(ngModel)]="input" />
      `
    })
    export class AppComponent implements AfterViewInit {
      inputForm = new FormGroup({
        input: new FormControl('')
      })
    
      input = '';
    
      ngAfterViewInit() {
        this.inputForm.patchValue({
          input: 'testing patch'
        })
      }
    }
    

    【讨论】:

    • 标记为已解决,因为您的示例按预期工作,谢谢!那么更新模板驱动元素呢?当我尝试设置 input 的值时,我得到了一个控制台错误,没有太多的堆栈跟踪。
    • @user3280523 - 对不起,我不明白你的问题。在答案中使用 stackblitz 我可以在输入字段中输入并登录指令,这就是你的意思吗?
    • 对不起,我不清楚。我已经更新了the stackblitz,见第 29 行,以及它在控制台中产生的错误。
    • @user3280523 - 如果您将输入分配移动到ngOnInit,它会修复错误。 modified stackblitz
    • 首先感谢您的额外帮助。非常感激。我更新了那个stackblitz,你是对的,错误消失了,但是指令中没有检测到更新。这只是角度的限制吗?当然有一种方法可以在一个与模型和模板驱动的表单很好地配合使用的实现下工作......如果不是那真的很令人沮丧
    猜你喜欢
    • 2020-02-11
    • 1970-01-01
    • 2020-02-05
    • 2011-03-13
    • 1970-01-01
    • 2019-08-17
    • 1970-01-01
    • 2020-09-16
    • 1970-01-01
    相关资源
    最近更新 更多