web-dev-qa-db-fra.com

Un composant Plusieurs modèles en fonction de la condition

Alors voici l'affaire. J'ai un composant très bien écrit et utilisé dans beaucoup d'endroits. Maintenant, je dois utiliser le même composant, mais je souhaite qu’un modèle différent soit rendu, en fonction d’une condition. 

J'ai beaucoup essayé. 

1) Essayé d'utiliser plusieurs décorateurs de composants - pas de chance

2) Essayé plusieurs niveaux d'abstractions, où je viens de créer plus de composants - mauvaise idée

3) peut littéralement copier l'intégralité du composant, et simplement changer le sélecteur et le modèle - mauvaise idée

4) J'essayais actuellement ceci:

<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>

J'ai défini la propriété isWizard sur true/false . Maintenant, le problème est que ng-content ne s'exécute qu'une fois. Ainsi, lorsque isWizard est vrai, même si le bloc div est affiché, ng-content ne s'exécute pas (car il s'est exécuté dans le bloc ci-dessus).

5) Au lieu d'utiliser ngIf, j'ai aussi essayé ngSwitch - cela n'a pas fonctionné

Je suis désespéré maintenant. S'il vous plaît aider :)

13
Varun Joshi

Autant que je sache, cela ne peut pas être fait avec ng-content, mais vous pouvez le faire avec templates (ou ng-templates dans Angular 4+). Au lieu de transmettre le contenu directement à votre composant, placez-le simplement dans <template> comme ceci:

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

Ensuite, vous devez injecter le modèle à votre composant avec @ContentChild(TemplateRef) et le restituer autant de fois que vous le souhaitez.

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

Il y a une dernière chose, notre composant utilise ngTemplateRenderer, qui est une directive d'utilitaire simple qui rend les modèles passés par référence. Voici le code pour cette directive:

@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

Peut-être pourrions-nous essayer la solution proposée ici: angular 2 inclut les modèles html .

Je suis assez satisfait de cette solution car je me trouvais dans la même situation, par exemple en changeant de modèles en fonction de certaines valeurs et en ne finissant pas par gâcher le code avec une énorme quantité de lignes.

Je viens de décrire un peu la structure de mon projet pour plus de précisions,

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 

Cela fonctionne avec mon problème et je le recommande :)

0

Dans la version récente ci-dessus, vous pouvez utiliser *ngIf="somevar", tandis que vous pouvez transmettre la valeur "somevar" à l'aide de @input.

Exemple:

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