4

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 */
}
2
  • Sounds like a job for ViewChildren Commented Jan 30, 2020 at 15:55
  • have you tried adding and *ngIf="list" on the wrapper block Commented Jan 30, 2020 at 15:55

2 Answers 2

7

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.

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

Comments

0

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)))
)

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.