2016-04-12 2 views
2

Вчера я пытался играть с одним из вопросов SO и столкнулся с проблемой в своем решении.ручка настраиваемая директива с ngFor - Angular2

в шаблоне компонента, я использую ngFor директива, в рамках которой я использую свою собственную директиву popover. Только с помощью директивы, я хочу показать содержимое скрыть для каждого ngFor объект.

Как только вы проверите http://plnkr.co/edit/X4U8ofJ5rgmE1YQ7fTAG?p=preview, вы поймете мою проблему.

on mouseenter мероприятие, используемое в рамках директивы Я хочу показать содержание соответствующего ngFor объекта.

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

ответ

1

Я думаю, вы хотите что-то вроде

@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}; 
} 

Состояние каждого элемента должно храниться отдельно. Если вы используете одно и то же значение для каждого, они отображают/скрывают синхронно.

Поскольку вы используете двустороннюю привязку на [(value)]="show", значение каждого элемента будет размножаться до App и обратно к каждому tower-details.

Plunker example

Update

Вы можете экспортировать директиву как:

@Directive({ 
    selector: '.tower-details', 
    host:{ 
     '(mouseenter)':'show($event)', 
     '(mouseout)':'hide()' 
    }, 
    exportAs: 'tower' 
}) 
export class popover{ 

, то вы можете создать переменную шаблона для ссылки на значение в директиве

 <div class="tower-details" #tower="tower" style="display: block;border:1px solid green;background-color:orange" > 
     Hover Me ! {{index}} - {{tower.value}} 
      <div *ngIf="tower.value"> 

Вы также должны установить value в директиве, а не просто испускать событие. Фактически испускание события больше не требуется, кроме того, что вы хотите привязать для других средств.

show(val) 
    { 
    console.log(val.target); 
    this.value = true; 
    this.valueChange.emit(true); 
    } 
    hide() 
    { 
    console.log('hide'); 
    this.value = false; 
    this.valueChange.emit(false); 
    } 

Plunker example

+0

Gunter what Если у вас нет такого логического свойства, и вы все же хотите обрабатывать его только с помощью директивы. – micronyks

+0

здесь вы знаете, что у вас есть три объекта, поэтому вы придумали три объекта. Но на самом деле, что, если в массиве тысячи объектов. Вы просто не можете идти этим путем. правильно? Мне нужен динамический путь. например. используйте 'index', и если мы сможем с ним что-то сделать с помощью директивы. – micronyks

+0

Я обновил свой ответ. –

1

В самом деле, show переменная используется глобально. Вы должны использовать что-то вроде этого:

@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]; 
} 

Смотрите эту plunkr: http://plnkr.co/edit/pIgH4OdMIf7rj2NOw9b6?p=preview.

Редактировать

Подумав еще раз, вы можете использовать состояние прикладной директивы непосредственно, чтобы избежать использования show массива.

@Directive({ 
    selector: '.tower-details', 
    host:{ 
    '(mouseenter)':'show($event)', 
    '(mouseout)':'hide()' 
    }, 
    exportAs: 'popover' 
}) 
export class popover{ 
    shoudShow: false; 

    show(val) { 
    this.shoudShow = true; 
    } 

    hide() { 
    this.shoudShow = false; 
    } 
} 

И таким образом в компоненте:

@Component({ 
    selector: 'my-app', 
    template: ` 
    <div *ngFor="#p of popovers;#index=index"> 
     <div class="tower-details" #dir="popover" style="display: block;border:1px solid green;background-color:orange" > 
     Hover Me ! {{index}} 
      <div *ngIf="dir.shoudShow"> 
      <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"}] 
} 

Смотрите этот новый plunkr: http://plnkr.co/edit/4Ewx15fYgm8AgejWZmXl?p=preview.

+0

здесь вы знаете, что у вас есть три объекта, поэтому вы создали три объекта. Но на самом деле, что, если в массиве тысячи объектов. Вы просто не можете идти этим путем. правильно? Мне нужен динамический путь. например. используйте 'index', и если мы сможем с ним что-то сделать с помощью директивы. – micronyks

+0

На самом деле, массивы могут быть созданы динамически, конечно. Я подумал о другом решении ;-) Я обновил свой ответ соответственно ... –

Смежные вопросы