Se você estiver usando componentes criados dinamicamente no Angular, provavelmente terá dificuldade em passar informações entre os componentes pai e filho quando necessário. Você precisa fornecer as informações no pai e, em seguida, injetá-las no componente filho. Embora não seja necessariamente difícil de fazer, resulta em muito código clichê extra.
Seria muito melhor se pudéssemos usar o decorador @Input
como estamos acostumados. Bem, adivinhe? Angular suporta fazer exatamente isso a partir da versão dezesseis. Neste post vou te mostrar como. Tudo bem, vamos lá.
Primeiro, vamos ver como costumávamos passar dados para componentes criados dinamicamente a partir do pai. Aqui, neste exemplo, dentro do modelo de componente, temos nosso *ngComponentOutlet
e o estamos passando para nosso componente player.
Nesse caso, também estamos passando um injetor filho personalizado e é assim que injetaríamos os dados do componente filho antes.
@Component({ selector: 'app-root', template: ` <ng-container *ngComponentOutlet="playerComponent; injector: childInjector"></ng-container> ` }) export class App { protected playerComponent = PlayerComponent; }
E para criar esse injetor filho, precisávamos criar uma propriedade para que pudesse ser configurada e usada dentro do template.
export class App { protected childInjector?: Injector; ... }
Então, precisávamos injetar o Injector do núcleo angular dentro do construtor.
export class App { ... constructor(private injector: Injector) { } }
Depois disso, precisávamos definir o injetor filho usando o método create e o array de provedores para fornecer nosso token de jogador ao filho.
export class App { ... constructor(private injector: Injector) { this.childInjector = Injector.create({ providers: [ { provide: PlayerToken, useValue: this.player } ], parent: this.injector }); } }
E finalmente, no componente filho, nosso componente player, precisávamos definir nossa propriedade player com o método inject do núcleo angular.
export class PlayerComponent { protected player?: Player = inject(PlayerToken); }
Então, tudo isso é apenas para passar um objeto de jogador simples para um componente dinâmico. Quero dizer, se este não fosse um componente dinâmico, simplesmente tornaríamos isso um @Input
e vincularíamos o objeto de dados do jogador ao @Input
no pai. Mas este é um componente criado dinamicamente, então não podemos fazer isso, certo?
Bem, a partir do Angular dezesseis, podemos usar @Input
s, e é muito mais simples do que vimos até agora.
*ngComponentOutlet
Inputs Começamos alterando esta propriedade do player para @Input
. E é simplesmente digitado na interface do player.
export class PlayerComponent { @Input() player?: Player; }
Agora, podemos remover o método inject e as importações de tokens de jogadores, pois eles não são mais necessários. Então, de volta ao nosso pai, no modelo, podemos remover o injetor e, em vez disso, substituí-lo por um objeto de entrada. Podemos passar este objeto em qualquer número de entradas. Então, se tivéssemos cinco entradas, apenas incluiríamos seus nomes e passaríamos a cada uma os dados necessários.
Mas neste caso, temos apenas uma entrada em nosso componente filho, player, então isso é tudo que precisamos para passá-lo.
@Component({ selector: 'app-root', template: ` <ng-container *ngComponentOutlet="playerComponent; inputs: { player }"></ng-container> ` })
Agora podemos remover o injetor infantil. Isso significa que também podemos remover completamente o construtor. E finalmente, podemos remover o Injector do núcleo angular e a importação do token do jogador, já que não os estamos mais usando.
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; }
E é isso. Podemos ver que tudo funciona como antes. Então, é um pouco mais fácil de executar e menos código também, o que é sempre ótimo.
Uma chatice é que, embora @Input
s sejam suportados, @Output
s não são. Meio chato, mas é o que é. Esperançosamente, eles adicionarão suporte no futuro porque isso também seria muito útil, mas teremos que esperar para ver.
Confira o código de demonstração e exemplos dessas técnicas no exemplo Stackblitz abaixo. Se você tiver alguma dúvida ou opinião, não hesite em deixar um comentário.