1
votes

Normally in Angular to show and hide things I create a variable in the component, create a mouseover-mouseout event on the element that toggles that variable, and place an ngIf on any element that I want effected by that event (display/hide).

You can't approach it like this if the template is within an ngFor though. When you hover over any of the dynamically generated elements it will trigger EVERY show/hide. Thus my question is, using Angular star directives how can I make events equally dynamic on *ngFor-dynamically-generated-template-elements so that When I hover over one of those template elements on its corresponding event is emitted? More specifically, (see stackblitz below) how do I get ONE tooltip to appear when I am hovering over its corresponding template event?

How do people get around this. Can you create dynamically generated variable names? Would this even be a scalable approach whne you have hundreds of thousands of rows? Probably not. There must be a way.

Here's my Stackblitz demonstrating what I am talking about.

Template:

<h1>Tool tip example</h1>
<p>
  Events on dynamically generated template from *ngFor :)
</p>
<p>
  Requirements: Make a tooltip appear with the rest of the information on hover.
</p>


<table>
  <tr>
    <th>id</th>
    <th>name</th>
    <th>gender</th>
  </tr>
  <tr *ngFor="let object of this.data.arrayOfObjects">
    <td (mouseenter)="tooltipHover=!tooltipHover" (mouseleave)="tooltipHover=!tooltipHover" class="id-pointer">
      {{object.friends.length}}
        <div *ngIf="this.tooltipHover" class="tooltip">
Tooltip:
more info here

  </div>
    </td>
    <td>{{object.name}}</td>
    <td>{{object.gender}}</td>


  </tr>


</table>

Component:

import { Component } from '@angular/core';
import {Data} from './../../data'

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  tooltipHover:boolean =false;

  constructor(public data: Data){}


}
2
your stackblitz not working - Chellappan வ
stackblitz working but it was not related to your question - Chellappan வ
So sorry, its updated - imnickvaughn

2 Answers

3
votes

You have single variable for entire list, that's why it is triggered for each row. Instead you should have a list of each row tooltip visibility. Check this stackblitz

I changed your html to following

 <tr *ngFor="let object of this.data.arrayOfObjects; let i = index">
    <td (mouseenter)="onMouseEnter(i)" 
      (mouseleave)="onMouseLeave(i)" class="id-pointer">
      {{object.friends.length}}
        <div *ngIf="tooltipHover[i]" class="tooltip">
          Tooltip:
          more info here
       </div>
    </td>
    <td>{{object.name}}</td>
    <td>{{object.gender}}</td>

</tr>

And your component file to this

 tooltipHover: boolean[] = [];

  constructor(public data: Data){}

  onMouseEnter(index) {
    this.tooltipHover[index] = true;
  }

  onMouseLeave(index) {
    this.tooltipHover[index] = false;
  }
2
votes

Try something like this

create empty array

tooltipHover=[]

<tr *ngFor="let object of this.data.arrayOfObjects; let i = index">
    <td (mouseenter)="tooltipHover[i]=!tooltipHover[i]" (mouseleave)="tooltipHover[i]=!tooltipHover[i]" class="id-pointer">
      {{object.friends.length}}
        <div *ngIf="this.tooltipHover[i]" class="tooltip">
Tooltip:
more info here    
  </div>
    </td>
    <td>{{object.name}}</td>
    <td>{{object.gender}}</td> 
  </tr>

Example:https://stackblitz.com/edit/angular-xbwxrw