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,
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 .
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.
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.
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);
}
}
<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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With