57 votes

Comment placer un composant dynamique dans un conteneur

Je veux créer des composants dynamiques, et d'insérer des points de vue de ces composants dans un conteneur.

Je pense que cela peut être réalisé par ViewContainerRef.

Mais je ne sais pas, peut-on obtenir ViewContainerRef d'un composant? si oui, alors comment faire?. Je suis nouveau sur Angulaire, si il y a d'autres bonnes solutions disponibles pour ce cas de figure, merci de me suggérer.

Mise à jour Je pense, je suis à peu près près de la solution. Ci-dessous est le code.

app.composante.ts

import {Component} from '@angular/core';
import {ContainerComponet} from './container.component'

@Component({
    selector: 'my-app',
    template: `
    <container> </container>
    `,
    directives: [ContainerComponet]
})
export class AppComponent {

    constructor() { }

 }

le conteneur.composante.ts

import {Component, ComponentResolver, ViewContainerRef} from '@angular/core'
import {controlBoxComponent as controlBox} from './controlBox.component';

@Component({
    selector: 'container',
    template: 'container'    
})
export class ContainerComponet {
    constructor(viewContainer: ViewContainerRef, private _cr: ComponentResolver) {

        this._cr.resolveComponent(controlBox)
            .then(cmpFactory => {
                const ctxInjector = viewContainer.injector;
                return viewContainer.createComponent(cmpFactory, 0,  ctxInjector);
            })

    }
}

controlBox.composante.ts

import {Component} from '@angular/core'
@Component({
    selector: 'controlBox',
    template: 'controlBox'
})
export class controlBoxComponent {
    constructor() { }
}

Sortie

<my-app>
    <container>container</container><controlbox _ngcontent-lsn-3="">controlBox</controlbox>
</my-app>

Résultat Attendu

<my-app>
    <container>container
    <controlbox _ngcontent-lsn-3="">controlBox</controlbox>
    </container>
</my-app>

59voto

Günter Zöchbauer Points 21340

Vous pouvez obtenir le ViewContainerRef du composant actuel par ou à partir d'un élément de la vue du composant actuel.

 @Component({
  selector: '...',
  directives: [OtherComponent, FooComponent],
  template: `
    <other-component></other-component>
    <foo-component #foo></foo-component>
    <div #div></div>`
})

export class SomeComponent {
  // `ViewContainerRef` from an element in the view
  @ViewChild(OtherComponent, {read: ViewContainerRef}) other;
  @ViewChild('foo', {read: ViewContainerRef}) foo;
  @ViewChild('div', {read: ViewContainerRef}) div;

  // `ViewContainerRef` from the component itself
  constructor(private viewContainerRef:ViewContainerRef, private componentFactoryResolver: ComponentFactoryResolver) {}

  let factory = this.componentFactoryResolver.resolveComponentFactory(ControlBox)
  this.componentRef = this.other.createComponent(factory);
  // this.componentRef = this.foo.createComponent(factory);
  // this.componentRef = this.div.createComponent(factory);
  // this.componentRef = this.viewContainerRef.createComponent(factory);
  });
}
 

Voir aussi Onglets dynamiques angulaires 2 avec les composants choisis par un clic de l'utilisateur

0voto

Sebastian Points 31

Je cherchais une solution à ce problème également.

La seule façon dont j'ai pu y arriver était d'utiliser un Component supplémentaire

 import {Component, ViewContainerRef} from '@angular/core';

@Component({
    selector: 'sw-view-container-ref',
    template: `<div></div>`
})

export class SwViewContainerRef {

    private _viewContainerRef:ViewContainerRef;

    constructor(viewContainerRef:ViewContainerRef) {
        this._viewContainerRef = viewContainerRef;
    }

    get viewContainerRef():ViewContainerRef {
        return this._viewContainerRef;
    }
}
 

container.component.ts

 import {Component, ComponentResolver, ViewContainerRef, AfterViewInit, ViewChild,Injector} from '@angular/core'
import {controlBoxComponent as controlBox} from './controlBox.component';
import {SwViewContainerRef} from "./sw-view-container-ref";

@Component({
    selector: 'container',
    template: 'container<sw-view-container-ref #swViewContainerRef></sw-view-container-ref>',
    directives: [SwViewContainerRef]
})
export class ContainerComponet implements AfterViewInit {

    @ViewChild('swViewContainerRef', SwViewContainerRef) swViewChild:SwViewContainerRef;

    ngAfterViewInit() {
        this.desiredViewContainerRef = this.swViewChild.viewContainerRef;

        var self = this;

        this._cr.resolveComponent(controlBox).then((factory) => {

            var componentRef = self.desiredViewContainerRef.createComponent(factory, null, self.injector, null);
            componentRef.changeDetectorRef.detectChanges();
            componentRef.onDestroy(()=> {
                componentRef.changeDetectorRef.detach();
            })

            return componentRef;
        });
    }

    public desiredViewContainerRef:ViewContainerRef;

    constructor(private _cr: ComponentResolver, public injector:Injector) {

    }
}
 

Cela devrait produire quelque chose de similaire à cela.

 <my-app>
<container>container
<sw-view-container-ref><div></div></sw-view-container-ref>
<controlbox>controlBox</controlbox>
</container>
</my-app>
 

Je ne sais pas si mes exemples sont clairs ou fonctionnels, n'hésitez pas à poser des questions ou à faire des suggestions, je vais essayer de répondre et de mettre à jour mon exemple.

0voto

fireaxe Points 240

J'ai fait quelque chose comme ça pour mon application. Pour charger des données dans une table.

Pour ce faire, j'ai créé une directive:

 directives: [TableDirective]
 

Et puis je l'utilise comme ça:

 @ViewChild(TableDirective) tableDirective:TableDirective;

ngAfterViewInit() {
    setTimeout(_=>this.load());
}

load() {
    this.tableDirective.loadTable(*ADirectiveToLoad*);
}
 

Le fichier TableDirective:

 import { Component, DynamicComponentLoader, ViewContainerRef } from 'angular2/core';

@Component({
    selector: "my-table",
    template: `<my-data></my-data>`
})

export class TableDirective {
    constructor(
        private dcl:DynamicComponentLoader,
        private viewContainerRef:ViewContainerRef) {
    }

public loadTable(base:any) {
    this.viewContainerRef.clear();
    this.dcl.loadNextToLocation(base, this.viewContainerRef);
}
}
 

Cela va charger les données dans mon tableau, cela dépend de la directive que j'envoie. Par exemple :

 import { Component, OnInit } from 'angular2/core';

@Component({
    selector: "my-data",
    templateUrl: "app/_includes/table/actionnaire/table.html"
})

export class ActionnaireDirective implements OnInit {
    private entity:any;

ngOnInit() {
    this.entity = ACTIONNAIRES_PORTEUR;
}
}

var ACTIONNAIRES_PORTEUR:Actionnaire[] = [
    {"id": 1, "nom": "Test", "prenom": "Testeur", "dateNaissance": "15/05/1995"}
];

export class Actionnaire {
    id:number;
    nom:string;
    prenom:string;
    dateNaissance:any;
}
 

Je suis aussi nouveau avec Angular: x

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X