Один компонент Несколько шаблонов на основе условия
Итак, вот сделка. У меня есть компонент, который очень хорошо написан и используется во многих местах. Теперь мне нужно использовать один и тот же компонент, но вам нужен другой шаблон для визуализации, основанный на условии.
Я много пробовал.
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 является истинным, даже если отображается div-блок, ng-контент не запускается (запустите его в указанном выше блоке).
5) Вместо использования ngIf я также попробовал ngSwitch - не работал
Теперь я в отчаянии. Пожалуйста, помогите:)
Ответы
Ответ 1
Насколько я знаю, это невозможно сделать с помощью ng-content
, но вы можете достичь этого, используя templates
(или ng-templates
в Angular 4+). Поэтому вместо передачи содержимого непосредственно вашему компоненту просто оберните его в <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();
}
}
Ответ 2
В последней версии выше можно сделать, используя * ngIf = "somevar", в то время как вы можете передать значение "somevar" с помощью @input.
Пример:
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() {
}
}
<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>