web-dev-qa-db-ja.com

条件に基づく1つのコンポーネントの複数のテンプレート

だからここに契約がある。非常によく書かれ、多くの場所で使用されているコンポーネントがあります。ここで、同じコンポーネントを使用する必要がありますが、条件に基づいて異なるテンプレートをレンダリングする必要があります。

私はたくさん試しました。

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が1回しか実行されないことです。そのため、isWizardがtrueの場合、divブロックが表示されていても、ng-contentは実行されません(上記のブロックで実行されたため)。

5)ngIfを使用する代わりにngSwitchも試しました-動作しませんでした

今私は必死です。助けてください :)

15
Varun Joshi

私の知る限り、_ng-content_を使用してそれを行うことはできませんが、templates(または_ng-templates_ in 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(); 
    }
}
_
3
Slawomir Dadas

おそらく、ここで作成した解決策を試すことができます 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 

これは私の問題で動作し、これをお勧めします:)

上記の最近のバージョンでは、*ngIf="somevar"を使用して実行できますが、@inputを使用して「somevar」値を渡すことができます。

例:

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>
0
Sahil Gupta