Cet article traite de la création d'un composant de dialogue (Dialog) avec Riot, en utilisant le CSS Material Design BeerCSS, et de la gestion des événements de clic.
Avant de commencer, assurez-vous d'avoir une application de base RiotJS, ou consultez mes articles précédents de la série.
Je suppose que vous avez une compréhension de base de Riot ; cependant, n'hésitez pas à consulter la documentation si nécessaire : https://riot.js.org/documentation/
Le dialogue informe les utilisateurs sur une tâche spécifique et peut contenir des informations critiques, nécessiter des décisions ou impliquer plusieurs tâches. Dans un dialogue modal, l'utilisateur est interrompu et interagit avec le dialogue avant de pouvoir continuer à interagir avec le reste de l'application, par exemple en choisissant une sonnerie de téléphone:
Base du Composant de Dialogue
L'objectif est de créer une application Riot avec un dialogue et d'exécuter une action si le modal est annulé ou confirmé.
Tout d'abord, créez un nouveau fichier nommé c-dialog.riot dans le dossier des composants. Le préfixe c-
signifie "composant", une convention de nommage utile et une bonne pratique.
Écrivez le code HTML suivant dans ./components/c-dialog.riot
(le HTML a été trouvé dans la documentation BeerCSS):
<c-dialog>
<dialog class="
{props?.active ? 'active ' : null}
{props?.blur ? 'overlay blur ' : null}
{props?.left ? 'left ' : null}
{props?.right ? 'right ' : null}
{props?.top ? 'top ' : null}
{props?.bottom ? 'bottom ' : null}
{props?.max ? 'max ' : null}
"
>
<h5 if={ props?.title }>{ props?.title }</h5>
<div>
{ props?.message }
<slot name="body"></slot>
</div>
<nav class="right-align no-space">
<button onclick={ (ev) => clicked(ev, "cancel") } class="transparent link" if={ !props?.disableCancel }>{ props?.cancelText ?? "cancel" }</button>
<button onclick={ (ev) => clicked(ev, "confirm") } class="transparent link" if={ !props?.disableConfirm }>{ props?.confirmText ?? "confirm" }</button>
<slot name="button"></slot>
</nav>
</dialog>
<script>
export default {
clicked (e, name) {
e.preventDefault();
e.stopPropagation();
this.root.dispatchEvent(new Event(name));
}
}
</script>
</c-dialog>
Source Code: https://github.com/steevepay/riot-beercss/blob/main/components/c-dialog.riot
Expliquons le code :
- Les balises
<c-dialog>
et</c-dialog>
définissent une balise racine personnalisée, portant le même nom que le fichier. Vous devez l'écrire ; sinon, cela pourrait créer des résultats inattendus. Utiliser la balise<dialog></dialog>
comme balise racine ou redéfinir des balises HTML natives est une mauvaise pratique, donc commencer parc-
est un bon choix de nom. - Le dialogue comporte trois sections principales :
- Un titre en en-tête rempli grâce à
{props.title}
. - Un message dans le corps imprimé avec
{props.message}
. - Une action (call to action) avec deux boutons :
annuler
etconfirmer
.
- Un titre en en-tête rempli grâce à
- Lorsqu'un bouton est cliqué, l'événement
click
est capturé dans la fonctionclicked
, puis un événement personnalisé est émis vers le HTML parent avecthis.root.dispatchEvent(new Event(name));
: il émettra soitconfirm
soitcancel
. - Le modal s'affiche uniquement si
props.active
existe et est positif ; alors, la classeactive
est appliquée. - Le composant Dialogue a différents styles, et il est imprimé conditionnellement si leurs
props
correspondants existent, par exemple pour rendre le dialogue plein écran :{props?.max ? 'max ' : null}
si la propriété max existe, la classe max est appliquée.
Enfin, chargez et instanciez le composant c-dialog.riot dans une page principale nommée index.riot:
<index-riot>
<div style="width:800px;padding:20px;">
<c-button onclick={ (ev) => update({ active: !state.active, max: false })}>Dialog</c-button>
<c-button onclick={ (ev) => update({ active: !state.active, max: true })}>Max</c-button>
<c-dialog
title="Dialog"
message="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
active={ state.active }
oncancel={ cancel }
onconfirm={ confirm }
max={ state.max }
/>
</div>
<script>
import cButton from "../components/c-button.riot"
import cDialog from "../components/c-dialog.riot"
export default {
components: {
cDialog,
cButton
},
state: {
active: false,
left: false,
max: false
},
cancel() {
console.log("dialog cancel")
this.update({ active: false })
},
confirm() {
console.log("dialog confirm")
this.update({ active: false })
}
}
</script>
</index-riot>
Source Code: https://github.com/steevepay/riot-beercss/blob/main/examples/index.dialog.riot
Détails du code :
- Les composants sont importés avec
import cDialog from "./components/c-dialog.riot";
puis chargés dans l'objet Riotcomponents:{}
. - Le composant dialog est instancié avec
<c-dialog/>
dans le HTML. - L'état du dialogue est stocké dans l'objet Riot
state:{}
sous la propriété booléennestate.active
. La propriété est passée en tant qu'attribut, comme :<c-dialog active={ state.active }/>
. Lorsque le bouton est cliqué, il définit la propriétéactive
sur true et affiche le modal. - Le titre et le message du dialogue sont passés en tant qu'attributs.
- Si le bouton
annuler
ouconfirmer
est cliqué, il émettra deux événements personnalisés :-
oncancel
: il exécutera la fonctionthis.cancel()
, et fermera le modal. -
onconfirm
: il exécutera la fonctionthis.confirm()
, et fermera le modal.
-
- Les deux appels à l'action peuvent être liés à une fonction personnalisée : faire un appel API, ajouter un élément HTML, envoyer un email, confirmer une suppression et plus encore !
Tests du Composant de Dialogue
Il existe deux méthodes pour tester le composant de dialogue, et elles sont couvertes dans deux articles différents :
- Test avec Vitest et Riot-SSR dans un environnement Node
- Test avec Vitest dans un environnement JsDom
Conclusion
Voilà 🎉 Nous avons créé un composant de dialogue Riot en utilisant des éléments Material Design avec BeerCSS. Le code source du modal est disponible sur Github : https://github.com/steevepay/riot-beercss/blob/main/components/c-dialog.riot
Bonne journée ! Santé 🍻