2016-05-12 22 views
39

Voglio creare componenti dinamici e inserire viste di questi componenti in un contenitore.Come posizionare un componente dinamico in un contenitore

Penso che questo può essere raggiunto da ViewContainerRef.

Ma non lo so, possiamo ottenere ViewContainerRef di qualsiasi componente? se sì allora come? Sono nuovo in Angular, se ci sono altre buone soluzioni disponibili per gestire questo scenario, per favore suggeriscimi.

aggiornato Penso, sono quasi vicino alla soluzione. Di seguito è riportato il codice.

app.component.ts

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

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

    constructor() { } 

} 

container.component.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.component.ts

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

uscita

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

Risultato previsto

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

È segnato la domanda come risposta. In che modo hai utilizzato view child per correggere il componente figlio e renderlo rendering all'interno del nodo del modello principale? – WesW

+1

@WesW puoi riferirti [questo esempio] (http://plnkr.co/edit/cM8ipPKZPrNjIqQtPPQb?p=preview) –

+0

Grazie per un esempio semplice e chiaro @PremParihar – RobSeg

risposta

42

è possibile ottenere il ViewContainerRef del componente corrente o da un elemento nella vista del componente corrente

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

Vedi anche Angular 2 dynamic tabs with user-click chosen components

+2

c'è la possibilità di aggiungere il componente dinamico creato come figlio di viewcontainerref, come ex. come figlio di ? Invece di crearlo come un vicino nel DOM se sai cosa intendo. – NDY

+2

No, è necessario un 'ViewContainerRef' dall'interno di quel bambino per farlo. –

+3

@ GünterZöchbauer ha indicato un modo per inserire un DOM figlio in [questa altra domanda SO] (http://stackoverflow.com/questions/38093727/angular2-insert-a-dynamic-component-as-child-of-a- container-in-the-dom): sostituire '

' da '' (e avvolgere con il tag che si desidera). Penso che valga la pena di aggiungere questa informazione a questa risposta, poiché era parte della domanda iniziale. – Antoine

0

ho fatto qualcosa di simile per la mia app. Per caricare i dati in una tabella.

Per fare che ho creat una direttiva:

directives: [TableDirective] 

E poi lo uso così:

@ViewChild(TableDirective) tableDirective:TableDirective; 

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

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

Il file 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); 
} 
} 

Questo caricherà i dati nella mia tabella dipendono dalla direttiva che invio. Per Esempio:

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

Sono anche nuovo con angolare: x

+2

Grazie per il suggerimento. [DynamicComponentLoader] (https://angular.io/docs/ts/latest/api/core/index/DynamicComponentLoader-class.html) è contrassegnato come Deprecato, possiamo avere altra soluzione. –

1

ero alla ricerca di una soluzione a questo problema pure.

L'unico modo sono stato in grado di farlo accadere era quello di utilizzare un ulteriore Component

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

    } 
} 

Dovrebbe produrre qualcosa di simile a questo.

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

Non sono sicuro se i miei esempi sono chiari o di lavoro, sentitevi liberi di porre domande o dare suggerimenti, cercherò di rispondere e aggiornare il mio esempio.

+3

Non hai bisogno di 'var self = this;' quando ti attacchi con '=>' invece di 'function()' –

Problemi correlati