Cet article traite de la création d'un composant d'onglets (Tabs) 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 Riot, ou consultez mes articles précédents.

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/

Les onglets sont utilisés pour organiser le contenu sur différents écrans et vues, par exemple, une application média avec 3 onglets : Photos, Vidéos et Audios.

Application of a media center on mobile with three tabs

Base du Composant d'Onglets

L'objectif est de créer une application Riot avec des onglets, de changer l'onglet actif au clic, et de modifier le contenu de la page:

Active Tabs changes on click event

Tout d'abord, créez un nouveau fichier nommé c-tabs.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-tabs.riot (CSS trouvé dans la documentation BeerCSS):

class="tabs
        { props?.min ? ' min' : null }
        { props?.rightAlign ? ' right-align' : null }
        { props?.centerAlign ? ' center-align' : null }
        { props?.leftAlign ? ' left-align' : null }
    ">
         each={ (tab, index) in props.tabs } class="{ props.active === index ? 'active ' : null }{ props?.vertical ? 'vertical' : null }" onclick={ (ev) => clicked(ev, index) }>
             if={ tab?.icon }>{ tab.icon }
             if={ tab?.img } class="circle" src={ tab.img }>
            { tab.label }
        
    
    
        export default {
            clicked (e, index) {
                e.preventDefault();
                e.stopPropagation();
                this.root.value = index;
                this.root.dispatchEvent(new Event('click'));
                this.root.dispatchEvent(new Event('change'));
            }
        }

Expliquons le code :

  • Les balises et 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
    comme balise racine ou redéfinir des balises HTML natives est une mauvaise pratique, donc commencer par c- est un bon choix de nom.
  • Une liste d'onglets doit être passée en tant qu'attribut, accessible avec props.tabs. Chaque objet de la liste définira les propriétés de l'onglet : l'étiquette, une image ou une icône provenant de Google Font Icons.
  • La liste des onglets est parcourue grâce à l'expression Each de Riot appliquée sur les balises HTML , tel que : { tab.label } .
  • L'onglet actif est défini avec la propriété active, l'index de l'onglet sélectionné. Si l'index de l'onglet actuellement affiché est égal à active, la classe active est appliquée à l'onglet.
  • Si l'onglet possède une icône ou une image, il affiche l'expression de l'icône { tab.icon }, ou une image .
  • Lorsqu'un clic se produit sur l'un des onglets, l'index de l'onglet sélectionné est passé à la fonction clicked: la fonction émettra deux événements (change et click) et fournira l'index sélectionné.
  • Enfin, chargez et instanciez le composant c-tabs.riot dans une page nommée index.riot :

    style="width:800px;padding:20px;">
             active={ state.active } tabs={ state.tabs } onchange={ changed } />
             class="page padding { state.active === 0 ? 'active' : null}" if={ state.active === 0 }>
                Tab 1
            
             class="page padding { state.active === 1 ? 'active' : null}" if={ state.active === 1 }>
                Tab 2
            
             class="page padding { state.active === 2 ? 'active' : null}" if={ state.active === 2 }>
                Tab 3
            
             class="page padding { state.active === 3 ? 'active' : null}" if={ state.active === 3 }>
                Tab 4
            
        
        
            import cTabs from "./components/c-tabs.riot"
    
            export default {
                components: {
                    cTabs
                },
                state: {
                    active: 2,
                    tabs: [
                        { label: "Flights", icon: "flight" },
                        { label: "Travel", icon: "card_travel" },
                        { label: "Explore", icon: "explore" },
                        { label: "BeerCSS", img: "./favicon.png" }
                    ]
                },
                changed(ev) {
                    this.update({
                        active: ev.target.value
                    })
                }
            }

    Détails du code :

    1. Les composants sont importés avec import cTabs from "./components/c-tabs.riot"; puis chargés dans l'objet Riot components:{}.
    2. Le composant tabs est instancié avec dans le HTML.
    3. Pour stocker des données dans un composant, elles doivent être définies dans l'objet Riot state:{}. Dans notre cas, deux données sont nécessaires :
      • state.tabs : La liste des onglets avec des étiquettes, des icônes ou des images.
      • state.active : L'index de l'onglet sélectionné.
    4. Passez les états au composant Tabs en tant que props : .
    5. Lorsque quelqu'un clique sur un onglet, l'événement de changement est déclenché, et la fonction changed est exécutée : state.active obtient le nouvel index sélectionné grâce à la fonction Riot this.update({active: ev.target.value}).
    6. Lorsque l'index state.active change, la page affichée change également avec une condition IF, tel que :
      Onglet 1
      .

    Tests du Composant d'Onglets

    Il existe deux méthodes pour tester le composant d'onglets, et elles sont couvertes dans deux articles différents :

    Conclusion

    Voilà 🎉 Nous avons créé un composant d'onglets Riot en utilisant des éléments Material Design avec BeerCSS. Le code source de l'onglet est disponible sur Github : https://github.com/steevepay/riot-beercss/blob/main/components/c-tabs.riot

    N'hésitez pas à commenter si vous avez des questions ou besoin d'aide concernant RiotJS.

    Bonne journée ! Santé 🍻