简体   繁体   English

单击 eventListener 绑定在动态 HTML Angular 12 上不起作用

[英]Click eventListener binding not working on dynamic HTML Angular 12

i have an issue while click binding on dynamic html.I tried setTimeout function but click event not binding on button.i have also tried template referance on button and get value with @ViewChildren but @ViewChildren showing null value.我在动态 html 上单击绑定时遇到问题。我尝试了setTimeout function 但单击事件未绑定在按钮上。我还尝试在按钮上引用模板并使用@ViewChildren获取值,但@ViewChildren显示 Z37A6259CC0489DFF02E 值。6

Typscript打字稿

export class AddSectionComponent implements OnInit {
      sectionList: any = [];
      constructor(private elRef: ElementRef,private _httpService: CommonService ,private sanitized: DomSanitizer) { }
    
      ngOnInit(): void {
        this.getSectionList();
      }
      ngAfterViewInit() {
          let element = this.elRef.nativeElement.querySelector('button');
          if (element) {
            element.addEventListener('click', this.bindMethod.bind(this));
          }
      }
      bindMethod() {
        console.log('clicked');
      }
      sanitizeHtml(value: string): SafeHtml {
        return this.sanitized.bypassSecurityTrustHtml(value)
      }
        getSectionList() {
        //API request
        this._httpService.get('/Section/GetSectionList').subscribe(res => {
          if (res) {
              this.sectionList = res.json();
            //sectionList is returning below HTML   
            //<div class="wrapper">
            //  <button type='button' class='btn btn-primary btn-sm'>Click Me</button>
            //</div>
          }
        })
      }
    }

Template模板

<ng-container *ngFor="let item of sectionList">
    <div [innerHTML]="sanitizeHtml(item?.sectionBody)">

    </div>
    //innerHTML after rendering showing this 
    //<div class="wrapper">
    //  <button type='button' class='btn btn-primary btn-sm'>Click Me</button>
    //</div>
</ng-container>

Short Answer, you are binding functions inside your templates, which means you have a new html content every time change detection runs, and change detection runs everytime a function is called, which means your button keeps on being updated infinitely, that's why it never works, Read more here please .简短的回答,您正在模板中绑定功能,这意味着每次更改检测运行时您都有一个新的 html 内容,并且每次调用 function 时都会运行更改检测,这意味着您的按钮会不断更新,这就是它永远不会工作的原因, 请在此处阅读更多内容

Now on how to do this, I would listen to ngDoCheck, and check if my button has a listener, if not, I will append the listener.现在关于如何做到这一点,我会听 ngDoCheck,并检查我的按钮是否有监听器,如果没有,我将 append 监听器。 I will also make sure to use on Push change detection, because if not, this will ngDoCheck will be called a lot, and maybe the button will be replaced more often, not quite sure about it.我还会确保在 Push 更改检测上使用,因为如果没有,这将 ngDoCheck 被调用很多,并且可能会更频繁地更换按钮,不太确定。 Here is how the code would look like.这是代码的样子。

html html

<!-- no more binding to a function directly --> 
<div #test [innerHTML]='sanitizedHtml'></div>

component零件

import { HttpClient } from '@angular/common/http';
import { AfterViewChecked, AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, DoCheck, ElementRef, OnDestroy, ViewChild } from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  changeDetection:  ChangeDetectionStrategy.OnPush
})
export class AppComponent implements DoCheck {
  name = 'Angular';
  people: any;
  //now we are getting the div itself, notice the #test in the html part
  @ViewChild('test')
  html!: ElementRef<HTMLDivElement>;
  //a property to hold the html content
  sanitizedHtml!: SafeHtml;
  constructor(private _http: HttpClient, private sanitized: DomSanitizer,private change: ChangeDetectorRef ) {}

  ngDoCheck(): void {
    //run with every change detection, check if the div content now has a button and attach the click event
    if (this.html != undefined) {
        let btn = this.html.nativeElement.querySelector('button');
        if (btn && btn.onclick == undefined) {
          btn.onclick = this.bindMethod.bind(this);
        }
      }
  }

  ngOnInit() {
    this.peoples();
  }

  peoples() {
    this._http.get('https://swapi.dev/api/people/1').subscribe((item: any) => {
    const people = `<div class="wrapper">
                      <p>${item['name']}</p>
                      <button type='button' class='btn btn-primary btn-sm'>Click Me</button>
                    </div>`;
    //assign the html content and notify change detection
    this.sanitizedHtml = this.sanitized.bypassSecurityTrustHtml(people);
    this.change.markForCheck();
    });
  }
  bindMethod() {
    console.log('clicked');
  }
}

I don't like the approach because of the need to listen to ngDoCheck, this can run a lot, especially if you don't use onpush change detection.我不喜欢这种方法,因为需要听 ngDoCheck,这可以运行很多,特别是如果您不使用 onpush 更改检测。 I hope this helped.我希望这会有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM