handle custom directive with ngFor – Angular2

Yesterday I was trying to play with one of SO question and encountered problem within my solution.

in component’s template, I’m using ngFor directive within which I’m using my custom popover directive. Through directive only, I want to show hide content for each ngFor object.

Once you check http://plnkr.co/edit/X4U8ofJ5rgmE1YQ7fTAG?p=preview you will realize my problem.

on mouseenter event used within directive I want to show content of appropriate ngFor object.

directive.ts

import {Input,Component,Output,EventEmitter,Input,Directive,Hostbinding} from 'angular2/core';
import {Component, Input, OnInit, OnChanges, ChangeDetectionStrategy, ElementRef} from 'angular2/core';
@Directive({
    selector: '.tower-details',
    host:{
      '(mouseenter)':'show($event)',
      '(mouseout)':'hide()'
    }
})
export class popover{
   @Input() value: string;
   @Output() valueChange=new EventEmitter();


   ngOnChanges(...args:any[]){
     //console.log(args[0].value);
   }
   show(val)
   {
     console.log(val.target);
     this.valueChange.emit(true);
   }
   hide()
   {
     console.log('hide');
     this.valueChange.emit(false);
   }

}

app.ts

 template: `
    <div  *ngFor="#p of popovers;#index=index">
            <div class="tower-details"  [(value)]="show" style="display: block;border:1px solid green;background-color:orange" >
             Hover Me ! {{index}}
                <div *ngIf="show">
                <div class="popover top" style="display: block;border:1px solid green">
                    <h3 class="popover-title">{{p.title}}</h3>
                    <div class="popover-content">pop up content</div>
                </div>
                </div>
            </div>
            <br>
            <br>
     </div>
  `

2
Leave a Reply

avatar
2 Comment threads
0 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
1 Comment authors
Jason Recent comment authors
  Subscribe  
newest oldest most voted
Notify of
Jason
Guest

I guess you want something like @Component({ selector: 'my-app', providers: [], template: ` <div *ngFor="let p of popovers;let index=index"> <div class="tower-details" [(value)]="show[p.title]" style="display: block;border:1px solid green;background-color:orange" > Hover Me ! {{index}} <div *ngIf="show[p.title]"> <div class="popover top" style="display: block;border:1px solid green"> <h3 class="popover-title">{{p.title}}</h3> <div class="popover-content">pop up content</div> </div> </div> </div> <br> <br> </div> `, directives: [popover] }) export class App { popovers=[{"title":"popover1"},{"title":"popover2"},{"name":"title"}] show={'popover1': false, 'popover2': false, 'title': false}; } The state for each item needs to be stored separately. If you use the same value for each, they show/hide synchronous. Because you use two-way-binding on [(value)]="show" the value of each item… Read more »

Jason
Guest

In fact, the show variable you use is globally. You should use something like that: @Component({ selector: 'my-app', providers: [], template: ` <div *ngFor="#p of popovers;#index=index"> <div class="tower-details" (valueChange)="show[index]=$event" style="display: block;border:1px solid green;background-color:orange" > Hover Me ! {{index}} <div *ngIf="show[index]"> <div class="popover top" style="display: block;border:1px solid green"> <h3 class="popover-title">{{p.title}}</h3> <div class="popover-content">pop up content</div> </div> </div> </div> <br> <br> </div> {{show | json }} `, directives: [popover] }) export class App { popovers=[{"title":"popover1"},{"title":"popover2"}, {"name":"title"}] show=[false,false,false]; } See this plunkr: http://plnkr.co/edit/pIgH4OdMIf7rj2NOw9b6?p=preview. Edit After thinking again, you could leverage the state of the applied directive directly to avoid the use of a show… Read more »