2016-05-14 51 views
6

我试图创建一个使用角度2.一个非常简单的例子一个表单生成如下:NG-含量的选择变量绑定

this.fields = [{name: 'Name', type: 'text'}, {name: 'Age', type: 'number'}]; 

但我也想支持像自定义元素:

this.fields = [ 
    {name: 'Name', type: text}, 
    {name: 'Age', type: 'custom', customid: 'Ctl1'}, 
    {name: 'Whatever', type: 'custom', customid: 'Ctl2'} 
]; 
// template: 
<super-form [fields]="fields"> 
    <Ctl1><input type="number" ...><Ctl1> 
    <Ctl2><whaterver-control ...><Ctl2> 
</super-form> 

在我的表单生成组件然后我有类似:

<div *ngFor="let f of fields"> 
    <div [ngSwitch]="f.type"> 
    <span *ngSwitchWhen="'custom'">   
     <ng-content select="f.customid"></ng-content> 
    </span> 
    </div> 
</div> 

但考虑到我在这里这显然不不行。这是一个ng2限制吗?如果是这样,我想我可以硬编码说5可选内容元素,并检查他们是否指定,并没有动态选择,但这是一个黑客。

干杯

回答

4

既然你绑定到一个变量,请使用单向绑定语法,如:

<ng-content [select]="f.customid"></ng-content>

修正
ng-content是静态投影仅。它意味着快速“transcluding”。更多信息

+0

是的..试过了,选择被忽略 – gatapia

+0

@gatapia对不起,它似乎'ng-content'只用于静态投影。 [检查这个问题](https://github.com/angular/angular/issues/8563) – Abdulrahman

+0

谢谢我刚刚发现,也。修改你的答案,并将其标记为正确。 – gatapia

7

,如果你换一个<template>元素的内容你可以做到这一点已经请检查this issue

// renders the template 
// `item` is just an example how to bind properties of the host component to the content passed as template 
@Directive({ 
    selector: '[templateWrapper]' 
}) 
export class TemplateWrapper implements OnChanges { 

    private embeddedViewRef:EmbeddedViewRef<any>; 

    @Input() 
    private item:any; 

    constructor(private viewContainer:ViewContainerRef) { 
    console.log('TemplateWrapper'); 
    } 

    @Input() templateWrapper:TemplateRef<any>; 

    ngOnChanges(changes:{[key:string]:SimpleChange}) { 
    if (changes['templateWrapper']) { 
     if (this.embeddedViewRef) { 
     this.embeddedViewRef.destroy(); 
     } 
     console.log('changes', changes); 
     this.embeddedViewRef = this.viewContainer.createEmbeddedView(this.templateWrapper, {item: this.item}); 
    } 

    if (this.embeddedViewRef) { 
     console.log('context', this.embeddedViewRef.context); 
     this.embeddedViewRef.context.item = this.item; 
    } 
    } 
} 
// just some component that is used in the passed template 
@Component({ 
    selector: 'test-component', 
    styles: [':host { display: block; border: solid 2px red;}'], 
    directives: [TemplateWrapper], 
    template: ` 
<div>test-comp</div> 
<div>prop: {{prop | json}}</div> 
    ` 
}) 
export class TestComponent { 
    @Input() prop; 

    constructor() { 
    console.log('TestComponent'); 
    } 
} 
// the component the `<template>` is passed to to render it 
@Component({ 
    selector: 'some-comp', 
    directives: [TemplateWrapper], 
    template: ` 
<div>some-comp</div> 
<div *ngFor="let f of fields"> 
    <div [ngSwitch]="f.type"> 
    <span *ngSwitchCase="'custom'">   
     <template [templateWrapper]="template" [item]="f" ></template> 
    </span> 
    </div> 
</div> 
    ` 
}) 
export class SomeComponent { 

    constructor() { 
    console.log('SomeComponent'); 
    } 

    @ContentChild(TemplateRef) template; 

    fields = [ 
    {name: 'a', type: 'custom'}, 
    {name: 'b', type: 'other'}, 
    {name: 'c', type: 'custom'}]; 
} 
// the component where the `<template>` is passed to another component 
@Component({ 
    selector: 'my-app', 
    directives: [SomeComponent, TestComponent], 
    template: ` 
<some-comp> 
    <template let-item="item"> 
    <div>some content</div> 
    <div>item: {{item | json}}</div> 
    <test-component [prop]="item"></test-component> 
    </template> 
</some-comp> 
    `, 
}) 
export class App { 
    constructor() { 
    console.log('AppComponent'); 
    } 
} 

Plunker example

+0

我正在尝试,真的但我不能让这个头或尾巴。看起来你创建了一个模板(我猜可能是空的)并将其传递给测试组件。什么是测试组件,是否应该是我传递给表单构建器的“动态元素”?这是否意味着对于我可能想要注入到表单构建器的每个元素,我需要给它一个[prop]输入? – gatapia

+0

TestComponent只是我在传递给'SomeComponent'(可能是任何东西)的模板中使用的一些组件。我只是添加它来演示如何将传递的模板中的内容绑定到“SomeComponent”中的属性。希望这可以帮助。如果您还有其他问题,我今天不会再回复。这是时候睡觉了。 'prop'的东西也只是一些例子,如何从模板绑定(如前所述),您不需要为最简单的情况添加它。 –

+0

@GünterZöchbauer这仍然是使用Angular 2.4.1的正确方法吗? – Sebastian

9

我知道这是一个老问题,但是这是第一个地方之一此功能在搜索时我登陆所以我会补充我如何解决它。

ngContent仅用于静态投影,因此您不能使用它来执行任何绑定。如果您需要绑定您的计划内容,则可以使用ngTemplateOutlet和ngOutletContext。

用法示例:

<my-component> 
    <template let-item="item"> 
     <h1>{{item?.label}}</h1> - <span>{{item?.id}}</span> 
    </template> 
</my-component> 

里面MyComponent的,你可以使用ContentChild访问模板:

@ContentChild(TemplateRef) templateVariable: TemplateRef<any>; 

然后你的组件模板里,你传递给ngTemplateOutlet这样的:

<div *ngFor="let item of list"> 
    <template [ngTemplateOutlet]="templateVariable" [ngOutletContext]="{item: item}"></template> 
</div> 

ngOutletContext是可选的,但它允许您创建对象您将在模板中绑定。请注意,我在上下文对象中创建了一个属性item。这匹配我放在模板上的名称:let-item="item"

现在my-component的使用者可以传入模板以用于列表中的每个项目。

贷款: 这answer带领我在正确的方向。

+0

有没有办法将'Outlet'模板(与' let-item')在另一个组件中? - 不是直接在'my-component'内? – naomi

+0

@naomi。我不知道我是否明白你在做什么,你是在谈论html模板代码还是控制器代码?一旦你有了模板的句柄,你可以像其他变量一样传递它,所以你只需要以某种方式得到它。例如,在我的用例中,我实际上必须将模板从另一个层次传递给孩子我的组件,所以我只是将它作为输入参数传递给子组件,然后我有模板在那里使用它。 – Justin

+0

@naomi。如果您不希望您的项目模板位于标记内,则可以使用ViewChild从其他位置获取它,但我没有对其进行测试。 – Justin