Si está utilizando componentes creados dinámicamente en Angular, probablemente le haya resultado difícil pasar información entre los componentes principal y secundario cuando sea necesario. Debe proporcionar la información en el componente principal y luego inyectarla dentro del componente secundario. Si bien no es necesariamente difícil de hacer, genera una gran cantidad de código repetitivo adicional.
Sería mucho mejor si pudiéramos usar el decorador @Input
como estamos acostumbrados. ¿Bien adivina que? Angular admite hacer exactamente esto a partir de la versión dieciséis. En esta publicación, te mostraré cómo. Muy bien, vayamos a ello.
Primero, veamos cómo solíamos pasar datos a componentes creados dinámicamente desde el padre. Aquí, en este ejemplo, dentro de la plantilla del componente, tenemos nuestro *ngComponentOutlet
y lo pasamos a nuestro componente reproductor.
En este caso, también estamos pasando un inyector secundario personalizado, y así es como inyectaríamos los datos para el componente secundario antes.
@Component({ selector: 'app-root', template: ` <ng-container *ngComponentOutlet="playerComponent; injector: childInjector"></ng-container> ` }) export class App { protected playerComponent = PlayerComponent; }
Y para crear este inyector secundario, necesitábamos crear una propiedad para poder configurarlo y luego usarlo dentro de la plantilla.
export class App { protected childInjector?: Injector; ... }
Luego, necesitábamos inyectar el Inyector desde el núcleo angular dentro del constructor.
export class App { ... constructor(private injector: Injector) { } }
Después de eso, necesitábamos configurar el inyector secundario usando el método de creación y la matriz de proveedores para proporcionar nuestro token de jugador al niño.
export class App { ... constructor(private injector: Injector) { this.childInjector = Injector.create({ providers: [ { provide: PlayerToken, useValue: this.player } ], parent: this.injector }); } }
Y finalmente, en el componente secundario, nuestro componente reproductor, necesitábamos establecer nuestra propiedad del reproductor con el método de inyección del núcleo angular.
export class PlayerComponent { protected player?: Player = inject(PlayerToken); }
Entonces, todo esto es solo para pasar un objeto reproductor simple a un componente dinámico. Quiero decir, si este no fuera un componente dinámico, simplemente lo convertiríamos en un @Input
y simplemente vincularíamos el objeto de datos del reproductor al @Input
en el padre. Pero este es un componente creado dinámicamente, por lo que no podemos hacer esto, ¿verdad?
Bueno, a partir de Angular dieciséis, podemos usar @Input
en su lugar, y es mucho más simple de lo que hemos visto hasta ahora.
*ngComponentOutlet
Comenzamos cambiando esta propiedad del reproductor a @Input
. Y simplemente se escribe en la interfaz de nuestro reproductor.
export class PlayerComponent { @Input() player?: Player; }
Ahora podemos eliminar el método de inyección y las importaciones de tokens de jugador, ya que ya no son necesarios. Luego, volviendo a nuestro padre, en la plantilla, podemos quitar el inyector y, en su lugar, reemplazarlo con un objeto de entradas. Podemos pasar este objeto en cualquier número de entradas. Entonces, si tuviéramos cinco entradas, simplemente incluiríamos sus nombres y luego pasaríamos a cada una los datos que necesitemos.
Pero en este caso, solo tenemos una entrada en nuestro componente secundario, player, así que eso es todo lo que necesitamos para pasarlo.
@Component({ selector: 'app-root', template: ` <ng-container *ngComponentOutlet="playerComponent; inputs: { player }"></ng-container> ` })
Ahora podemos quitar el inyector infantil. Esto significa que también podemos eliminar el constructor por completo. Y finalmente, podemos eliminar el Inyector del núcleo angular y la importación del token del jugador, ya que ya no los usaremos.
export class App { protected player: Player = { name: 'LeBron James', games: 1421, points: 38652, fieldGoalPercentage: 0.505, threePointPercentage: 0.345, imageName: 'lebron-james' }; protected playerComponent = PlayerComponent; }
Y eso es. Podemos ver que todo funciona como antes. Por lo tanto, es un poco más fácil de lograr y también menos código, lo cual siempre es genial.
Sin embargo, lo malo es que, si bien los @Input
son compatibles, los @Output
no lo son. Una especie de fastidio, pero es lo que hay. Con suerte, agregarán soporte en el futuro porque esto también sería muy útil, pero tendremos que esperar y ver.
Consulte el código de demostración y los ejemplos de estas técnicas en el ejemplo de Stackblitz a continuación. Si tienes alguna pregunta o idea, no dudes en dejar un comentario.