Angular Elements - Réutilisez vos composants partout

Léon Weiss .

18 avril 2026

Composants Angular Material avec des éléments angulaires, incluant des boutons et des sélecteurs, présentés dans une interface de bibliothèque de design.

Transformer un composant Angular en élément réutilisable change surtout une chose: on ne livre plus seulement une brique interne à un projet, on expose une vraie interface HTML consommable ailleurs. La passerelle Angular Elements répond précisément à ce besoin, quand on veut réutiliser une UI dans React, Vue, du JavaScript “vanilla” ou un CMS, sans imposer tout Angular au reste de la stack. Je vais aller droit au point pratique: quand cette approche a du sens, comment la mettre en place, et où se cachent les pièges qui coûtent du temps en production.

Les points à garder sous la main avant d’exposer un composant Angular ailleurs

  • Un élément web Angular est d’abord un composant Angular emballé dans une balise HTML autonome.
  • Le navigateur gère l’enregistrement via `customElements.define()`, donc l’intégration côté hôte reste standard.
  • Les propriétés d’entrée deviennent des attributs ou des propriétés consommables hors d’Angular, et les sorties deviennent des événements DOM.
  • Le bon cas d’usage, ce sont les widgets réutilisables, les micro-frontends et les design systems partagés.
  • Le piège le plus courant consiste à garder une API trop Angular-spécifique ou à réutiliser le sélecteur du composant comme nom de balise.
  • Si l’élément est consommé dans une app Angular, il faut penser au schéma `CUSTOM_ELEMENTS_SCHEMA` et au typage côté client.

Architecture de micro-frontends avec des éléments **angular** dans le navigateur, gérant des modules, des composants web et VUE.

Comprendre ce que l’on publie vraiment

Je distingue toujours deux niveaux. D’un côté, il y a le composant Angular, avec son template, son injection de dépendances, ses inputs, ses outputs et sa logique de change detection. De l’autre, il y a la balise HTML que l’on expose au monde extérieur. C’est cette balise qui devient la frontière stable, pas le composant interne lui-même.

Techniquement, on parle de custom elements, une brique du standard Web Components. Le navigateur garde un registre des éléments définis, puis instancie la classe associée quand il rencontre la balise dans le DOM. Angular s’insère dans ce mécanisme en transformant un composant en constructeur de custom element via `createCustomElement()`.

Le point important, c’est que l’élément reste utilisable comme n’importe quelle autre balise HTML une fois enregistré. Il se branche au DOM quand on l’ajoute, puis il est détruit quand on le retire. Cela paraît simple, mais c’est justement ce qui rend l’intégration propre dans des environnements hétérogènes.

En pratique, je pense cette approche comme un emballage propre autour d’un composant mature. Le code Angular reste Angular à l’intérieur; l’API publique, elle, doit ressembler à du HTML ordinaire. C’est cette séparation qui fait la valeur du modèle.

Quand cette approche vaut vraiment le coup

Je recommande ce format quand la réutilisation traverse les frontières de framework. Ce n’est pas une solution “par défaut” pour n’importe quel composant, et c’est là qu’il faut être lucide. Si tout reste dans une seule application Angular, le gain est souvent faible par rapport au coût de packaging et de maintenance.

Contexte Mon verdict Pourquoi
Widget intégré sur un site tiers Oui La balise HTML est facile à embarquer et l’hôte n’a pas besoin d’Angular.
Design system partagé entre Angular, React et Vue Oui, si l’API reste simple On mutualise l’UI sans imposer le même framework à tout le monde.
Micro-frontend avec responsabilité bien bornée Oui L’élément constitue une frontière de déploiement claire.
Application Angular unique et très homogène Pas forcément Un composant Angular classique est souvent plus simple à maintenir.
Écran très couplé au routeur, à l’état global ou à des services internes Plutôt non Le portage vers une balise autonome devient artificiel et fragile.

Le bon test, je le pose toujours ainsi: est-ce que cette UI doit vivre seule, dehors, pendant longtemps, et dans des environnements que je ne contrôle pas complètement? Si la réponse est oui, ce modèle devient pertinent. Sinon, je préfère garder le composant dans le cadre Angular classique et éviter de sur-architecturer.

Passer d’un composant Angular à une balise HTML

Le chemin minimal est assez court, mais chaque étape compte. Je pars d’un composant propre, j’explicite ses entrées et ses sorties, puis je le transforme en élément enregistré dans le navigateur. Il ne faut pas chercher à contourner le framework: il faut le laisser produire un élément standard.

Préparer le composant

Je garde le composant aussi indépendant que possible. Plus il dépend d’un état global implicite, plus il devient difficile à exporter. Un bon candidat expose une API claire et tient debout avec peu d’hypothèses externes.

import {Component, input, output} from '@angular/core';

@Component({
  selector: 'app-toast',
  standalone: true,
  template: `
    

{{ message() }}

`, }) export class ToastComponent { message = input(''); closed = output(); }

Le transformer et l’enregistrer

Ensuite, je passe par `createCustomElement()` avec un injecteur Angular, puis j’enregistre la classe obtenue avec le registre natif du navigateur. C’est là que l’élément devient réellement consommable hors d’Angular.

import {Injector} from '@angular/core';
import {createCustomElement} from '@angular/elements';
import {ToastComponent} from './toast.component';

export function registerToastElement(injector: Injector) {
  const ToastElement = createCustomElement(ToastComponent, {injector});

  if (!customElements.get('acme-toast')) {
    customElements.define('acme-toast', ToastElement);
  }
}

L’utiliser dans une page classique

Une fois la balise enregistrée, l’hôte la consomme comme du HTML ordinaire. Les attributs deviennent des entrées simples, et les événements se branchent via le DOM standard.

const toast = document.querySelector('acme-toast');

toast?.addEventListener('closed', () => {
  console.log('Toast fermé');
});

Je fais attention à un détail souvent négligé: le nom de la balise doit contenir un tiret, et je n’utilise pas le sélecteur Angular du composant comme nom de custom element. C’est une règle simple, mais elle évite des comportements bizarres et des doubles instanciations difficiles à diagnostiquer.

Concevoir une API publique qui reste lisible hors d’Angular

Le vrai travail commence quand l’élément existe. À partir de là, je dois penser en termes d’API publique, pas de mécanique Angular interne. Le consommateur doit comprendre comment l’utiliser sans lire le code source.

Attributs et propriétés

Les entrées simples se prêtent bien aux attributs HTML. Pour les données textuelles ou les états lisibles, c’est parfait. En revanche, dès qu’on manipule des objets, des tableaux ou une configuration riche, je préfère utiliser des propriétés JavaScript sur l’élément lui-même.

Angular transforme les noms d’entrées en attributs compatibles avec les conventions HTML, donc en minuscules séparées par des tirets. C’est pratique, mais il faut le prévoir dès la conception du composant pour éviter une API qui “sonne Angular” au lieu de “sonner HTML”.

Événements et nommage

Les sorties sont exposées comme des événements DOM standards. Je garde ici une règle très simple: un événement, un verbe clair, un nom stable. Si je dois passer un signal de fermeture, de validation ou de sélection, je choisis un nom qui reste compréhensible dans n’importe quel projet.

Quand je sais que l’élément sera consommé dans plusieurs environnements TypeScript, je documente les événements au même niveau que les attributs. Le but n’est pas seulement que ça marche, mais que l’intégration soit prévisible.

Lire aussi : Angular - output() vs EventEmitter: Lequel choisir en 2026?

Typage côté client

Sur un projet sérieux, je ne laisse pas le typage au hasard. Le plus propre est soit de caster l’élément avec les types fournis par Angular, soit d’enrichir `HTMLElementTagNameMap` pour que TypeScript comprenne la balise une bonne fois pour toutes. C’est un petit effort qui évite beaucoup d’erreurs à l’usage.

import {NgElement, WithProperties} from '@angular/elements';

declare global {
  interface HTMLElementTagNameMap {
    'acme-toast': NgElement & WithProperties<{ message: string }>;
  }
}

Si je dois intégrer l’élément dans une autre application Angular, j’ajoute aussi `CUSTOM_ELEMENTS_SCHEMA` là où la balise apparaît. Sans ça, Angular peut considérer le tag comme inconnu et remonter une erreur inutilement bruyante.

Les pièges qui reviennent en production

La plupart des échecs ne viennent pas d’Angular Elements lui-même, mais d’une API trop ambitieuse ou d’un mauvais découpage. J’en vois toujours quelques-uns revenir.

  • Réutiliser le sélecteur du composant comme nom de balise. C’est une mauvaise idée, parce qu’Angular peut créer deux instances pour le même nœud DOM.
  • Exposer trop de logique interne. Si l’élément dépend de services globaux non documentés, l’hôte finit par être couplé à Angular sans le vouloir.
  • Penser que l’encapsulation est totale par magie. Le passage en custom element n’efface pas les choix de styles, d’état et de projection du composant.
  • Négliger la destruction et le remontage dans le DOM. Les scénarios de démontage/réattachement peuvent révéler des problèmes de cycle de vie ou de nettoyage.
  • Oublier le coût de bundle. Un élément réutilisable doit rester rentable à charger. S’il est lourd et rarement utilisé, il faut le livrer à la demande.
  • Manquer de discipline sur les noms. Une API de balise mal nommée devient vite pénible à utiliser dans un CMS, un shell micro-frontend ou une app legacy.

Mon réflexe est simple: je traite l’élément comme un produit public. Cela veut dire moins d’entrées, moins d’effets de bord, plus de contrats explicites. Si un détail n’est pas clair dans la documentation du composant, il ne le sera pas davantage dans une intégration externe.

L’intégrer sans friction dans un front hétérogène

Le meilleur indicateur de réussite, c’est la simplicité du côté hôte. Dans une page en JavaScript brut, l’intégration doit se limiter à charger le bundle, insérer la balise et écouter les événements. Dans React ou Vue, je peux parfois ajouter une fine couche d’adaptation, mais je garde le noyau identique.

Je protège aussi l’enregistrement de l’élément, surtout quand le code peut être chargé plusieurs fois. Le test `customElements.get()` évite les collisions et les erreurs de réinitialisation. C’est un détail, mais en micro-frontend, ce détail compte.

if (!customElements.get('acme-toast')) {
  customElements.define('acme-toast', ToastElement);
}

Quand l’hôte est lui-même une application Angular, je vérifie deux choses: le schéma adapté pour que la balise soit reconnue, et les types pour que l’autocomplétion reste utile. Si j’ignore ce point, je perds une partie du bénéfice en confort de développement, alors que la promesse de départ était justement de simplifier l’intégration.

Je conseille aussi de charger l’élément au plus tard possible si son usage n’est pas immédiat. Sur un front riche, ce type de chargement paresseux fait souvent la différence entre une bonne idée technique et une bonne expérience réelle.

Le bon réflexe avant de l’adopter partout

Si je devais résumer ma position, je dirais ceci: je convertis un composant Angular en élément web quand il représente une capacité stable, utile hors du framework, et suffisamment autonome pour vivre seul. C’est souvent le cas d’un widget, d’un composant de design system, d’une boîte de dialogue ou d’un bloc marketing embarquable.

À l’inverse, si le composant reste profondément lié au routeur, à l’état global d’Angular, à une orchestration complexe ou à une logique de page très spécifique, je le laisse dans le monde Angular. Forcer le portage dans un custom element ne le rendra pas meilleur; cela le rendra juste plus difficile à maintenir.

Mon critère final est toujours le même: si je peux décrire l’élément en une phrase simple, avec quelques attributs et quelques événements, alors le passage au format web component est probablement sain. Si je dois raconter toute l’architecture du projet pour l’utiliser correctement, je n’ai pas encore la bonne frontière.

Questions fréquentes

Angular Elements permet de transformer un composant Angular en un Custom Element standard du navigateur. Cela le rend réutilisable dans n'importe quel environnement HTML, qu'il s'agisse de React, Vue, ou du JavaScript "vanilla", sans imposer Angular à l'application hôte.
Utilisez Angular Elements lorsque vous avez besoin de réutiliser un composant UI dans des applications utilisant différents frameworks, comme des widgets, des micro-frontends ou des éléments de design system partagés. Si le composant reste dans une seule application Angular, un composant classique est souvent plus simple.
Les inputs d'un composant Angular deviennent des attributs HTML ou des propriétés JavaScript sur le Custom Element. Les outputs sont exposés comme des événements DOM standards, que l'application hôte peut écouter de manière classique.
Évitez de réutiliser le sélecteur Angular comme nom de balise, de rendre l'API trop spécifique à Angular, de négliger le coût de bundle, ou de ne pas bien gérer la destruction et le remontage dans le DOM. Une API publique claire et simple est essentielle.

Évaluer l'article

Moyenne: 0.0 / 5 · 0 évaluations

Tags

angular elements angular elements utilisation créer web component angular
Autor Léon Weiss
Léon Weiss
Je m'appelle Léon Weiss et j'ai huit ans d'expérience dans le développement web, avec un accent particulier sur JavaScript, le backend, NoSQL et la sécurité. Mon parcours dans ce domaine a commencé par une curiosité insatiable pour la technologie et comment elle façonne notre quotidien. J'aime explorer les défis techniques et aider les lecteurs à comprendre des concepts souvent perçus comme complexes. J'écris principalement sur des sujets liés à la sécurité des applications web et à l'optimisation des bases de données NoSQL, en m'efforçant de rendre ces informations accessibles et pratiques. Je m'engage à fournir des contenus utiles, précis et à jour, en vérifiant mes sources et en comparant les informations pour offrir une perspective claire. Mon objectif est de simplifier des sujets ardus et de suivre les tendances actuelles, afin d'aider mes lecteurs à naviguer dans le paysage en constante évolution du développement web.

Commentaires (0)

Ajouter un commentaire