◆ Portail Antalaha

Bibliothèques › Alpine.js

x-on

x-on vous permet d'exécuter facilement du code en réaction à des événements du DOM.

Voici un exemple de bouton simple qui affiche une alerte lorsqu'on clique dessus.

<button x-on:click="alert('Bonjour le monde !')">Dire bonjour</button>

Remarque : x-on ne peut écouter que des événements dont le nom est en minuscules, car les attributs HTML ne sont pas sensibles à la casse. Écrire x-on:CLICK écoutera un événement nommé click. Si vous avez besoin d'écouter un événement personnalisé dont le nom est en camelCase, vous pouvez utiliser l'assistant .camel pour contourner cette limitation. Vous pouvez aussi utiliser x-bind pour attacher une directive x-on à un élément depuis du code JavaScript (où la casse est préservée).

Syntaxe abrégée

Si x-on: vous paraît trop verbeux, vous pouvez utiliser la syntaxe abrégée : @.

Voici le même composant que ci-dessus, mais avec la syntaxe abrégée :

<button @click="alert('Bonjour le monde !')">Dire bonjour</button>

Remarque : bien que cela ne figure pas dans l'extrait ci-dessus, x-on ne peut pas être utilisé si aucun élément parent ne définit x-data. → En savoir plus sur x-data

L'objet événement

Si vous souhaitez accéder à l'objet événement JavaScript natif depuis votre expression, vous pouvez utiliser la propriété magique $event d'Alpine.

<button @click="alert($event.target.getAttribute('message'))" message="Bonjour le monde">Dire bonjour</button>

De plus, Alpine passe aussi l'objet événement à toute méthode référencée sans parenthèses. Par exemple :

<button @click="handleClick">...</button>

<script>
    function handleClick(e) {
        // Vous pouvez maintenant accéder directement à l'objet événement (e)
    }
</script>

Événements clavier

Alpine facilite l'écoute des événements keydown et keyup sur des touches précises.

Voici un exemple d'écoute de la touche Enter dans un champ de saisie.

<input type="text" @keyup.enter="alert('Envoyé !')">

Vous pouvez aussi enchaîner ces modificateurs de touches pour obtenir des écouteurs plus complexes.

Voici un écouteur qui s'exécute lorsque la touche Shift est maintenue et que Enter est pressée, mais pas lorsque Enter est pressée seule.

<input type="text" @keyup.shift.enter="alert('Envoyé !')">

Vous pouvez utiliser directement comme modificateurs tous les noms de touches valides exposés par KeyboardEvent.key, en les convertissant en kebab-case.

<input type="text" @keyup.page-down="alert('Envoyé !')">

Pour référence rapide, voici la liste des touches courantes que vous pourriez vouloir écouter.

Modificateur Touche du clavier
.shift Maj (Shift)
.enter Entrée
.space Espace
.ctrl Ctrl
.cmd Cmd
.meta Cmd sur Mac, touche Windows sur Windows
.alt Alt
.up .down .left .right Flèches haut/bas/gauche/droite
.escape Échap
.tab Tabulation
.caps-lock Verrouillage majuscules
.equal Égal, =
.period Point, .
.comma Virgule, ,
.slash Barre oblique, /

Événements souris

Comme pour les événements clavier ci-dessus, Alpine permet d'utiliser certains modificateurs de touches pour gérer les événements click.

Modificateur Touche de l'événement
.shift shiftKey
.ctrl ctrlKey
.cmd metaKey
.meta metaKey
.alt altKey

Ils fonctionnent sur les événements click, auxclick, context et dblclick, ainsi que sur mouseover, mousemove, mouseenter, mouseleave, mouseout, mouseup et mousedown.

Voici un exemple de bouton dont le comportement change lorsque la touche Shift est maintenue enfoncée.

<button type="button"
    x-data="{ message: 'sélectionner' }"
    @click="message = 'sélectionné'"
    @click.shift="message = 'ajouté à la sélection'"
    @mousemove.shift="message = 'ajouter à la sélection'"
    @mouseout="message = 'sélectionner'"
    x-text="message"></button>

Remarque : les événements click normaux combinés à certains modificateurs (comme ctrl) deviennent automatiquement des événements contextmenu dans la plupart des navigateurs. De même, les événements de clic droit déclenchent un événement contextmenu, mais déclenchent aussi un événement auxclick si l'événement contextmenu est annulé.

Événements personnalisés

Les écouteurs d'événements d'Alpine sont une surcouche des écouteurs d'événements natifs du DOM. Ils peuvent donc écouter N'IMPORTE QUEL événement du DOM, y compris les événements personnalisés.

Voici un exemple de composant qui déclenche un événement DOM personnalisé et l'écoute également.

<div x-data @foo="alert('Le bouton a été cliqué !')">
    <button @click="$event.target.dispatchEvent(new CustomEvent('foo', { bubbles: true }))">...</button>
</div>

Lorsque l'on clique sur le bouton, l'écouteur @foo est appelé.

Comme l'API .dispatchEvent est verbeuse, Alpine propose un assistant $dispatch pour simplifier les choses.

Voici le même composant réécrit avec la propriété magique $dispatch.

<div x-data @foo="alert('Le bouton a été cliqué !')">
    <button @click="$dispatch('foo')">...</button>
</div>

→ En savoir plus sur $dispatch

Modificateurs

Alpine propose un certain nombre de modificateurs de directive pour personnaliser le comportement de vos écouteurs d'événements.

.prevent

.prevent équivaut à appeler .preventDefault() dans un écouteur sur l'objet événement du navigateur.

<form @submit.prevent="console.log('envoyé')" action="/foo">
    <button>Envoyer</button>
</form>

Dans l'exemple ci-dessus, grâce à .prevent, un clic sur le bouton n'enverra PAS le formulaire vers le point d'accès /foo. C'est l'écouteur d'Alpine qui s'en chargera et qui « empêchera » l'événement d'être traité plus avant.

.stop

Comme .prevent, .stop équivaut à appeler .stopPropagation() dans un écouteur sur l'objet événement du navigateur.

<div @click="console.log('Je ne serai pas affiché')">
    <button @click.stop>Cliquez-moi</button>
</div>

Dans l'exemple ci-dessus, cliquer sur le bouton N'affichera PAS le message. En effet, nous arrêtons immédiatement la propagation de l'événement et ne lui permettons pas de « remonter » jusqu'à la <div> qui porte l'écouteur @click.

.outside

.outside est un assistant pratique pour écouter un clic en dehors de l'élément auquel il est attaché. Voici un exemple simple de menu déroulant pour l'illustrer :

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

    <div x-show="open" @click.outside="open = false">
        Contenu...
    </div>
</div>

Dans l'exemple ci-dessus, après avoir affiché le contenu du menu en cliquant sur le bouton « Afficher/masquer », vous pouvez fermer le menu en cliquant n'importe où sur la page en dehors du contenu.

C'est parce que .outside écoute les clics qui ne proviennent PAS de l'élément sur lequel il est enregistré.

Remarque : il est important de noter que l'expression de .outside n'est évaluée que lorsque l'élément sur lequel elle est enregistrée est visible sur la page. Sinon, de fâcheuses situations de concurrence se produiraient : cliquer sur le bouton « Afficher/masquer » déclencherait aussi le gestionnaire @click.outside alors que l'élément n'est pas visible.

.window

Lorsque le modificateur .window est présent, Alpine enregistre l'écouteur d'événement sur l'objet racine window de la page plutôt que sur l'élément lui-même.

<div @keyup.escape.window="...">...</div>

L'extrait ci-dessus écoutera l'appui sur la touche « Échap » N'IMPORTE OÙ sur la page.

Ajouter .window aux écouteurs est extrêmement utile dans les cas où une petite partie de votre balisage s'intéresse à des événements qui se produisent sur la page entière.

.document

.document fonctionne comme .window, mais il enregistre les écouteurs sur l'objet global document au lieu de l'objet global window.

.once

En ajoutant .once à un écouteur, vous garantissez que le gestionnaire n'est appelé qu'UNE SEULE fois.

<button @click.once="console.log('Je ne serai affiché qu\'une fois')">...</button>

.debounce

Il est parfois utile de temporiser (« debounce ») un gestionnaire d'événement afin qu'il ne soit appelé qu'après une certaine période d'inactivité (250 millisecondes par défaut).

Par exemple, si vous avez un champ de recherche qui lance des requêtes réseau au fur et à mesure de la saisie, ajouter une temporisation évitera que les requêtes ne partent à chaque frappe.

<input @input.debounce="fetchResults">

Désormais, au lieu d'appeler fetchResults après chaque frappe, fetchResults ne sera appelée qu'après 250 millisecondes sans frappe.

Si vous souhaitez allonger ou raccourcir la durée de temporisation, vous pouvez le faire en faisant suivre le modificateur .debounce d'une durée, comme ceci :

<input @input.debounce.500ms="fetchResults">

Désormais, fetchResults ne sera appelée qu'après 500 millisecondes d'inactivité.

.throttle

.throttle est similaire à .debounce, sauf qu'il laisse passer un appel du gestionnaire toutes les 250 millisecondes au lieu de le différer indéfiniment.

C'est utile dans les cas où des événements peuvent être déclenchés de façon répétée et prolongée, et où .debounce ne convient pas parce que vous voulez tout de même traiter l'événement de temps en temps.

Par exemple :

<div @scroll.window.throttle="handleScroll">...</div>

L'exemple ci-dessus est un excellent cas d'usage de la limitation. Sans .throttle, la méthode handleScroll serait appelée des centaines de fois lorsque l'utilisateur fait défiler une page, ce qui peut sérieusement ralentir un site. En ajoutant .throttle, nous nous assurons que handleScroll n'est appelée que toutes les 250 millisecondes.

Remarque : anecdote amusante : cette même stratégie est utilisée sur le site de documentation d'Alpine pour mettre à jour la section actuellement mise en évidence dans la barre latérale de droite.

Comme avec .debounce, vous pouvez ajouter une durée personnalisée à votre événement limité :

<div @scroll.window.throttle.750ms="handleScroll">...</div>

Désormais, handleScroll ne sera appelée que toutes les 750 millisecondes.

.self

En ajoutant .self à un écouteur d'événement, vous garantissez que l'événement provient bien de l'élément sur lequel il est déclaré, et non d'un élément enfant.

<button @click.self="handleClick">
    Cliquez-moi

    <img src="...">
</button>

Dans l'exemple ci-dessus, nous avons une balise <img> à l'intérieur de la balise <button>. Normalement, tout clic provenant de l'intérieur de l'élément <button> (sur l'<img>, par exemple) serait capté par un écouteur @click placé sur le bouton.

Ici cependant, grâce au .self ajouté, seul un clic sur le bouton lui-même appellera handleClick. Les clics qui proviennent de l'élément <img> ne seront pas traités.

.camel

<div @custom-event.camel="handleCustomEvent">
    ...
</div>

Il peut arriver que vous vouliez écouter des événements en camelCase, tels que customEvent dans notre exemple. Comme le camelCase n'est pas pris en charge dans les attributs HTML, le modificateur .camel est nécessaire pour qu'Alpine mette le nom de l'événement en camelCase en interne.

En ajoutant .camel dans l'exemple ci-dessus, Alpine écoute désormais customEvent au lieu de custom-event.

.dot

<div @custom-event.dot="handleCustomEvent">
    ...
</div>

Comme pour le modificateur .camel, il peut arriver que vous vouliez écouter des événements dont le nom contient des points (comme custom.event). Les points dans le nom de l'événement étant réservés par Alpine, vous devez les écrire avec des tirets et ajouter le modificateur .dot.

Dans l'exemple de code ci-dessus, custom-event.dot correspond au nom d'événement custom.event.

.passive

Les navigateurs optimisent le défilement des pages pour qu'il soit rapide et fluide, même lorsque du JavaScript s'exécute sur la page. Cependant, des écouteurs tactiles et de molette mal implémentés peuvent bloquer cette optimisation et dégrader les performances du site.

Si vous écoutez des événements tactiles, il est important d'ajouter .passive à vos écouteurs pour ne pas bloquer les performances de défilement.

<div @touchstart.passive="...">...</div>

→ En savoir plus sur les écouteurs passifs

.passive.false

Dans les navigateurs modernes, les écouteurs d'événements tactiles et de molette sont passifs par défaut. Utilisez .passive.false pour rendre ces événements annulables, afin de pouvoir appeler preventDefault dessus.

<div @touchmove.passive.false="$event.preventDefault()">...</div>

.capture

Ajoutez ce modificateur si vous voulez exécuter cet écouteur pendant la phase de capture de l'événement, c'est-à-dire avant que l'événement ne remonte de l'élément cible vers le haut du DOM.

<div @click.capture="console.log('Je serai affiché en premier')">
    <button @click="console.log('Je serai affiché en second')"></button>
</div>

→ En savoir plus sur les phases de capture et de propagation (bubbling) des événements

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