midstack
midstack

Reputation: 2123

How can I select a html element which loaded dynamically in Angular?

I want to select a specific html element that created dynamically. But "list" variable which create the html blocks is filling with http request and dom not loaded immediately. I want to select the element via id that got from url and equal to list item's id. So selected element is undefined even if I select the element in ngAfterViewInit hook. How can I select?

HTML

<div id="wrapper">
    <ng-container *ngFor="let item of list">
        <div [id]="item.id">{{item.content}}</div>
    </ng-container>
</div>

TS

list = null;
selectedItemId = null;

ngOnInit() {
    this.selectedItemId = this.activatedRoute.snapshot.params.id;
}

getList() {
    this.http.get('http://api.example.com').subscribe(
        result => this.list = result
    )
}

ngAfterViewInit() {
    const htmlElement= document.getElementById(this.selectedItemId);

    /* Some codes that using htmlElement variable */
}

Upvotes: 4

Views: 5341

Answers (2)

Martin Parenteau
Martin Parenteau

Reputation: 73751

If you refer to the HTML elements with @ViewChildren, you can subscribe to the QueryList.changes event to be notified when the elements appear in the DOM.

In the template, set a template reference variable on the item elements:

<div id="wrapper">
  <ng-container *ngFor="let item of list">
    <div #itemElement [id]="item.id">{{item.content}}</div>
  </ng-container>
</div>

In the code, use that variable name to refer to the elements with ViewChildren:

@ViewChildren("itemElement") private itemElements: QueryList<ElementRef>;

ngAfterViewInit() {
  this.itemElements.changes.subscribe(() => {
    console.log("Item elements are now in the DOM!", this.itemElements.length);
    const htmlElement = document.getElementById(this.selectedItemId);
    ...
  });
}

See this stackblitz for a demo. Please note that the ng-container is not necessary if it contains only one div element. You can apply the *ngFor directive directly to that element.

Upvotes: 7

Petr Averyanov
Petr Averyanov

Reputation: 9486

you can use setTimeout (After http request finishes, your code is executed, then you left zone and Angular run check and add elements, after timeout is executed):

this.http.get('http://api.example.com').subscribe(
    result => this.list = result;
    setTimeout(() => console.log(document.getElementById(this.selectedItemId)))
)

Upvotes: 0

Related Questions