paint-brush
Как использовать Angular @Input для передачи данных в динамически создаваемые компонентык@briantreese
379 чтения
379 чтения

Как использовать Angular @Input для передачи данных в динамически создаваемые компоненты

к Brian Treese4m2024/02/27
Read on Terminal Reader

Слишком долго; Читать

Angular 16 позволяет передавать данные между динамически создаваемыми компонентами от родителя к дочернему компоненту. Раньше нам приходилось предоставлять информацию в родительском компоненте, а затем внедрять ее в дочерний компонент. Теперь мы можем сделать это, используя вместо этого декоратор `@Input`.
featured image - Как использовать Angular @Input для передачи данных в динамически создаваемые компоненты
Brian Treese HackerNoon profile picture

Если вы используете динамически создаваемые компоненты в Angular, вам, вероятно, сложно передавать информацию между родительским и дочерним компонентами, когда это необходимо. Вам необходимо предоставить информацию в родительском компоненте, а затем внедрить ее в дочерний компонент. Хотя это не обязательно сложно сделать, это приводит к появлению большого количества дополнительного шаблонного кода.


Было бы намного лучше, если бы мы могли просто использовать декоратор @Input , как мы привыкли. Ну, угадайте, что? Angular поддерживает именно это, начиная с шестнадцатой версии. В этом посте я покажу вам, как это сделать. Хорошо, давайте перейдем к делу.

Передача данных старым способом с использованием Angular Injector

Во-первых, давайте посмотрим, как мы раньше передавали данные динамически создаваемым компонентам от родителя. Здесь, в этом примере, в шаблоне компонента у нас есть *ngComponentOutlet , и мы передаем его нашему компоненту проигрывателя.


В этом случае мы также передаем пользовательский дочерний инжектор, и именно так мы раньше вводили данные для дочернего компонента.

main.ts

 @Component({ selector: 'app-root', template: ` <ng-container *ngComponentOutlet="playerComponent; injector: childInjector"></ng-container> ` }) export class App { protected playerComponent = PlayerComponent; }


И чтобы создать этот дочерний инжектор, нам нужно было создать свойство, чтобы его можно было установить и затем использовать в шаблоне.


 export class App { protected childInjector?: Injector; ... }


Затем нам нужно было внедрить инжектор из ядра angular в конструктор.


 export class App { ... constructor(private injector: Injector) { } }


После этого нам нужно было установить дочерний инжектор, используя метод create и массив провайдеров, чтобы предоставить дочернему токену наш токен игрока.


 export class App { ... constructor(private injector: Injector) { this.childInjector = Injector.create({ providers: [ { provide: PlayerToken, useValue: this.player } ], parent: this.injector }); } }


И, наконец, в дочернем компоненте, нашем компоненте player, нам нужно было установить свойство player с помощью метода inject из ядра Angular.

player.comComponent.ts

 export class PlayerComponent { protected player?: Player = inject(PlayerToken); }


Итак, все это делается для того, чтобы передать простой объект игрока динамическому компоненту. Я имею в виду, что если бы это не был динамический компонент, мы бы просто сделали его @Input и просто привязали объект данных игрока к @Input в родительском элементе. Но это динамически создаваемый компонент, поэтому мы не можем этого сделать, верно?


Что ж, начиная с Angular шестнадцати, мы фактически можем использовать @Input вместо этого, и это намного проще, чем то, что мы видели до сих пор.

Передача данных по-новому с использованием объекта входов *ngComponentOutlet

Вместо этого мы начнем с изменения этого свойства player на @Input . И он просто вводится в интерфейс нашего плеера.

player.comComponent.ts

 export class PlayerComponent { @Input() player?: Player; }


Теперь мы можем удалить метод инъекции и импорт токенов игрока, поскольку они больше не нужны. Затем, вернувшись к нашему родительскому элементу, в шаблоне, мы можем удалить инжектор и вместо этого заменить его объектом ввода. Мы можем передать этот объект на любое количество входов. Итак, если бы у нас было пять входных данных, мы бы просто включили их имена, а затем передали каждому необходимые нам данные.


Но в данном случае у нашего дочернего компонента, player, есть только один ввод, так что это все, что нам нужно для его передачи.

main.ts

 @Component({ selector: 'app-root', template: ` <ng-container *ngComponentOutlet="playerComponent; inputs: { player }"></ng-container> ` })


Теперь мы можем снять дочерний инжектор. Это означает, что мы также можем вообще удалить конструктор. И, наконец, мы можем удалить инжектор из ядра Angular и импорт токенов игрока, поскольку мы их больше не используем.


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


Вот и все. Мы видим, что все работает так же, как и раньше. Таким образом, это намного проще реализовать и меньше кода, что всегда здорово.


Однако есть один облом: хотя @Input поддерживаются, @Output — нет. Какой-то облом, но это то, что есть. Надеюсь, они добавят поддержку в будущем, потому что это тоже будет очень удобно, но нам просто придется подождать и посмотреть.

Хотите увидеть это в действии?

Ознакомьтесь с демонстрационным кодом и примерами этих методов в примере Stackblitz ниже. Если у вас есть какие-либо вопросы или мысли, не стесняйтесь оставлять комментарии.