基于条件的一个组件多个模板

时间:2016-06-04 20:30:45

标签: angular angular2-template angular2-directives

所以这是交易。我有一个非常好的组件,并在很多地方使用。现在我需要使用相同的组件,但希望根据条件呈现不同的模板。

我尝试了很多。

1)尝试使用多个组件装饰器 - 没有运气

2)尝试了多层次的抽象,我最终创造了更多的组件 - 糟糕的主意

3)可以逐字复制整个组件,只需更改选择器和模板 - 坏主意

4)目前我正在尝试这个:

<div *ngIf="!isWizard">
    <ul class="nav" role="tablist">
        <ng-content select="tab-link"></ng-content>
    </ul>
    <ng-content select="tab-content"></ng-content>
</div>


<div *ngIf="isWizard">
    <nav class="nav-panel sidenav">
        <ng-content select=".wizard-title"></ng-content>
            <ul class="nav" role="tablist">
                <ng-content select="tab-link"></ng-content>
            </ul>

    </nav>

    <main class="settings-panel content-area">
        <ng-content select="tab-content"></ng-content>
    </main>

</div>

我将isWizard属性设置为true / false。 现在的问题是,ng-content只运行一次。因此,当isWizard为true时,即使显示div块,ng-content也不会运行(导致它在上面的块中运行)。

5)而不是使用ngIf我也试过ngSwitch - 没有工作

我现在很绝望。请帮助:)

3 个答案:

答案 0 :(得分:3)

据我所知,使用ng-content无法完成此操作,但您可以使用templates(或Angular 4+中的ng-templates)来实现此目的。因此,不要将内容直接传递给您的组件,而是将其包装在<template>中,如下所示:

<my-component [isWizard]="true">
    <template>Hello World!</template>
</my-component>

然后,您需要使用@ContentChild(TemplateRef)将模板注入到组件中,并根据需要多次渲染。

@Component({
  selector: "my-component",
  template: `
    <div *ngIf="!isWizard">
      first: <template [ngTemplateRenderer]="template"></template>
    </div>
    <div *ngIf="isWizard">
      second: <template [ngTemplateRenderer]="template"></template>
    </div>`
})
export class MyComponent {

  @ContentChild(TemplateRef)
  private template: TemplateRef<any>;

  @Input("isWizard")
  private isWizard: boolean;
}

最后一件事,我们的组件使用ngTemplateRenderer这是一个简单的实用程序指令,它通过引用呈现模板。这是该指令的代码:

@Directive({ selector: '[ngTemplateRenderer]'})
export class TemplateRenderer implements OnInit, OnDestroy {

    @Input("ngTemplateRenderer")
    private template: TemplateRef<any>;

    private view: EmbeddedViewRef<any>;

    constructor(private container: ViewContainerRef) {}

    ngOnInit(): void {
      this.view = this.container.createEmbeddedView(this.template);
    }

    ngOnDestroy(): void {
      this.view.destroy(); 
    }
}

答案 1 :(得分:0)

在上面的最新版本可以使用*ngIf="somevar"完成,而你可以通过&#34; somevar&#34;价值使用@input

示例:

&#13;
&#13;
import { Component, OnInit, Input, Output, EventEmitter} from '@angular/core';
import {SearchPipe} from './../filters/search.pipe';

@Component({
  selector: 'itra-filter',
  templateUrl: 'filter.component.html',
  styleUrls: ['filter.component.scss'],
  inputs:['IsCheckboxEnabled','IsRadioboxEnabled'],
  outputs: ['itemClicked']
})
export class ItraFilterComponent {
	// Default Value
	public IsCheckboxEnabled:boolean = false;
	public IsRadioboxEnabled:boolean = false;

	constructor() {		
	}

	ngOnInit() {
		
	}
}
&#13;
<span class="checkbox-control" *ngIf="IsCheckboxEnabled">
        <i class="icon icon_Check-box_filled"   *ngIf="y.checked"></i>
				<i class="icon icon_Check-box" *ngIf="!y.checked">        </i>
</span>
      
<span class="radiobox-control" *ngIf="IsRadioboxEnabled">
				<i class="icon icon_Radio-button-filled" *ngIf="y.checked"></i>
				<i class="icon icon_Radio-button" *ngIf="!y.checked"></i>
</span>
&#13;
&#13;
&#13;

答案 2 :(得分:0)

也许,我们可以尝试这里提出的解决方案,angular 2 include html templates

我对这个解决方案非常满意,因为我处于相同的情况,比如根据某些值切换模板,最终不会用大量的行来搞乱代码。

我只是简单地描述了我项目的结构,

Component Structure
====================
Comp A
 -> Comp a1
 -> Comp a2 
 -> Comp a3 
 -> Comp a-consolidated*(declaring all needed component's selectors) 
Comp B 
Comp C 
Comp D 

这适用于我的问题,我建议:)