Architecture > Éléments Angular

Références

L'actualité

Librairie

L'information

Vue d'ensemble des éléments Angular

Les éléments Angular sont des composants conditionnés en tant qu'éléments personnalisés, une norme Web permettant de définir le nouveaux éléments HTML d'une manière indépendante de la structure.

Les éléments personnalisés sont une fonctionnalité de la plate-forme Web actuellement prise en charge par Chrome, Firefox, Opera et Safari, et disponible dans d'autres navigateurs par le biais de la fonction de remplissage multiple. Un élément personnalisé étend le code HTML en vous permettant de définir une balise dont le contenu est créé et contrôlé par du code JavaScript. Le navigateur gère un CustomElementRegistry d'éléments personnalisés définis (également appelés composants Web), qui mappe une classe JavaScript instanciable à une balise HTML.

Le package @angular/elements exporte une API createCustomElement() fournissant un pont entre l'interface de composant et la fonctionnalité de détection des modifications d'Angular et l'API DOM intégrée.

La transformation d'un composant en un élément personnalisé permet au navigateur de disposer de toute l'infrastructure Angular requise. La création d'un élément personnalisé est simple et directe. Elle connecte automatiquement votre vue définie par le composant avec la détection des modifications et la liaison des données, en mappant la fonctionnalité Angular aux équivalents HTML natifs correspondants.

Utiliser des éléments personnalisés

Les éléments personnalisés s'amorcent eux-mêmes: ils démarrent automatiquement lorsqu'ils sont ajoutés au DOM et sont automatiquement détruits lorsqu'ils sont supprimés du DOM. Une fois qu'un élément personnalisé est ajouté au DOM pour une page, il ressemble à tout autre élément HTML et se comporte de manière similaire. Il ne nécessite aucune connaissance particulière des termes Angular ou des conventions d'utilisation.

Contenu dynamique simple dans une application Angular

La transformation d'un composant en élément personnalisé permet de créer facilement un contenu HTML dynamique dans votre application Angular. Le contenu HTML que vous ajoutez directement au DOM dans une application Angular est normalement affiché sans traitement, sauf si vous définissez un composant dynamique, ajoutez votre propre code pour connecter la balise HTML aux données de votre application et participez à la détection des modifications. Avec un élément personnalisé, tout ce câblage est pris en charge automatiquement.

Applications riches en contenu

Si vous avez une application riche en contenu, des éléments personnalisés vous permettent d'offrir à vos fournisseurs de contenu des fonctionnalités Angular sophistiquées sans nécessiter de connaissances en la matière. Il peut inclure des éléments spéciaux tels ‹code-snippet› effectuant des opérations complexes. Il vous suffit d'indiquer à votre fournisseur de contenu la syntaxe de votre élément personnalisé. Ils n'ont besoin de rien savoir sur Angular, ni sur les structures de données ou l'implémentation de votre composant.

Comment ça marche

Utilisez la fonction createCustomElement() pour convertir un composant en une classe pouvant être enregistrée avec le navigateur en tant qu'élément personnalisé. Une fois que vous avez inscrit votre classe configurée dans le registre des éléments personnalisés du navigateur, vous pouvez utiliser le nouvel élément comme un élément HTML intégré au contenu que vous ajoutez directement dans le DOM :

Lorsque votre élément personnalisé est placé sur une page, le navigateur crée une instance de la classe enregistrée et l'ajoute au DOM. Le contenu est fourni par le modèle du composant, qui utilise la syntaxe du modèle Angular, et est rendu à l'aide du composant et des données DOM. Les propriétés d'entrée dans le composant correspondent aux attributs d'entrée pour l'élément.



Transformer des composants en éléments personnalisés

Angular fournit la fonction createCustomElement() permettant de convertir un composant Angular, ainsi que ses dépendances, en un élément personnalisé. La fonction collecte les propriétés observables du composant, ainsi que la fonctionnalité Angular dont le navigateur a besoin pour créer et détruire des instances, ainsi que pour détecter les modifications et y répondre.

Le processus de conversion implémente l'interface NgElementConstructor et crée une classe de constructeur configurée pour produire une instance à amorçage automatique de votre composant.

Utilisez une fonction JavaScript customElements.define() pour enregistrer le constructeur configuré et sa balise d'élément personnalisé associée avec le navigateur CustomElementRegistry. Lorsque le navigateur rencontre la balise de l'élément enregistré, il utilise le constructeur pour créer une instance d'élément personnalisé.



Cartographie

Un élément personnalisé héberge un composant Angular, fournissant un pont entre les données et la logique définie dans le composant et les API DOM standard. Les propriétés et la logique des composants sont directement mappées sur les attributs HTML et le système d'événements du navigateur.

L'API de création analyse le composant à la recherche de propriétés d'entrée et définit les attributs correspondants pour l'élément personnalisé. Il transforme les noms de propriété pour les rendre compatibles avec des éléments personnalisés, qui ne reconnaissent pas les distinctions de casse. Les noms d'attributs obtenus utilisent des minuscules séparées par des tirets. Par exemple, pour un composant @Input('myInputProp') inputProp, l'élément personnalisé correspondant définit un attribut my-input-prop.

Les sorties de composant sont distribuées sous forme d'événements HTML personnalisés, le nom de l'événement personnalisé correspondant au nom de sortie. Par exemple, pour un composant avec @Output() valueChanged = new EventEmitter(), l'élément personnalisé correspondant enverra des événements avec le nom "valueChanged" et les données émises seront stockées dans la propriété detail de l'événement. Si vous fournissez un alias, cette valeur est utilisée. Par exemple @Output('myClick') clicks = new EventEmitter‹string›();, des événements de répartition portant le nom "myClick" sont générés.

Prise en charge du navigateur pour les éléments personnalisés

La fonctionnalité Web Platform des éléments personnalisés récemment développés est actuellement prise en charge de manière native dans un certain nombre de navigateurs. Une assistance est en attente ou prévue dans d'autres navigateurs.
Navigateur Support d'éléments personnalisés
Chrome Soutenu nativement.
Opéra Soutenu nativement.
Safari Soutenu nativement.
Firefox Pris en charge nativement à partir de la version 63. Dans les versions antérieures: définissez les préférences dom.webcomponents.enabledet dom.webcomponents.customelements.enabledsur true.
Bord Travailler sur une implémentation.
Dans les navigateurs prenant en charge nativement les éléments personnalisés, la spécification exige que les développeurs utilisent les classes ES2015 pour définir les éléments personnalisés. Les développeurs peuvent souscrire à cette option en définissant la propriété target : "es2015" dans le projet tsconfig.json. Etant donné que la prise en charge de Custom Element et ES2015 peut ne pas être disponible dans tous les navigateurs, les développeurs peuvent à la place choisir d'utiliser un polyfill pour prendre en charge les anciens navigateurs et le code ES5.

Exemple: un service de pop-up

Auparavant, lorsque vous vouliez ajouter un composant à une application lors de l'exécution, vous deviez définir un composant dynamique. Le module d'application devrait répertorier votre composant dynamique sous entryComponents, de sorte que l'application ne s'attendrait pas à ce qu'elle soit présente au démarrage, puis vous devrez le charger, l'attacher à un élément du DOM et relier tous les éléments. les dépendances, la détection des modifications et la gestion des événements, comme décrit dans Dynamic Component Loader.

L'utilisation d'un élément personnalisé Angular rend le processus beaucoup plus simple et transparent, en fournissant automatiquement toute l'infrastructure et la structure. Il vous suffit de définir le type de gestion des événements que vous souhaitez.

L'exemple d'application Popup Service (illustré ci-dessous) définit un composant que vous pouvez soit charger de manière dynamique, soit convertir en un élément personnalisé.

  • popup.component.ts définit un simple élément contextuel qui affiche un message d'entrée, avec quelques animations et styles.
  • popup.service.ts crée un service injectable qui fournit deux méthodes différentes pour appeler PopupComponent; en tant que composant dynamique ou en tant qu'élément personnalisé. Notez combien de configuration supplémentaire est nécessaire pour la méthode de chargement dynamique.
  • app.module.ts ajoute le PopupComponent à la liste entryComponents du module , pour l'exclure de la compilation et éviter les avertissements ou les erreurs de démarrage.
  • app.component.ts définit le composant racine de l'application, qui utilise PopupService pour ajouter la fenêtre contextuelle au DOM lors de l'exécution. Lorsque l'application est exécutée, le constructeur du composant racine convertit PopupComponent en un élément personnalisé.

Pour comparaison, la démo montre les deux méthodes. Un bouton ajoute la fenêtre contextuelle à l'aide de la méthode de chargement dynamique et l'autre utilise l'élément personnalisé. Vous pouvez voir que le résultat est le même. seule la préparation est différente.

popup.component.ts

popup.service.ts

app.module.ts

app.component.ts


Dactylographie pour des éléments personnalisés

Les API DOM génériques, telles que document.createElement() ou document.querySelector(), renvoient un type d'élément approprié pour les arguments spécifiés. Par exemple, l'appel de document.createElement('a') retournera un HTMLAnchorElement, TypeScript sait avoir une propriété href. De la même manière document.createElement('div'), retournera HTMLDivElement, TypeScript sait qu'il n'a pas de propriété href.

Lorsqu'elles sont appelées avec des éléments inconnus, tels qu'un nom d'élément personnalisé (popup-element dans notre exemple), les méthodes renverront un type générique, tel que HTMLELement, puisque TypeScript ne peut pas déduire le type correct de l'élément renvoyé.

Les éléments personnalisés créés avec l'extension Angular NgElement (qui à son tour étend HTMLElement). De plus, ces éléments personnalisés auront une propriété pour chaque entrée du composant correspondant. Par exemple, notre popup-element aura une propriété message de type string.

Il existe quelques options si vous souhaitez obtenir les types corrects pour vos éléments personnalisés. Supposons que vous créez un élément my-dialog personnalisé basé sur le composant suivant :

Le moyen le plus simple d'obtenir des typages précis est de convertir la valeur de retour des méthodes DOM appropriées dans le type approprié. Pour cela, vous pouvez utiliser les types NgElement et WithProperties (exportés depuis @angular/elements) :

C'est un bon moyen d'obtenir rapidement les fonctionnalités TypeScript, telles que la vérification de type et la prise en charge de la saisie semi-automatique, pour votre élément personnalisé. Mais cela peut devenir fastidieux si vous en avez besoin à plusieurs endroits, car vous devez utiliser le type de résultat à chaque occurrence.

Une autre façon, qui ne nécessite la définition de chaque type d'élément personnalisé une fois, viendront grossir la HTMLELementTagNameMap, qu'il utilise pour déduire le type d'un élément retourné en fonction de son nom de la balise (pour les méthodes DOM telles que document.createElement(), document.querySelector(), etc.) :

Désormais, TypeScript peut déduire le type correct de la même manière que pour les éléments intégrés: