Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add events to elements after the DOM has been created

I am trying to figure out how I can add events to an element after it has been added to the DOM.

Right now, I have something like this:

import {Component} from 'angular2/core';

@Component({
    selector   : 'sub-child',
    template   : '<form [innerHTML]="html"></form>'
})

export class SubChildClass
{
    private html:string;
    private buttonText:string;

    constructor()
    {
        this.buttonText = 'A new button';
        this.create();
    }

    private create()
    {
        this.html = "<button (click)='new()'>" + this.buttonText + "</button>"
    }

    private new()
    {
        this.buttonText = "Text Changed";
    }
}

The part that doesn't work is this:

this.html = "<button (click)='new()'>" + this.buttonText + "</button>"

Angular 2 doesn't know what to do with (click)='new()' at this point. I am not really sure what is the right way to do this.

What I would expect is to be able to add HTML to the DOM at a later point with some corresponding events.

I haven't worked with Angular 1. But it sounds like this used to be the equivalent of $compile in Angular 1. Some other post recommend using Dynamic Content Loader for stuff like this. But that doesn't seem like the right answer for this use case. So any help or guidance is appreciated. Thanks,

like image 399
Kris Hollenbeck Avatar asked Feb 04 '16 19:02

Kris Hollenbeck


People also ask

How do you add event listeners to dynamically created elements?

To attach event handlers to the dynamically created button, we need to select the button with a class of btn and add an event listener of click . We're saying that onclick of the button, the p tag with a class of moreInfo should display block .

How do you bind a click event to dynamically created elements?

To bind the event handler to dynamically created elements, we will be using Event Delegation. On clicking the new list items, the same action is performed.


2 Answers

Updated Suggestion

import {Component} from '@angular/core';

@Component({
  selector: 'special-button-component',
  template: '<button type="button" (click)="changeText()">{{buttonText}}</button>'
})
export class SpecialButtonComponent{
  public buttonText: string = 'A New Button';
  public changeText(): void{
    this.buttonText = 'Text Changed';
  }
}

@Component({
  selector   : 'sub-child',
  template   : '<form><special-button-component></special-button-component></form>'
})
export class SubChildClass{}

Original Answer (Does not work anymore due to the removal of BrowserDomAdapter from Angular 2)

If you really want to bind to a non-template DOM element that has been injected then you can set up an event listener the good 'ol fashioned way using some rather undocumented features of Angular2

import {Component, ElementRef} from 'angular2/core';
import {BrowserDomAdapter} from 'angular2/platform/browser';

@Component({
  selector   : 'sub-child',
  template   : '<form [innerHTML]="html"></form>'
})
export class SubChildClass
{
  private html:string;
  private buttonText:string;

  constructor(private elementRef: ElementRef, private domAdapter: BrowserDomAdapter)
  {
    this.buttonText = 'A new button';
    this.create();
  }

  private create()
  {
    let button = this.domAdapter.createElement('button');
    button.innerHtml = this.buttonText;
    this.domAdapter.on(button, 'click', this.new.bind(this));
    this.domAdapter.appendChild(this.elementRef.nativeElement, button);
  }

  private new()
  {
    let button = this.domAdapter.querySelector(this.elementRef.nativeElement, 'button');
    button.innerHTML = "Text Changed";
  }
}

But what's the point... why use angular in the first place if we just drop down to this level. I also am using Angular2 in an Enterprise Application in production. And my choice for this functionality would be to create the button itself as a Component, and then use the DynamicComponentLoader to inject the element in.

like image 168
SnareChops Avatar answered Nov 05 '22 10:11

SnareChops


I use ngFor to repeat DOM. When you press click button, add item to array. Example: + Component:

export class AbcComponent {
  billingInforArr: RegisterBillingInfoModel[] = [];

  months: any[] = [];
  years: any[] = [];

  constructor(private fb: FormBuilder, private router: Router) {
    for (let i = 1; i <= 12; i++) {
      this.months.push({ value: i, text: i });
    }

    let today = new Date();
    let year = today.getFullYear();
    for (let i = 1; i <= 10; i++) {
      this.years.push({ value: year + i, text: year + i });
    }

    if (localStorage.getItem('listCard') != null) {
      this.billingInforArr = JSON.parse(localStorage.getItem('listCard'));
    }
  }
  addCard(value: any) {
    this.billingInforArr.push({ Id: Date.now().toString(), NameOnCard: value.name, CardNumber: value.cardNumber, ExpMonth: value.expMonth, ExpYear: value.expYear, Expire: `${value.expMonth}/${value.expYear}` });
    localStorage.setItem('listCard', JSON.stringify(this.billingInforArr));
  }
  removeCard(value: any) {
    console.log(value);
    console.log(this.billingInforArr);

  }
}
  • HTML:

<div class="form-group list-credit" *ngFor="let item of billingInforArr">
  <div class="content-credit">
    <i class="material-icons remove" (click)="removeCard(item.Id)">cancel</i>
  </div>
</div>
like image 42
Truc Avatar answered Nov 05 '22 11:11

Truc