Composants angulaires avec contenu en ligne

Lorsque vous créez de nouveaux composants lors du développement sur Angular, vous vous efforcez de les créer de manière à ce qu'ils puissent être réutilisés plusieurs fois. Tout comme dans le développement de logiciels, un programmeur s'efforce de rendre son code aussi réutilisable que possible. En même temps, je veux avoir des composants flexibles mais pas trop complexes.



En règle générale, les composants doivent être aussi stupides que possible pour être plus faciles à entretenir et à tester. Mais en même temps, ils sont personnalisables et flexibles de sorte que vous pouvez les réutiliser plusieurs fois, et ne pas traiter des composants de clonage qui sont similaires visuellement et fonctionnellement, mais qui diffèrent toujours par quelque chose. Ou n'ajoutez pas un tas de paramètres aux composants, en fonction desquels activer ou désactiver tout comportement du composant, mais qui seront en fait utilisés dans 1 cas sur 100.

Créer un sous-marin, qui devrait couler jusqu'au fond de la mer bleue sans risque pour la vie de l'équipage, puis le modifier avant de voler dans le ciel bleu n'est pas une tâche facile.

Un composant angulaire est la plus petite unité d'interface utilisateur qui devrait effectuer une tâche simple et rien de plus. La création de composants pour toutes les occasions est une mauvaise pratique. Il faut donc trouver un compromis entre flexibilité et simplicité.

Supposons que vous vouliez créer un composant qui se compose d'une sorte de wrapper, à l'intérieur duquel se trouvent un en-tête et une sorte de commutateur, et du contenu sous eux. Quelque chose comme ça:



L'ensemble du composant, qui sera appelé widget, est indiqué en vert. Le commutateur d'en-tête est surligné en rouge et le contenu est surligné en bleu. Angular est un cadre incroyablement puissant; la création d'un composant similaire à celui de l'image est une tâche très triviale pour Angular.

Mais que se passe-t-il si ce composant est rendu plus flexible, par exemple, de sorte que le contenu change en fonction des paramètres du composant widget?

Vous pouvez résoudre la représentation externe du contenu en fonction du paramètre de widget, par exemple, à l'aide de la directive structurelle ngIf . Vous pouvez basculer entre différentes vues. Et s'il y a trop de soumissions, vous pouvez utiliser une autre directive structurelle ngSwitch .

Et si différentes vues répondaient différemment aux actions des utilisateurs? Ensuite, le code du composant aura également un tas d'instructions conditionnelles. Mais le code, dans lequel il existe de nombreuses instructions conditionnelles, au fil du temps, il devient difficile de maintenir, de corriger des bogues ou d'étendre les fonctionnalités ...

Vous pouvez créer un composant widget de telle manière qu'il reçoive n'importe quel contenu, mais en même temps, il jette les valeurs sélectionnées du panneau de filtre dans les composants de la zone de contenu. Et je voudrais également pouvoir transmettre des paramètres du composant parent du widget au contenu, sans affecter le composant du widget lui-même. Pour résoudre ce problème, vous pouvez utiliser la merveilleuse directive ngTemplateOutlet , qui vous permettra de «résoudre» la représentation visuelle du composant. Pour plus d'informations, vous pouvez vous référer à la documentation , bien qu'à mon avis toute sa puissance n'y soit pas montrée.

Dans ce cas, le composant widget peut être représenté comme suit:

// widget.component.ts … private widgetContentTemplate: TemplateRef<any>; //      @ContentChild(WidgetContentTemplateDirective, { read: TemplateRef }) set WidgetContentTemplate(value: TemplateRef<any>) { this.widgetContentTemplate = value; } get WidgetContentTemplate(): TemplateRef<any> { return this.widgetContentTemplate; } … 

 <!-- widget.component.html --><div class="widget__content"> <!--      ,      context.   ,     --> <ng-container *ngTemplateOutlet="WidgetContentTemplate || DefaultWidgetContentTemplate; context: { post: SelectedPost }"> </ng-container> </div> <ng-template #DefaultWidgetContentTemplate> <div>[    ]</div> </ng-template> 

La directive ngTemplateOutlet accepte un objet TemplateRef qui est lu dans le composant à l'aide de @ContentChild. Pour ce faire, vous devez créer une directive simple. Voici son code:

 // widget-content-template.directive.ts import { Directive, TemplateRef } from '@angular/core'; @Directive({ selector: '[appWidgetContentTemplate]' }) export class WidgetContentTemplateDirective { get Template(): TemplateRef<any> { return this.template; } constructor(private readonly template: TemplateRef<any>) {} } 

Les paramètres du commutateur de widget peuvent être transmis au contenu à l'aide de l'objet contextuel. Pour que les paramètres du contexte soient correctement lus par le composant, il est nécessaire dans le composant parent, dans notre cas c'est AppComponent, n'oubliez pas de les décrire comme suit:

 <!-- app.component.html --> <app-widget-component Title="  (  )"> <!-- let-post="post" ,         --> <ng-template appWidgetContentTemplate let-post="post"> <app-post-view [Post]="post"></app-post-view> </ng-template> </app-widget-component> <br> <br> <app-widget-component Title="  (  )"> <!--  let-post="post"     ,  ShowPostInfo  AppComponent --> <ng-template appWidgetContentTemplate let-post="post"> <app-post-view [Post]="post" [ShowPostInfo]="ShowPostInfo"></app-post-view> </ng-template> </app-widget-component> 

Ainsi, nous avons un composant widget qui accepte et affiche n'importe quel contenu, tandis que le composant widget lui-même n'a rien à savoir sur le contenu. Il transmet simplement les options de commutation. Les lire ou non est une question de contenu.



La version complète du code peut être consultée ici .

Source: https://habr.com/ru/post/fr478886/


All Articles