Click function in dynamically loaded data doesn't work


#1

I have object like this

obj = {
    id: 1,
    data: 'please click here <button (click)="someFunction()">do job</button>'
}

So, when i use *ngFor in list and print data, click event doesn’t work. I click button and nothing happens and can anyone help?


#2

Why not just generate the buttons inside of the html template?

<ion-list>
    <ion-item *ngFor="let item of items" (click)="someFunction()">
      Click here to do the job
    </ion-item>
</ion-list>

items being the array of the objects that you are using.


#3

Because buttons must be in big text like this:

obj = {
    id: 1,
    data: 'please click here <button (click)="someFunction()">do job</button>. did you click it? okey now click here <button (click)="someFunction()">another button with click</button>'
}

So do you understand what i need to achive?


#4

I kinda understand, but why keep the template data in the obj variable inside your .ts file and not directly in the .html file?

<ion-list>
    <ion-item *ngFor="let item of items">
      please click here <button (click)="someFunction()">do job</button>. did you click it? okey now click here <button (click)="someFunction()">another button with click</button>
    </ion-item>
</ion-list>

#5

because i give you small piece of my data to demonstrate what i want. I have big data with many buttons inside and because my data is big i serve it from objects.js file with providers. So is anyone here who can say why click event doesn’t work?


#6

I advised the first approach because you can only use declarative event binding in static html inside of the component templates.

For dynamicaly added elements you need to dynamicaly add event listeners to it.

export class MyPage {
  constructor(private el:ElementRef) {
  }

  subscribeToClickListeners() {
    this.el.nativeElement.querySelector('button').addEventListener('click', (event) => this.someFunction(event));
  }

  someFunction(event) {
    // some work
  }
}

Basicly add a new click event listener to each of the buttons that you intend to use in your dynamicaly added content.

Or use renderer as described in this stack overflow post.


#7

I knew this approach, but i wasn’t sure if this was right way, but as it seems there is no other way so i will use this. Thanks bro


#8

Any time I feel the urge to directly interact with the DOM in an Angular application, I ask myself very critically to find another design that doesn’t require that.


#9

I think the same, but i couldn’t find any other way to achieve it


#10

I would change the way the data is represented to something other than HTML and have the template be capable of processing whatever structured format that is. For example:

obj = {
  id: 1,
  data: [
    {flavor: 'span', contents: 'please click here'},
    {flavor: 'button', contents: 'do job', action: 'someFunction'}
  ]
}

<ng-template ngFor let-block [ngForOf]="obj.data">
<span *ngIf="block.flavor === 'span'">{{block.contents}}</span>
<button *ngIf="block.flavor === 'button'" (click)="onClick(block.action)">{{block.contents}}</button>
</ng-template>

#11

Maybe a good idea. Thanks i’ll try it