Search code examples
htmlangularobservable

How to get an HTML element added from a dynamic array in Angular?


I have a list of items displayed in HTML from a Dynamic array as async. When I try to add a new item to the array, I want to select and get that item as an HTML element from DOM. How can I do that? When I try to get the item with a specific id, the DOM is not rendered with the item yet. I used ViewChild, but it returns undefined.

For example:

I have an array of vehicles as Dynamic Observable. I am trying to add a new item and get that item as an html element using the id. How can I do that?

  @ViewChild('span') span: HTMLElement;
  vehicles:Observable<any[]> = [
    {'name':'test1', 'id': 1},
    {'name':'test2', 'id': 2},
    {'name':'test3', 'id': 3},
  ]
  pushData() {
    this.vehicles
         .pipe(
         tap(() => vehicles.push({
      name: 'test10',
      id: 4
    })

    const element:HTMLElement = document.getElementById("4");
    console.log(element)
    
    // console.log(this.span.id===4)
  }
    <div *ngFor='let vehicle of vehicles | async'>
      <span #span id="{{vehicle.id}}">{{vehicle.name}}<br></span>       
    </div>
    <button (click)="pushData()">Push Data</button>

Solution

  • As per comment that you need the HTML element which you newly added, for that you need wait for sometime(use setTimeout) so that element is reflected to DOM.

    pushData() {
        this.vehicles
             .pipe(
             tap(() => vehicles.push({
          name: 'test10',
          id: 4
        })
    
      setTimeout(() => {
        const element:HTMLElement = document.getElementById("4");
        console.log(element)
      }, 50);
        
        // console.log(this.span.id===4)
      }
    

    Here is the code for the to get the elements based on the ViewChildren changes.

    Updated TS:

        @ViewChildren('vehicleElement') vehicleItems!: QueryList<HTMLElement>;
        
          vehicles = [
            { name: 'test1', id: 1 },
            { name: 'test2', id: 2 },
            { name: 'test3', id: 3 },
          ];
        
          ngAfterViewInit() {
            this.vehicleItems?.changes.subscribe((elements: QueryList<HTMLElement>) => {
              console.log(elements); // all elements
              console.log(elements.last); // last elements
            });
          }
    
      push() {
        this.vehicles.push({
          name: 'test10',
          id: 4,
        });
        // console.log(document.getElementById("4"))
      }
    

    HTML Template:

    <section class="row">
        <div class="col-md-1"*ngFor='let vehicle of vehicles' >
        <span #vehicleElement id="{{vehicle.id}}">{{vehicle.name}}<br></span>       
        </div>
    </section>
    
    <button (click)="push()">Push data</button>