typescript - componentfactoryresolver - dynamic component angular 4
Cómo colocar un componente dinámico en un contenedor (3)
Quiero crear componentes dinámicos e insertar vistas de estos componentes en un contenedor.
Creo que esto se puede lograr con ViewContainerRef .
Pero no sé, ¿podemos obtener ViewContainerRef
de cualquier componente? ¿Si es así, entonces cómo?. Soy nuevo en Angular, si hay otras buenas soluciones disponibles para manejar este escenario, por favor sugiérame.
Actualizado Creo que estoy muy cerca de la solución. A continuación está el código.
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() { }
}
Salida
<my-app>
<container>container</container><controlbox _ngcontent-lsn-3="">controlBox</controlbox>
</my-app>
Resultado Esperado
<my-app>
<container>container
<controlbox _ngcontent-lsn-3="">controlBox</controlbox>
</container>
</my-app>
Estaba buscando una solución a este problema también.
La única forma en que pude hacerlo fue usar un Component
adicional
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) {
}
}
Debería producir algo similar a esto.
<my-app>
<container>container
<sw-view-container-ref><div></div></sw-view-container-ref>
<controlbox>controlBox</controlbox>
</container>
</my-app>
No estoy seguro si mis ejemplos son claros o funcionan, puede hacer preguntas o hacer sugerencias, intentaré responder y actualizar mi ejemplo.
Hice algo así para mi aplicación. Para cargar datos en una tabla.
Para hacer eso, he creado una directiva:
directives: [TableDirective]
Y luego lo uso así:
@ViewChild(TableDirective) tableDirective:TableDirective;
ngAfterViewInit() {
setTimeout(_=>this.load());
}
load() {
this.tableDirective.loadTable(*ADirectiveToLoad*);
}
El archivo 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);
}
}
Esto cargará datos en mi tabla, depende de la Directiva que envío. Por ejemplo :
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;
}
También soy nuevo con Angular: x
Puede obtener ViewContainerRef
del componente actual por o desde un elemento en la vista del componente actual
@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);
});
}
Consulte también las pestañas dinámicas Angular 2 con componentes elegidos por el usuario.