typescript - ReflectiveInjector vs Injector al crear componentes dinámicos en Angular 5+
Después de migrar a Angular v.5.2.9, noté un mensaje de desaprobación:
ReflectiveInjector está en desuso: desde la v5 es lento y trae mucho código, use
Injector.createen su lugar.
Antes de Angular v5, he creado componentes dinámicos así:
ReflectiveInjector
// Old API with ReflectiveInjector
createWithReflectiveInjector() {
// Inputs need to be in the following format to be resolved properly
const resolvedInputs = ReflectiveInjector.resolve([
{ provide: "options", useValue: this.data }
]);
// Clear the template before inserting new one
this.dynamicComponentContainer.clear();
// We create an injector out of the data we want to pass down and this components injector
const injector = ReflectiveInjector.fromResolvedProviders(
resolvedInputs,
this.dynamicComponentContainer.parentInjector
);
// We create a factory out of the component we want to create
const factory = this.resolver.resolveComponentFactory(CounterWithInject);
// We create the component using the factory and the injector
const component = factory.create(injector);
// Subscribe to Output events:
component.instance.resetCounter.subscribe(() => {
this.data.count = 0;
});
// We insert the component into the dom container
this.dynamicComponentContainer.insert(component.hostView);
}
He refactorizado para la API actualizada con Injector.create():
Inyector
createWithInjector() {
const inputs = [{ provide: "options", useValue: this.data }];
// Clear the template before inserting new one
this.dynamicComponentContainer2.clear();
const injector = Injector.create({
providers: inputs,
parent: this.dynamicComponentContainer2.parentInjector
});
// We create a factory out of the component we want to create
const factory = this.resolver.resolveComponentFactory(CounterWithInput);
// Destroy the previously created component
if (this.componentRef) {
this.componentRef.destroy();
}
this.componentRef = this.dynamicComponentContainer2.createComponent(
factory, 0, injector);
// We insert the component into the dom container
this.dynamicComponentContainer2.insert(this.componentRef.hostView);
this.componentRef.instance.resetCounter.subscribe(() => {
this.data.count = 0;
});
}
Y en realidad es prácticamente el mismo fragmento de código incluso después de cambiar a la nueva API de Injector.
Mis preguntas son:
1) ¿Quizás me estoy perdiendo algo en la documentación y crear componentes dinámicos podría ser mucho más sencillo en Angular v5+?
2) Noté que en la documentación oficial se proporciona datos de entrada extendiendo la instancia de un componente, así:
let componentRef = viewContainerRef.createComponent(componentFactory);
(<AdComponent>componentRef.instance).data = adItem.data;
Y cuál es la forma preferida de proporcionar props a componentes dinámicos:
con los proveedores:
const inputs = [{ provide: "options", useValue: { count: 0} }];
const injector = Injector.create({
providers: inputs,
parent: this.dynamicComponentContainer2.parentInjector
});
y leer las props inyectadas en el componente:
...
ngOnInit() {
this.options = this.injector.get("options") || {};
}
con la extensión de la instancia:
// Define input data
this.componentRef.instance.data = { count: 0 };
y obtener el @Input() en el componente:
export class CounterWithInput implements OnInit {
@Input() data: any;
}
Demostración en vivo con enfoques: enlace