在Angular 2中使用ngForTemplate时的绑定事件 [英] Binding events when using a ngForTemplate in Angular 2

查看:56
本文介绍了在Angular 2中使用ngForTemplate时的绑定事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有这个简单的列表呈现组件:

Let's say I've got this simple list rendering component:

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>

到目前为止一切都很好.

So far so good.

下一步,我决定希望用户能够为渲染的项目提供自己的模板,因此我更改了组件

Next I decide I want the user to be able to supply his own template for the rendered items, so I change the component

@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 )时,此方法才有效.如果像我在组件的第一个版本中那样尝试绑定到click事件,Angular会引发以下异常:

This works only I don't bind any event handlers to the list items (plunker). If I try to bind to the click event, as I did in the first version of the component, Angular throws the following exception:

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

这是一个显示此内容的弹药.您可以删除点击绑定,它会起作用.

Here's a plunker showing that. You can delete the click binding and it'll work.

我该如何解决?我只希望用户能够为要通过ngFor进行迭代的下级项目指定模板,但是我需要能够将处理程序绑定到这些项目.

How do I fix this? I just want the user to be able to specify a template for a subordinate item which I'm going to iterate via ngFor, but I need to be able to bind handlers to those items.

推荐答案

项模板是在App上下文中定义的,尚不清楚如何将其附加到我的列表"组件上下文中.我有处理模板及其变量的create wrapper指令,该指令包装在div中以捕获事件.可以这样使用:

Item template is defined in App context, it is not clear how to attach it to my-list component context. I have create wrapper directive that handles template and its variables, directive is wrapped into div to capture events. It can be used like this:

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

该解决方案并不完美,但效果很好,请检查 plunkr .

The solution is not prerfect but nearly good, check plunkr.

这篇关于在Angular 2中使用ngForTemplate时的绑定事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆