2016-04-19 17 views
14

में एक ngForTemplate का उपयोग कर मान लीजिए कि मैं इस सरल सूची प्रतिपादन घटक मिल गया है दो:बाध्यकारी घटनाओं जब कोणीय 2

import {Input, Component } from 'angular2/core' 

@Component({ 
    selector: 'my-list', 
    template: ` 
     <div *ngFor='#item of items' (click)='onItemClicked(item)'> 
      {{item}} 
     </div> 
    ` 
}) 
class MyList { 
    @Input() items: string[]; 

    onItemClicked(item) { console.log('Item clicked:', item); } 
} 

मैं इस तरह इसका इस्तेमाल:

<my-list [items]='myAppsItems'></my-list> 

अब तक तो अच्छा।

अगला मैं तय मैं उपयोगकर्ता प्रदान की गई मदों के लिए अपने ही टेम्पलेट आपूर्ति करने में सक्षम होना चाहता हूँ, इसलिए मैं घटक

@Component({ 
    selector: 'my-list', 
    template: ` 
     <template ngFor [ngForOf]="items" [ngForTemplate]="userItemTemplate" (click)='onItemClicked(item)'> 
     </template> 
    ` 
}) 
class MyList { 
    @Input() items: string[]; 
    @ContentChild(TemplateRef) userItemTemplate: TemplateRef; 

    onItemClicked(item) { console.log('Item clicked:', item); } 
} 

बदल सकते हैं और इस तरह से इसका इस्तेमाल करते हैं:

<my-list [items]='items'> 
    <template #item> 
     <h1>item: {{item}}</h1> 
    </template> 
</my-list> 

यह केवल काम करता है मैं किसी भी ईवेंट हैंडलर को सूची आइटम (plunker) पर बाध्य नहीं करता हूं। अगर मैं, क्लिक करें घटना के लिए बाध्य करने के लिए के रूप में मैं घटक के पहले संस्करण में किया था की कोशिश, कोणीय फेंकता निम्न अपवाद:

"Event binding click not emitted by any directive on an embedded template" 

यहाँ एक plunker showing that है। आप क्लिक बाध्यकारी को हटा सकते हैं और यह काम करेगा।

मैं इसे कैसे ठीक करूं? मैं बस उपयोगकर्ता को एक अधीनस्थ आइटम के लिए एक टेम्पलेट निर्दिष्ट करने में सक्षम होना चाहता हूं जिसे मैं ngFor के माध्यम से पुनरावृत्त करने जा रहा हूं, लेकिन मुझे उन वस्तुओं को हैंडलर बांधने में सक्षम होना चाहिए।

+0

हम्म, यह एक अच्छा है ... ध्यान देने योग्य एक बात - आपके प्लैंक बीटा -8 दोनों का उपयोग कर रहे हैं, जो ~ 2 महीने पुराना है। नवीनतम (बीटा -15) को अपडेट करने से बग ठीक नहीं होता है, लेकिन फिर भी मैं इसे – drewmoore

उत्तर

10

आइटम टेम्पलेट ऐप संदर्भ में परिभाषित किया गया है, यह स्पष्ट नहीं है कि इसे मेरी सूची घटक संदर्भ में कैसे संलग्न किया जाए। मैंने रैपर निर्देश बनाया है जो टेम्पलेट और इसके चर को संभालता है, निर्देशों को कैप्चर करने के लिए निर्देश को div में लपेटा जाता है। यह इस तरह से इस्तेमाल किया जा सकता:

@Directive({ 
    selector: '[ngWrapper]' 
}) 
export class NgWrapper 
{ 
    @Input() 
    private item:any; 

    private _viewContainer:ViewContainerRef; 

    constructor(_viewContainer:ViewContainerRef) 
    { 
     this._viewContainer = _viewContainer; 
    } 

    @Input() 
    public set ngWrapper(templateRef:TemplateRef) 
    { 
     var embeddedViewRef = this._viewContainer.createEmbeddedView(templateRef); 
     embeddedViewRef.setLocal('item', this.item) 
    } 
} 
@Component({ 
    selector: 'my-list', 
    directives: [NgWrapper], 
    template: ` 
     <template ngFor #item [ngForOf]="items"> 
     <div (click)="onItemClicked(item)"> 
     <template [ngWrapper]="userItemTemplate" [item]="item"></template> 
     </div> 
     </template> 
    ` 
}) 
class MyList { 
    @Input() items: string[]; 
    @ContentChild(TemplateRef) userItemTemplate: TemplateRef; 
    userItemTemplate1: TemplateRef; 

    onItemClicked(item) { 
     console.log('Item click:', item); 
    } 

    ngAfterViewInit(){ 
     this.userItemTemplate; 
    } 
} 
@Component({ 
    selector: 'my-app', 
    directives: [MyList], 
    template: ` 
    <my-list [items]='items'> 
     <template #item="item"> 
      <h1>item: {{item}}</h1> 
     </template> 
    </my-list> 
    ` 
}) 
export class App { 
    items = ['this','is','a','test'] 

     onItemClicked(item) { 
     console.log('Item click:', item); 
    } 
} 

समाधान prerfect नहीं है, लेकिन लगभग अच्छा, जाँच plunkr

+0

करने का सुझाव देता हूं http: // stackoverflow देखें।हटाए गए 'सेटलोकल' (इस महान उत्तर के आधार पर 'संदर्भ' का उपयोग करने के लिए कॉम/प्रश्न/37225722/एनजी-सामग्री-चयन-बाध्य-परिवर्तनीय/3722 9 4 9 5 # 3722 9 4 9 5 –

+0

ग्रेट हालांकि यह आरसी 4 के साथ विफल रहता है, कृपया देखें अद्यतन plunkr http://plnkr.co/edit/mFdVd9aORm2ciEfSni33?p=preview –

+0

मैं कोणीय 2 फ़ाइनल जारी होने तक इस दृष्टिकोण (या समान जटिलता वाले किसी अन्य) का उपयोग करने की अनुशंसा नहीं करता। एपीआई अभी तक स्थिर नहीं है, इसलिए आपको निकट भविष्य में और अधिक समस्याएं मिल सकती हैं। – kemsky

14

अब एक सप्ताह के लिए इसका उत्तर ढूंढ रहे थे और मैं अंततः एक सुंदर सभ्य समाधान के साथ आया। NgForTemplate का उपयोग करने के बजाय मैं ngTemplateOutlet का उपयोग करने का सुझाव दूंगा।

यह पहले से ही बहुत अच्छी तरह से यहाँ वर्णित है: angular2 feeding data back to `<template>` from `[ngTemplateOutlet]`

सूची आइटम के लिए कस्टम टेम्पलेट घटक टैग के बीच रखा गया है:

<my-list> 
    <template let-item="item"> 
    Template for: <b>{{item.text}}</b> ({{item.id}}) 
    </template> 
</my-list> 

और घटक टेम्पलेट:

<ul> 
    <li *ngFor="let item of listItems" (click)="pressed(item)"> 
    <template 
     [ngTemplateOutlet]="template" 
     [ngOutletContext]="{ 
     item: item 
     }"> 
    </template> 
    </li> 
</ul> 

मैंने यहां एक उदाहरण दिया: https://plnkr.co/edit/4cf5BlVoqzZdUQASVQaC?p=preview

+0

इसके लिए धन्यवाद! मैंने अभी इस पर अपना कोड अपडेट किया है और मेरे कस्टम टेम्पलेट प्रतिपादन निर्देश से छुटकारा पा लिया है। एफवाईआई, आपके पास आपके कोड में दो '[ngOutletContext]' बाइंडिंग हैं। यह केवल काम करता है क्योंकि दूसरे को नजरअंदाज कर दिया जाता है। – Mud

+0

@Mud आप बहुत स्वागत है! मैंने देखा कि यह एक अंतरराष्ट्रीयकरण ब्राउज़र या फ़ायरफ़ॉक्स (एंड्रॉइड) में अंतर्राष्ट्रीयकरण पॉलीफिल जोड़ने के बिना काम नहीं करता है। यह अन्यथा एक त्रुटि फेंक देगा "Intl परिभाषित नहीं है"। – Bender

संबंधित मुद्दे