0
votes

While I'm inside the ngFor directive, how is it possible to access the specific ngFor item via ElementRef? To make it clear:

<div>
  <div class="color"></div>
  <ul>
    <li *ngFor="let item of numberList">
      <div class="innercolor" #innercolor></div>
      <p (click) = "onItemClick()" >{{item}}</p>
    </li>
  </ul>
</div>

In this code, #innercolor reference is not specific for any ngFor item so this is where the trouble begins. I've searched this, there's a solution with using QueryList in controller file, but i think this is too costy for handling a simple click event, querying all the list and iterating over and over again!

It would be great to give unique elementref to the elements of ngFor. Is there a way to make it? Or is there any other solution? I'm attaching the StackBlitz code below:

StackBlitz

I think this example is easily understandable. I would like to change the color of specific clicked list item but it only changes the first. When I click on second or third, I would like to change second or third's line color, but instead they all change the first line's color. Again, there's a solution with QueryList but I don't want to query all the list elements and pass the index to the controller, then iterate over query elements!

Any help would be great.

2

2 Answers

1
votes

I would simply use an index and save the selected index on click. Then add a class to the selected element with ngClass

<div>
    <div class="color"></div>
    <ul>
        <li *ngFor="let item of items; let i=index">
            <div [ngClass]="{'selected': i === selectedIndex}" ></div>
            <p (click)="onItemClick(i)">{{item}}</p>
        </li>   
    </ul>
</div>
1
votes

You can make use of ViewChildren in this scenario

If you use *ngFor, then it will create multiple templates with the same template variable #innercolor. So if we use ViewChild we will just get the first occurrence of it. If you use ViewChildren we can get all occurrences of #innercolor.

app.component.html

<div>
  <div class="color"></div>
  <ul>
    <li *ngFor="let item of numberList; let index = index;" >
      <div class="innercolor" #innercolor></div>
      <p (click) = "onItemClick(index)" >{{item}}</p>
    </li>
  </ul>
</div>

app.component.ts

@ViewChildren("innercolor") innercolor: QueryList<ElementRef>;

  onItemClick(elementIndex: number) {
    const element = this.innercolor.find(
      (element, index) => index === elementIndex
    );
    element.nativeElement.style.backgroundColor = "yellow";
  }

Here is the Stackblitz demo url.