0

I want to create a dynamic number of html dom element buttons and have them be able to call a service when clicked. Is there any way to do that?

For example, test.component.ts:

import {ApiService } from '../services/api.service';
...
export class test implement OnInit(){
    constructor(private apiGet : ApiService) { }
    ngOnInit() {
        ...
        for (i = 0; i < x; i++) {
            var row = document.getElementById('row');
            var cell = insertCell();
            cell.innerHTML = "<button name='" + i + '" (click)=test.callService()>click me</button>";
        }
    }
    public callService() {
        //call ApiService here using buttons name
    }
}

I've been getting it to work when I put the (click) event on an html element inside test.component.html, but it hasn't been working for the dom generated buttons. Is there something I'm missing, or is there a better way to do this?

1
  • To dynamically generate elements consider using *ngFor Commented Mar 27, 2020 at 20:53

2 Answers 2

1

For dynamically created elements, event handlers have to be defined using addEventListener() method. Also you could manually trigger change detection to make sure the elements are generated in DOM. Try the following

import { Component, OnInit, ChangeDetectorRef } from '@angular/core';
import { ApiService } from '../services/api.service';
...
export class test implement OnInit {
  constructor(private apiGet: ApiService, private _cdr: ChangeDetectorRef) { }

  ngOnInit() {
    ...
    for (i = 0; i < x; i++) {
      var row = document.getElementById('row');
      var cell = insertCell();
      cell.innerHTML = "<button id='button" + i + "' name='" + i + '">click me</button>";
    }
    this.addEventListeners(x);
  }

  private addEventListeners(x) {
    this._cdr.detectChanges();    // <-- manually trigger change detection to be sure
    for (i = 0; i < x; i++) {
      const button = document.getElementById('button' + i);
      if (button) {
        button.addEventListener('click', this.callService());
      }
    }
  }

  public callService() {
      //call ApiService here using buttons name
  }
}

Also unrelated, export class test implement OnInit(){ should be replaced with export class test implement OnInit {. The parentheses are not required here.

Sign up to request clarification or add additional context in comments.

1 Comment

it doesn't seem pretty though
0

Your html using ngFor

 <div *ngFor="let button of buttons">
     <button (click)="callService(button.name)">{{button.name}}</button>
 </div>

And your component:

  buttons = [
    {
      name: 'one'
    },
    {
      name: 'two'
    }
  ];

  callService(buttonName) {
    alert(`call ApiService here using buttons name: [${buttonName}]`);
  }

Check this stackblitz.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.