Publié le : 14/08/24
Modifié le : 26/01/25 à 12h18

emoji_objects

Ce document est une ressource informative, mais il est sage de consulter différentes sources pour confirmer les informations fournies, car des erreurs peuvent toujours se glisser. Documentation officielle : link

Généralités


Vue.js 3 est une plateforme de développement front-end moderne, offrant une architecture réactive et une composition de composants performante pour la création d'interfaces utilisateur dynamiques et évolutives. Cette version apporte de nombreuses améliorations en termes de performance, d'API plus propre et de nouvelles fonctionnalités, telles que la composition API, qui simplifie la gestion de l'état et les interactions entre les composants.

Installation de Vue.js


L'installation de Vue.js peut varier en fonction de notre environnement, dans cette partie nous utiliserons les CDN pour pouvoir débuter l'utilisation de Vue.js le plus vite possible.
Un fichier de base utilisant des liens CDN est disponible ici : download

Les variables


En Vue.js, on peut gérer les variables de deux manières principales :

Variables non réactives let ou const

Ce sont des variables JavaScript standard. Les modifications apportées à ces variables ne sont pas automatiquement détectées par Vue.js. On devra mettre à jour manuellement les parties de notre application qui dépendent de ces variables.

Variables réactives ref

La fonction ref crée une référence réactive à une valeur (tableau, objet ou primitive). On accède à la valeur réelle de la variable réactive à l'aide de l'attribut value. Les changements apportés à value sont automatiquement détectés par Vue.js, ce qui met à jour les parties de notre application qui dépendent de cette variable de manière automatique.

Déclarations de variables réactives
                        let users = ref([]);
let error = ref(null);
let count = ref(0);
let message = ref('');

message.value = "Bonjour à tous.";

                        
content_copy
Un peu plus sur le const

const garantit que la variable ne peut pas être réassignée à une nouvelle valeur ou référence.
Si c'est un type primitif (nombre, chaîne, booléen, etc.), on ne peut pas changer la valeur.
Si c'est un objet ou un tableau, on ne peut pas changer l'objet ou le tableau référencé, mais on peut modifier ses propriétés ou éléments internes.

Exemple avec un type primitif
                            const x = 10;
x = 20; // Erreur ! On ne peut pas réassigner x à 20.

                            
Exemple avec un objet ou un tableau
                            const arr = [1, 2, 3];
arr[0] = 10; // Cela fonctionne, car on modifie le contenu du tableau, pas la référence.
arr = [4, 5, 6]; // Erreur ! On ne peut pas réassigner la variable 'arr' à un nouveau tableau.

const obj = { name: "Toto" };
obj.name = "Bob"; // Cela fonctionne, car on modifie une propriété de l'objet.
obj = { name: "Charlie" }; // Erreur ! On ne peut pas réassigner 'obj' à un nouvel objet.

                            

Les objets


En Vue.js, les objets permettent de créer des variables contenant plusieurs attributs. Cela facilite la gestion de données complexes en les regroupant de manière structurée.

Création
                        const message_object = ref({ show: false, message: "", color: "" });

                        
content_copy
Utilisation
                        <div v-if="message_object.show">
    <p :class="[message_object.color]">
        {{ message_object.message }}
    </p>
</div>

                        
content_copy

Les inputs


On peut gérer les entrées d'utilisateurs dans des éléments de formulaire pour modifier une variable réactive en utilisant la directive v-model. La directive v-model lie l'élément de formulaire à une variable réactive.
De plus, nous utilisons des conditions pour afficher une phrase en fonction de l'âge.

                            <!-- HTML -->
<div class="change-value mt-3">
    <input type="number" v-model="age" placeholder="Entrez votre âge" />
    <h2 v-if="age >= 18">Vous êtes majeur.</h2>
    <p v-else-if="age >= 13">Vous êtes mineur mais adolescent.</p>
    <p v-else>Vous êtes mineur.</p>
</div>

// VueJs
let age = ref(18);

                            
content_copy
Les selects

Les menus déroulants selects sont des composants importants en HTML. Dans cet exemple, nous allons voir comment les manipuler avec Vue.js 3, en sélectionnant une couleur à appliquer à un élément div HTML.

HTML
Vue
Ex interactif
Code HTML
emoji_objects

- v-model="selectedOption" : Cette directive lie la valeur sélectionnée dans le menu déroulant au modèle de données selectedOption. Cela permet de gérer et de mettre à jour facilement la valeur sélectionnée.
- option : La balise option est utilisée pour créer des choix individuels dans le menu déroulant. En utilisant v-for pour itérer à travers la liste d'options disponibles, chaque option est configurée avec un attribut value, et key pour une identification unique. Le texte affiché dans chaque balise option est défini par option.text.
- :class : Enfin, la directive de binding est utilisée pour appliquer la couleur au div.

                                        <!-- HTML -->
<select class="form-select" aria-label="Vue js select example" v-model="selectedOption">
    <option v-for="option in options" :key="option.value" :value="option.value">
        {{ option.text }}
    </option>
</select>
<p>Selected option: {{ selectedOption }}</p>

<div :class="['box', selectedOption]"></div>

                                        
content_copy
Les cases à cocher

Dans cette partie, il y aura un exemple de comment fonctionne les cases à cocher en Vue.js :

Checkbox
                            <div class="mb-3">
    <label class="form-label">Sélectionnez vos fruits préférés</label>

    <div v-for="fruit in fruits" :key="fruit.id" class="form-check">
        <input class="form-check-input" type="checkbox" :id="'fruit-' + fruit.id" :value="fruit.id" v-model="selectedFruits"/>
        <label :for="'fruit-' + fruit.id" class="form-check-label">
            {{ fruit.name }}
        </label>
    </div>
    <p>Selected option: {{ selectedFruits }}</p>
</div>

                            
content_copy

                            const fruits = ref([
    { id: 1, name: 'Orange'},
    { id: 2, name: 'Banane'},
    { id: 3, name: 'Poire'},
    { id: 4, name: 'Annanas'},
]);

                            
content_copy

Bindings (Liaisons) dynamiques


En Vue.js, nous pouvons manipuler les propriétés des éléments HTML de manière déclarative en utilisant des Bindings. Voici une liste de quelques possibilités pour gérer les attributs d'un élément HTML en Vue.js :

Fonctionnement

la balise Vue est v-bind (ou la syntaxe abrégée :)

Eléments HTML

-disabled

Pour désactiver un bouton en fonction d'une condition :

HTML
Vue
                                        <button class="btn btn-sm btn-success" @click="toggleDisableBtn">Changer l'état du bouton</button>
<button class="btn btn-sm btn-secondary" :disabled="isBtnDisabled">Bouton</button>

                                        
content_copy
Exemple Interactif

-class

Lier une classe CSS à sa version active en fonction d'une variable Vue.js :

HTML
CSS
Vue.js
emoji_objects

Si la classe contient des/un "-" il faut mettre le nom de la classe entre "''".

                                        <button class="btn btn-sm btn-primary" @click="activeBox">Activer la boîte</button>
<div class="another-class box" :class="{ active: isBoxActive }">
    Une boîte à activer.
</div>

                                        
content_copy
Une boîte à activer.
-Gestion de plusieurs classes

On peut ajouter ou enlever des classes CSS en fonction de variables Vue :

HTML
CSS
Vue.js
                                            <div class="d-flex gap-2">
    <button type="button" class="btn btn-sm btn-secondary" @click="addStyleOne">
        {{ styleOne ? '-' : '+' }} Style 1
    </button>
    <button type="button" class="btn btn-sm btn-secondary" @click="addStyleTwo">
        {{ styleTwo ? '-' : '+' }} Style 2
    </button>
    <button type="button" class="btn btn-sm btn-secondary" @click="addStyleThree">
        {{ styleThree ? '-' : '+' }} Style 3
    </button>
</div>

<div
    class="box-ex-binding"
    :class="{
        'box-ex-binding-border': styleOne,
        'text-center-box-ex-binding': styleTwo,
        'border-color-box-ex-binding': styleThree
    }">
    <p>Exemple de boîte.</p>
</div>

                                            
content_copy
Exemple Interactif

Exemple de boîte.

-Gestion de plusieurs classes et conditions ternaires

Pour une interface utilisateur plus dynamique, il est intéressant de pouvoir personnaliser la couleur d'un bouton selon la valeur d'une variable réactive Vue.js.

                                <button @click="renderDiv" :class="['btn btn-sm',  enableRender ? 'btn-warning' : 'btn-success']">
    {{ enableRender ? 'Cacher le rendu' : 'Afficher le rendu' }}
</button>

// Vue
const enableRender = ref(false);

function renderDiv() {
    enableRender.value = !enableRender.value;
}

                                
content_copy
Exemple interactif
Activer moi.
-style

Lier des styles CSS à un élément en fonction d'une expression Vue.js :

                            <button :style="{ color: textColor }">Contenu</button>

                            
content_copy
-Attributs booléens

Gérer les attributs booléens des éléments HTML, comme required, checked, readonly, etc.

                            <input type="checkbox" v-model="isChecked" :checked="isChecked" />

                            
content_copy
- Attribuer une classe CSS en fonction d'un booléen

On peut utiliser des opérateurs ternaires pour déterminer quelle classe affecter en fonction d'une valeur booléenne :

                            :class="user.all_payments_true ? 'btn-warning' : 'btn-secondary'"

                            
content_copy
-Attributs généraux

On peut également lier n'importe quel attribut HTML avec v-bind :
Supposons que nous avons une boucle v-for qui parcourt une collection récupérée par une requête Axios. Si on souhaite créer des modals en fonction de cette collection :

                            <tr v-for="(file, index) in files" :key="file.id">
    <td>
        <span v-if="file.comment === null" class="material-icons">visibility_off</span>
        <div v-else>
            <a data-bs-toggle="modal" :data-bs-target="'#showComment_'+file.id" class="material-icons color_2 cursor">visibility</a>
            <!-- Modal comment -->
            <div class="modal fade modal-close" :id="'showComment_'+file.id" tabindex="-1" aria-labelledby="" aria-hidden="true">
                ...
            </div>
        </div>
    </td> <!-- Comments -->
</tr>


                            
content_copy
emoji_objects

- :data-bs-target="'#showComment_'+file.id" : Pour utiliser l'attribut data-bs-target dans Vue.js, il faut utiliser la directive v-bind et la syntaxe "'#showComment_ '+file.id"

Manipulation des Tableaux


Création d'un tableau
                        let fruits_1 = ref[];
let fruits = ref['Pommes', 'Bananes', 'Cerises'];

                        
content_copy
Ajout d'éléments au tableau
                        let fruits = ref['Pommes', 'Bananes', 'Cerises'];
fruits.value.push('Poires');

                        
content_copy
Suppression d'éléments
                        let fruits = ref['Pommes', 'Bananes', 'Cerises'];
fruits.value.splice(index, 1);

                        
content_copy
Mise à jour d'un élément
                        let fruits = ref['Pommes', 'Bananes', 'Cerises'];
fruits.value[1] = 'Abricot';

                        
content_copy

Les boucles


En Vue.js on peut utiliser des boucles sur des élements HTML, facilitant ainsi la manipulation des données, l'affichage des données.

for
Affichage dans un HTML
for
for of
for in

La directive Vue v-for permet de parcourir une structure de données et d'afficher son contenu dans le HTML.

                                        <!-- HTML -->
<ul>
    <li v-for="fruit in fruits" :key="fruit">
        @{{ fruit }}
    </li>
</ul>

// VueJs
let fruits = ['Pommes', 'Bananes', 'Cerises'];

                                        
content_copy
forEach
forEach (simple)
forEach (avec 3 paramètres)
forEach (suppression d'une case)

La méthode forEach est une façon très pratique et lisible de parcourir les éléments d'un tableau.

                                        const factures = ref([
    { id: 1, name: 'toto', prix: 45.4, },
    { id: 2, name: 'tata', prix: 14.5, },
    { id: 3, name: 'titi', prix: 78.8, },
    { id: 4, name: 'tutu', prix: 22.35, },
]);

function loopWithForEach() {
    factures.value.forEach(facture => {
        console.log("Nom : "+facture.name+" Prix : "+facture.prix);
    });
}

                                        
content_copy
map

La méthode map est utilisée pour transformer les données d'un tableau. Elle crée systématiquement un nouveau tableau contenant les résultats de l'application d'une fonction donnée à chaque élément du tableau original. Cette méthode est particulièrement utile lorsqu'on souhaite effectuer une manipulation uniforme sur tous les éléments sans modifier le tableau d'origine.

map (multiplication)
map (ajout d'une valeur)
map (copie d'un tableau)
                                        const valeurs = [1, 2, 3, 4, 5];

function loopWithMap1() {
    let newValues = valeurs.map(valeur => valeur * 2);
    console.log("Nouvelles valeurs : "+newValues);
}

                                        
content_copy

Les conditionnelles


En Vue.js on peut utiliser des conditionnelles sur des élements HTML, facilitant ainsi la manipulation des données, l'affichage des données.

                        <!-- HTML -->
<div>
    <p v-if="isLoggedIn">Bienvenue, utilisateur !</p>
    <p v-else>Veuillez vous connecter.</p>
</div>

// VueJs
let isLoggedIn = ref(false);

                        
content_copy

Les formulaires


Dans cette partie nous allons regarder comment on peut manipuler les formulaires.

Les formulaires

Le but de cette section est de montrer comment créer un formulaire et récupérer les données :

@submit

Lorsqu'on crée un formulaire en Vue.js, il faut prendre en compte la manière de le gérer. On utilise des liaisons d'événements, dont il existe deux principaux types :

@submit="myFun"
@submit.prevent
@submit.prevent="submitForm"

- Comportement : Avec cette approche, on associe l'événement submit à une méthode spécifique définie dans l'objet Vue (dans cet exemple, la méthode s'appelle myFun).

- Utilisation : On l'utilise lorsqu'on souhaite exécuter une logique personnalisée lors de la soumission du formulaire, comme valider les données ou envoyer une requête Axios.

- Effet : Lorsque le formulaire est soumis, la méthode myFun est appelée. Si cette méthode ne contient pas event.preventDefault(), le comportement par défaut de soumission du formulaire se produira.

                                        <form @submit="myFun">
    <!-- Champ Nom -->
    <div>
        <label for="nom">Nom:</label>
        <input type="text" v-model="nom">
    </div>

    <!-- Champ Prénom -->
    <div>
        <label for="prenom">Prénom:</label>
        <input type="text" v-model="prenom">
    </div>

    <!-- Champ Date de Naissance -->
    <div>
        <label for="date_naissance">Date de Naissance:</label>
        <input type="date" v-model="dateNaissance">
    </div>

    <!-- Champ Adresse Mail -->
    <div>
        <label for="email">Adresse Mail:</label>
        <input type="email" v-model="email">
    </div>

    <!-- Champ Mot de Passe -->
    <div>
        <label for="mot_de_passe">Mot de Passe:</label>
        <input type="password" v-model="motDePasse">
    </div>

    <button type="submit">Envoyer</button>
</form>

<!-- Affichage des données du formulaire -->
<div>
    <h2>Données du formulaire:</h2>
    <p>Nom: {{ nom }}</p>
    <p>Prénom: {{ prenom }}</p>
    <p>Date de Naissance: {{ dateNaissance }}</p>
    <p>Email: {{ email }}</p>
    <p>Mot de Passe: {{ motDePasse }}</p>
</div>

                                        
content_copy

                                        // Code vue.js

// Variables réactives
const nom = ref('');
const prenom = ref('');
const dateNaissance = ref('');
const email = ref('');
const motDePasse = ref('');

function myFun() {
    event.preventDefault();
    console.log("ok");
}

// Retourner les variables pour les utiliser dans le template
return {
    nom,
    prenom,
    dateNaissance,
    email,
    motDePasse,

    myFun
};

                                        
content_copy

Watch & WatchEffect

Les fonctions watchEffect et watch permettent toutes deux d'observer et de réagir aux changements des données réactives. Cependant, elles se distinguent par leur fonctionnement et leurs cas d'utilisation spécifiques.

watchEffect
watch

- Fonctionnement : elle exécute une fonction immédiatement lors de la création, puis à chaque fois que les données réactives utilisées à l'intérieur de cette fonction changent le code de la fonction s'exécute de nouveau.

Exemple d'utilisation de watchEffect

Dans cet exemple le but est d'activer ou désactiver un bouton en fonction de la taille d'un tableau. Nous avons un tableau réactif que l'on peut modifier en ajoutant ou supprimant des éléments. Le bouton (Supprimer) sera désactivé si le tableau ne contient qu'un seul élément. Le bouton (Ajouter) sera désactivé si on atteint 10 éléments dans le tableau.

                                        <!-- Code HTML -->
<p>Nombre d'éléments : {{ items.length }}</p>
<button class="btn btn-primary" @click="addItem" :disabled="isAddedDisabled">Ajouter un élément</button>
<button class="btn btn-danger" @click="removeItem" :disabled="isRemoveDisabled">Supprimer un élément</button>

<div class="items">
    <div v-for="(item, index) in items" :key="index" :class="['item', item.color]">
        {{ item.value }}
    </div>
</div>

                                        
content_copy

                                        // Tableau réactif où chaque élément contient une valeur et une couleur associée
const items = ref([ {value:'Elément 1', color: getRandomColor()} ]);
// Variable réactif pour contrôler l'état du bouton "Supprimer"
const isRemoveDisabled = ref(false);
// Variable réactif pour contrôler l'état du bouton "Ajouter"
const isAddedDisabled = ref(false);

// Fonction pour ajouter un élément au tableau avec une couleur aléatoire
function addItem() {
    if(items.value.length <= 9) {
        items.value.push({
            value: `Elément ${items.value.length + 1}`,
            color: getRandomColor(),
        });
    }
}

// Fonction pour supprimer un élément du tableau
function removeItem() {
    if(items.value.length > 0) {
        items.value.pop();
    }
}

function getRandomColor() {
    const colors = ['green', 'red', 'blueviolet'];
    return colors[Math.floor(Math.random() * colors.length)];
}

// watchEffect pour activer/désactiver le bouton "Supprimer"
watchEffect(() => {
    isRemoveDisabled.value = items.value.length <= 1;
    isAddedDisabled.value = items.value.length >= 10;
});

                                        
content_copy
Affecter directement une fonction à un watchEffect

Plutôt que d'écrire le code avec la syntaxe () => { ... }, il est possible de créer une fonction séparée et de l'affecter directement.

                                        function buttonsEffect() {
    isRemoveDisabled.value = items.value.length <= 1;
    isAddedDisabled.value = items.value.length >= 10;
}

watchEffect(buttonsEffect);

                                        
content_copy

Nombre d'éléments : 1

Elément 1

Exemple complet de validation d'un formulaire

HTML
Vue
Exemple interactif
HTML
                                        <form @submit.prevent="submitForm">
    <div class="mb-3 last-name">
        <label class="form-label">Nom <strong class="c_red">*</strong></label>
        <div class="input-group">
            <span class="input-group-text material-icons">badge</span>
            <input type="text" class="form-control" v-model="lastName" required>
        </div>
    </div>

    <div class="mb-3 first-name">
        <label class="form-label">Prénom <strong class="c_red">*</strong></label>
        <div class="input-group">
            <span class="input-group-text material-icons">badge</span>
            <input type="text" class="form-control" v-model="firstName" required>
        </div>
    </div>

    <div class="mb-3 email">
        <label class="form-label">Adresse mail <strong class="c_red">*</strong></label>
        <div class="input-group">
            <span class="input-group-text material-icons">alternate_email</span>
            <input type="email" class="form-control" v-model="emailAddress" required>
        </div>
    </div>

    <div class="mb-3 phone-number">
        <label class="form-label">Numéro de téléphone</label>
        <div class="input-group">
            <button class="btn btn-outline-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">{{ phoneIndicator }}</button>
            <ul class="dropdown-menu">
                <li v-for="(code, country) in countryCodes" :key="country">
                    <a class="dropdown-item" @click="selectCode(code)">{{ country }} ({{ code }})</a>
                </li>
            </ul>
            <input type="number" class="form-control" v-model="phoneNumber">
        </div>
    </div>

    <div class="mb-3 date-birth">
        <label class="form-label">Date de naissance</label>
        <div class="input-group">
            <span class="input-group-text material-icons">calendar_month</span>
            <input type="date" class="form-control" v-model="dateOfBirth">
        </div>
    </div>

    <div class="d-grid">
        <button class="btn btn-sm btn-success btn-rounded" :disabled="!isFormValid">Ajouter un utilisateur</button>
    </div>
</form>

                                        
content_copy

Fonctions


En Vue.js on peut définir les fonctions de différentes manières :

Function Expression
Syntaxe

La première définition utilise la syntaxe de fonction fléchée const incrementCount = () => { count.value++; };. C'est une Function Expression qui assigne une fonction anonyme à une constante const. Les fonctions fléchées sont plus courtes et peuvent être utilisées de manière plus concise.

Portée

Dans le cas d'une expression de fonction, la fonction utilise la portée léxicale lexical scope. Cela signifie que this dans la fonction fléchée est lié à la portée dans laquelle elle est définie (c'est-à-dire this sera le même que dans la fonction parent). Cela rend la gestion de la portée de this plus simple.

                        const incrementCount = () => {
    count.value++;
};

                        
content_copy
Function Declaration
Syntaxe

La deuxième définition est une déclaration de fonction classique function incrementCount() { count.value++; }. Elle déclare une fonction nommée de manière plus traditionnelle.

Portée

Dans le cas d'une Function Declaration, this est dynamique et dépend de l'endroit où la fonction est appelée. Cela peut conduire à une confusion ou des erreurs dans certains contextes.

                        function incrementCount() {
    count.value++;
}

                        
content_copy
emoji_objects

En résumé, les deux définitions de fonction montrées sont équivalentes en termes de comportement, mais utilisent des syntaxes et des portées différentes.
La fonction fléchée (arrow function) est souvent préférée en Vue 3 pour sa concision et sa gestion plus claire de this.

Composants et paramètres


Le but de Vue.js est de créer des composants réutilisables. Pour ce faire, nous avons besoin que ces composants acceptent des paramètres lors de leur appel. Cela nous permet d'utiliser le même composant, qui effectue une tâche spécifique, sur plusieurs pages tout en affichant ou en traitant des données différentes.

Du parent vers l'enfant

Dans ce premier exemple, le but est de créer un composant qui accepte en paramètre un endpoint HTTP d'API (ou autre) et qui retourne un message (à l'intérieur du composant enfant).

Laravel
Flask
Hapi Js
Vue.js 1/2
Vue.js 2/2
Appel du composant

Laravel

                                        // Le endpoint est /get-message
public function returnMessage() {
    // Le message a retourner
    $message = "Un composant avec des paramètres c'est chouette.";

    return response()->json([
        'message' => $message,
    ], 200);
}

                                        
content_copy
emoji_objects

Sur les codes de vue.js 2.4 des erreurs peuvent être présentent.

Vue.js 2.4
Appel du composant

Vue.js 2.4

                                        var app = new Vue({
    el: '#app',
    props: {
        endPoint: {
            type: String,
            required: true
        }
    },
    data() {
        return {
            message: ''
        };
    },
    mounted() {
        // Requête Axios vers l'endPoint fourni
        this.printMessage();
    },
    methods: {
        async printMessage() {
            try {
                const response = await axios.get(this.endPoint);
                if (response.status === 200) {
                    this.message = response.data.message;
                }
            } catch (error) {
                console.error('Erreur lors de la requête :', error);
            }
        }
    }
});

                                        
content_copy

Du composant enfant vers le parent

Le but de cet exemple est de retourner une valeur d'un composant enfant vers le composant parent qui l'appel.

Enfant (HTML)
Enfant (Vue.js)
Parent (HTML)
Parent (Vue.js)
Compsant enfant

On commence par créer le composant HTML ou la requête HTTP que l'on souhaite transmettre au composant parent.

                                        <template>
    <span>Saisir un âge</span>
    <input type="number" v-model="age">
    <button class="button" @click="sendDataToParent()">Envoyer</button>
</template>

                                        
content_copy
Vue.js 2.4
Appel du composant

Vue.js 2.4

                                        var app = new Vue({
    el: '#app',
    data() {
        return {
            age: null,
        };
    },
    methods: {
        sendDataToParent() {
            if (!this.age) {
                console.warn("LA SAISIE DE L'AGE EST OBLIGATOIRE.");
                return;
            }
            // Émettre l'événement avec la donnée
            this.$emit('dataToReceive', this.age);
        }
    }
});

                                        
content_copy

Gestion des erreurs

Pour simplifier la gestion des erreurs attendues côté client, on peut utiliser des fonctions qui permettent d'indiquer en paramètres les erreurs attendues et de les traiter plus facilement.

Objet message
Fonction d'affichage
Fonction de masquage
Affichage coté front
Fonction gestions des erreurs
Exemple d'utilisation
Un objet pour afficher les messages
                                    const msg = ref({
    show: false,
    message: "",
    bgColor: "",
    timeoutId: null
});

                                    
content_copy

Opérations CRUD


Dans cette section, nous examinerons en détail les diverses opérations CRUD (Create, Read, Update, Delete) en utilisant Vue.js 3, Laravel 10, Flask et Hapi Js.

Une requête Axios

Le code suivant montre le squelette type d'une requête Axios, il démontre comment vérifier les différents codes HTTP renvoyés par le serveur :

                        // Cette fonction effectue une requête Axios POST
async function postAddRole() {
    const dataToSend = {
        roleName: roleName.value
    };

    try {
        const response = await axios.post('/role/create-roles', dataToSend);
        return response;
    } catch (err) {
        throw err;
    }
}

async function handleAddRole(event) {
    event.preventDefault();

    try {
        const response = await postAddRole();
        const statusCode = response.status;

        // A CE STADE ON NE PEUT CAPTER QUE LA PLAGE DE 2XX
        if (statusCode === 200) {
            console.log("REQUETE OK");
        } else {
            console.log("Erreur requête");
        }
    } catch (err) {
        handleErrors(err, [400, 500] msg.value);
    }
}

                        
content_copy

Create

Dans cette section, nous allons aborder l'opération de création Create et examiner comment créer une ressource en utilisant Axios.

Laravel
Flask
Hapi Js

Laravel

                                    public function handleCrudPost(Request $request) {
    $validatedData = $request->validate([
        'nom' => 'required|string|regex:/^[a-zA-Z\s-]+$/|min:2|max:60',
        'prenom' =>'required|string|regex:/^[a-zA-Z\s-]+$/|min:2|max:60',
    ]);

    return response()->json([
        'message' => 'Ressource créée.',
    ], 200);
}

                                    
content_copy
Formulaire HTML

Nous allons commencer par créer un formulaire avec deux champs :

                            // CSS
.bg-danger { background-color: rgb(221, 62, 62); }
.bg-success { background-color: #2dd288; }

<form @submit="handleForm">
    // csrf
    <div class="mb-3">
        <label for="labelInputEmail" class="form-label">Nom</label>
        <input type="text" class="form-control" v-model="nom" aria-describedby="nom">
    </div>

    <div class="mb-3">
        <label for="labelInputEmail" class="form-label">Prénom</label>
        <input type="text" class="form-control" v-model="prenom" aria-describedby="prenom">
    </div>

    <button class="btn btn-success" :disabled="!isFormValid">Envoyer les données</button>
</form>

<div
    v-if="msg.show"
    :class="['d-flex', 'message-server', msg.bgColor]"
    >
    <span class="material-icons">info</span>
    <p>{{ msg.message }}</p>
</div>

                            
content_copy
Code Vue

Maintenant, nous allons écrire le code Vue pour gérer le bouton de validation, la liaison des champs et l'affichage des messages :

                            // Consts
const nomRegex = /^[a-zA-Z\s-]+$/;

// Variables
let nom = ref('');
let prenom = ref('');
let isFormValid = ref(false);

const msg = ref({
    show: false,
    message: "",
    bgColor: "",
    timeoutId: null
});

watchEffect(() => {
    // Vérifie si tous les champs sont remplis
    isFormValid.value = nomRegex.test(nom.value.trim()) &&
                        nomRegex.test(prenom.value.trim());
});

async function postRequest() {
    const dataToSend = {
        nom: nom.value,
        prenom: prenom.value
    };

    try {
        const response = await axios.post('crud-post', dataToSend);
        return response;
    } catch (err) {
        throw err;
    }
}

function resetForm() {
    nom.value = '';
    prenom.value = '';
}

async function handleForm(event) {
    event.preventDefault();
    if (!isFormValid.value) { return; }

    try {
        const response = await postRequest();
        const statusCode = response.status;

        if (statusCode === 200) {
            message.value = response.data.message;
            showMessageServer(message.value, message, 'bg-success', 10000);
            resetForm();
        }
    } catch (err) {
        handleErrors(err, [422, 500], msg.value);
    }
}

                            
content_copy

Read

Dans cette section, nous allons voir l'opération Read et comment lire des ressources avec Axios et Laravel.

Laravel
Flask
Hapi Js

Laravel

                                    public function getInfo() {
    // Liste des utilisateurs
    $users = [
        ['id' => 1, 'name' => 'Mahmoud'],
        ['id' => 2, 'name' => 'Toto'],
        ['id' => 3, 'name' => 'Tata'],
        ['id' => 4, 'name' => 'Titi'],
    ];

    return response()->json([
        'users' => $users,
    ], 200);
}

                                    
content_copy
Code HTML
                        <canvas ref="myChart"></canvas>

                        
content_copy
Code Vue

Dans notre code Vue.js, nous allons récupérer les données du contrôleur avec une requête GET, puis créer un graphique avec Chart.js.

                        let ventes = ref(null);
let error = ref(null);
let myChart = ref(null);

// Requête Axios
async function getData() {
    try {
        const response = await axios.get('get-info');
        ventes.value = response.data.ventes;
    } catch (err) {
        console.log('Erreur lors de la requête API :', err.message);
    } finally {
        initializeChart();
    }
}

// Code du chart
function initializeChart() {
    if (ventes.value === null) {
        console.log("ERREUR : Aucune donnée.");
        return;
    }

    const ctx = myChart.value.getContext('2d');

    new Chart(ctx, {
        type: 'bar',
        data: {
            // On extrait les mois ['Janvier', 'Février', 'Mars']
            labels: ventes.value.map(vente => vente.mois),
            datasets: [{
                label: 'Ventes',
                // On extrait les valeurs [140, 240, 350]
                data: ventes.value.map(vente => vente.data),
                borderWidth: 1
            }]
        },
        options: {
            scales: {
                y: {
                    beginAtZero: true
                }
            }
        }
    });
}

onMounted(async () => {
    getData();
});

return {
    loading,

    ventes,
    myChart,
}

                        
content_copy

Update

Dans cette section, nous allons aborder l'opération de mise à jour Update et explorer comment mettre à jour une ressource en utilisant Axios.

Delete

Dans cette section, nous allons aborder l'opération de suppression Delete et étudier comment supprimer une ressource en utilisant Axios.