◆ Portail Antalaha

Bibliothèques › Alpine.js

x-teleport

La directive x-teleport vous permet de transporter une partie de votre gabarit Alpine vers un tout autre endroit du DOM de la page.

C'est utile pour des éléments comme les fenêtres modales (surtout lorsqu'elles sont imbriquées), car cela permet de sortir du z-index du composant Alpine courant.

x-teleport

En attachant x-teleport à un élément <template>, vous indiquez à Alpine d'« ajouter » cet élément à la fin du sélecteur fourni.

Remarque : le sélecteur de x-teleport peut être n'importe quelle chaîne que vous passeriez normalement à une méthode comme document.querySelector. Alpine trouvera le premier élément correspondant, que ce soit un nom de balise (body), un nom de classe (.my-class), un identifiant (#my-id) ou tout autre sélecteur CSS valide.

→ En savoir plus sur document.querySelector

Voici un exemple de fenêtre modale volontairement simplifié :

<body>
    <div x-data="{ open: false }">
        <button @click="open = ! open">Afficher/masquer la fenêtre modale</button>

        <template x-teleport="body">
            <div x-show="open">
                Contenu de la fenêtre modale...
            </div>
        </template>
    </div>

    <div>Un autre contenu placé APRÈS le code de la fenêtre modale.</div>

    ...

</body>

Remarquez que lorsque vous affichez la fenêtre modale, son contenu réel apparaît APRÈS l'élément « Un autre contenu... ». C'est parce qu'au moment de son initialisation, Alpine voit x-teleport="body", puis ajoute et initialise cet élément à l'élément correspondant au sélecteur fourni.

Transférer les événements

Alpine fait de son mieux pour rendre l'expérience de téléportation transparente. Tout ce que vous feriez normalement dans un gabarit, vous devriez pouvoir le faire à l'intérieur d'un gabarit x-teleport. Le contenu téléporté a accès à la portée Alpine habituelle du composant ainsi qu'à d'autres fonctionnalités comme $refs, $root, etc.

Cependant, les événements natifs du DOM ne connaissent pas la notion de téléportation : si, par exemple, vous déclenchez un événement « click » depuis un élément téléporté, cet événement remontera l'arbre du DOM comme d'habitude.

Pour rendre cette expérience plus fluide, vous pouvez « transférer » les événements en enregistrant simplement des écouteurs d'événements sur l'élément <template x-teleport...> lui-même, comme ceci :

<div x-data="{ open: false }">
    <button @click="open = ! open">Afficher/masquer la fenêtre modale</button>

    <template x-teleport="body" @click="open = false">
        <div x-show="open">
            Contenu de la fenêtre modale...
            (cliquez pour fermer)
        </div>
    </template>
</div>

Remarquez que nous pouvons désormais écouter, depuis l'extérieur de l'élément <template>, les événements émis à l'intérieur de l'élément téléporté.

Alpine y parvient en recherchant les écouteurs d'événements enregistrés sur <template x-teleport...> et en empêchant ces événements de se propager au-delà de l'élément téléporté bien réel dans le DOM. Il crée ensuite une copie de l'événement et la redéclenche depuis <template x-teleport...>.

Imbrication

La téléportation est particulièrement utile si vous cherchez à imbriquer une fenêtre modale dans une autre. Alpine rend cela simple :

<div x-data="{ open: false }">
    <button @click="open = ! open">Afficher/masquer la fenêtre modale</button>

    <template x-teleport="body">
        <div x-show="open">
            Contenu de la fenêtre modale...

            <div x-data="{ open: false }">
                <button @click="open = ! open">Afficher/masquer la fenêtre modale imbriquée</button>

                <template x-teleport="body">
                    <div x-show="open">
                        Contenu de la fenêtre modale imbriquée...
                    </div>
                </template>
            </div>
        </div>
    </template>
</div>

Après avoir affiché les deux fenêtres modales, vous constaterez qu'elles sont écrites comme parent et enfant, mais qu'elles sont rendues comme des éléments frères sur la page, et non l'une à l'intérieur de l'autre.

Traduction française de la documentation officielle d'Alpine.js (licence MIT) – https://alpinejs.dev