【问题标题】:Angular : onClick on html element according to its classAngular:根据其类单击html元素
【发布时间】:2019-03-11 20:51:58
【问题描述】:

在我的 Angular 应用程序下,我正在使用一些在我的组件中呈现的第三个库小部件。

我的模板是:

<div>
  <myWidGet></myWidGet>
</div>

myWidGet 里面有一些按钮元素,我想处理它们的事件。 该按钮有这些类:.dx-edit-row .dx-command-edit .dx-link-save

所以我这样做了:

export class myClass AfterViewInit { 

  constructor(private elRef: ElementRef){}

  ngAfterViewInit() {
    this.elRef.nativeElement.querySelector('.dx-edit-row .dx-command-edit .dx- 
link-save').on('click', (e) => {
      alert('test');
    });
  }

}

我的目的是获取参考到我的按钮并从中处理点击事件

建议?

【问题讨论】:

  • 我觉得我有点困惑。为什么要在 Angular 中使用原生 JS 查询选择器?您无法与这些按钮进行任何交互?
  • 也许用ViewChild 获取myWidGet 并尝试用querySelector 获取按钮。虽然,这种做事方式不是“Angular”方式,但该按钮应该发出 Output 事件...
  • 您可以在div 上设置click 事件处理程序并检查event.target 的类以确定是否单击了小部件按钮(假设click 事件传播没有停止)。
  • 参见this stackblitz 了解事件委托的示例,正​​如我之前的评论中所建议的那样。

标签: javascript angular angular5 angular6 angular2-template


【解决方案1】:

通常,第 3 方小部件应提供如下点击处理程序:

<myWidGet (click)="myFunction($event)"></myWidGet>

在控制器中:

myFunction(evt) {
  const target = evt.target
  console.log('test')
}

但是,如果他们不公开点击处理程序,那么我会认真考虑不使用小部件。

如果仍然想使用小部件,那么使用 jQuery 来执行此操作:

ngAfterViewInit() {
  $('.dx-edit-row.dx-command-edit.dx-link-save').on('click', (evt) => {
    const target = evt.target
    console.log('test')
  });
}

以上假设所有这些类都出现在同一个按钮上。

或者只使用原版 JS。

如果按钮在 ngAfterViewInit() 上不可用,那么您可以这样做:

ngAfterViewInit() {
  const interval = setInterval(() => {
    const button = $('.dx-edit-row.dx-command-edit.dx-link-save')
    // if button is ready
    if (button) {
      // add click handlers
      button.on('click', (evt) => {
        const target = evt.target
        console.log('test')
      });
      // stop polling
      clearInterval(interval)
    }
  }, 100)
}

【讨论】:

  • 我试过用 jquery 来做:问题是,这个按钮会在一段时间后出现(它是我应该打开一些下拉菜单来查看按钮的表),所以我无法获得控制台.log 工作
  • 好的,如果按钮在 ngOnViewInit() 中不可用,您将不得不进行轮询,我将在我的答案中添加一个示例 - 此代码将一直触发,直到按钮准备好然后添加单击处理程序,然后停止触发,这不是很好,但是如果您不使用专业的 3rd 方库,就会发生这种情况
  • 我正在使用 DevExpress 的 devextereme-angular,对于某些小部件(数据网格),缺少编辑事件
  • 这是该库的链接,实际上我们在工作中使用它,它是一个很好的库 - js.devexpress.com/Demos/WidgetsGallery/Demo/DataGrid/…
  • 我从来没有用它编辑过,但我相信数据是双向绑定的,所以当您更改控制器中的数据网格数据时,数据网格中的数据会更新,反之亦然,也许您的控制器数据正在更新,因此您不需要处理编辑事件?
【解决方案2】:

使用 jQuery 访问 DOM 元素并不是一个好习惯。将ElementRefRenderer2 一起使用。此外,在 Angular 中没有像 ngOnViewInit 这样的东西。我是ngAfterViewInit

加载视图后,在ngAfterViewInit 中,您可以使用ElementRef 实例上的nativeElement 访问HTMLElement。您应该将其显式类型转换为HTMLElement 以获得智能。

然后您可以在其上调用querySelector 并将类传递给它。这将为您提供按钮元素。

现在您使用Renderer2 的实例的listen 方法。这需要三个参数:

  1. 您要监听事件的元素 (btnElement)。
  2. 事件名称(click)。
  3. 回调函数。

这将转化为如下代码:

constructor(
  private el: ElementRef,
  private renderer: Renderer2
) {}

ngAfterViewInit() {
  const btnElement = (<HTMLElement>this.el.nativeElement)
    .querySelector('.dx-edit-row.dx-command-edit.dx-link-save');

  this.renderer.listen(btnElement, 'click', () => {
    alert('Buton was clicked');
  });
}

这里有一个Working StackBlitz 供您参考。

【讨论】:

  • `ElementRef' 并不是一个更好的做法
  • @CristianTraìna,你在什么地方提到过吗?我想了解更多。我只是觉得这比用 jQuery 污染你的 Angular 代码要好。
  • @SiddAjmera 怎么办,如果我的按钮在ViewInit 之后没有出现(我会打开一个下拉菜单来查看按钮)? ..当然不用参考下拉打开的点击
  • 你的意思是你的按钮在视图加载时没有出现在 DOM 中?
  • @SiddAjmera 您不应该只查询方法中的元素。以角度直接访问 DOM 被认为是一种不好的做法。最好只使用默认的(点击)事件处理程序,角度方式
【解决方案3】:

您可以使用 Angular 指令自定义第三方小部件。它将允许使用 renderer2 访问 DOM 元素并附加侦听器。

<myWidGet customEvents></myWidGet>

指令:

@Directive({
   selector: '[customEvents]'
})
export class CustomEventsDirective implements OnInit {
    private element: any;
    constructor(private el: ElementRef, private renderer: Renderer2) {
        this.element = el.nativeElement;
    }
    ngOnInit() {

       const btnElement = this.element.querySelector('.dx-edit-row.dx-command-edit.dx-link-save');

       this.renderer.listen(btnElement, 'click', () => {
         alert('Buton was clicked');
       });
    }
}

【讨论】:

  • 太棒了,但它缺少一些东西:我的按钮没有出现在widegt的Inti上(它出现在同一个小部件内的一些下拉菜单打开后,怎么做?
  • ERROR TypeError: Cannot read property '__zone_symbol__addEventListener' of null
  • 您可以使用 *ngIf 来处理这个问题。根据您的条件将布尔值设置为 true。
  • 你已经明白了。自小部件初始化以来,小部件内的按钮未显示,因此我收到了最后一条错误消息。当按钮出现时我如何初始化通风口监听器
  • 我将这些逻辑移至“AfterViewInit”生命周期挂钩
猜你喜欢
  • 2023-03-21
  • 2020-06-06
  • 2013-10-28
  • 1970-01-01
  • 2019-07-15
  • 1970-01-01
  • 1970-01-01
  • 2021-06-22
  • 1970-01-01
相关资源
最近更新 更多