Laravel

Un framework qui rend heureux

Voir cette catégorie
Vers le bas
Comprendre Vue.js : simple application
Lundi 12 novembre 2018 22:08
Pour poursuivre notre exploration de Vue je vous propose dans ce nouvel article de créer une petite application qui va se contenter de calculer la TVA avec ses différents taux. Ça va nous permettre de voir de nouvelles possibilités et d'avancer dans la compréhension de Vue. Le code final pour cet article est téléchargeable ici.

On crée le projet

On commence par créer un nouveau projet en acceptant les réglages par défaut :
vue create tva
Si ça se termine comme ça c'est parfait : Si ce n'est pas le cas reportez-vous au précédent article pour voir si vous avez tous les outils nécessaires. Voilà la structure du projet : On lance avec :
npm run serve
On obtient au bout d'un moment la page classique d'accueil : On va conserver le composant HelloWorld mais on va changer son nom pour Tva, ce qui sera plus logique pour notre application : Évidemment la compilation va bloquer : On commence par renommer dans Tva.vue :
<script>
export default {
  name: 'Tva'  // On avait 'HelloWorld',
  props: {
    msg: String
  }
}
</script>
Et on change aussi dans App.vue :
<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <Tva msg="Calcul de la TVA"/>
  </div>
</template>

<script>
import Tva from './components/Tva.vue'

export default {
  name: 'app',
  components: {
    Tva
  }
}
</script>
Changez bien les 4 emplacements  ainsi que le texte de msg ! Normalement maintenant ça devrait refonctionner... C'est aussi une bonne idée de changer le logo qui est ici : Par exemple avec celui-ci :

Un framework CSS

Pour nous simplifier la vie on va utiliser un framework CSS, cette fois Bootstrap pour changer un peu.
npm i bootstrap
A l'installation on reçoit quelques alertes : En effet Bootstrap a besoin de Jquery et Popper pour certaines fonctionnalités mais on ne devrait pas en avoir besoin pour notre application. Si c'est le cas on installera ces librairies... Il nous faut charger Bootstrap avec main.js:
import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

// On charge Bootstrap
import "bootstrap/dist/css/bootstrap.min.css";

new Vue({
  render: h => h(App),
}).$mount('#app')
On va faire un peu le ménage dans les composants :
  • App.vue : on change le template et le style :
<template>
  <div class="container" id="app">
    <div class="row justify-content-center text-center">
      <div class="col-6">
        <img alt="Vue logo" src="./assets/logo.png">
        <Tva msg="Calcul de la Tva"/>
      </div>
    </div>
  </div>
</template>

...

<style>
body {
  padding-top: 2rem;
}
</style>
  • Tva.vue : on supprime tout le style et on change le template ainsi :
<template>
  <div>
    <h1>{{ msg }}</h1>
  </div>
</template>
Normalement vous avec le logo et le titre bien centré :

Le formulaire

Il nous faut mettre en place maintenant un formulaire pour le calcul de la TVA... On va préparer ce formulaire dans le composant Tva :
<template>
  <div>
    <h1>{{ msg }}</h1>
    <div class="jumbotron">
      <div class="row col input-group mb-4">
        <input type="text" class="form-control">
        <div class="input-group-append">
          <span class="input-group-text">€ HT</span>
        </div>
      </div>
      <div class="row col mb-4">
        Taux : &nbsp;
        <div class="form-check form-check-inline">
          <input class="form-check-input" value="0.2"type="radio" name="tva" id="20" checked>
          <label class="form-check-label" for="20">20 %</label>
        </div>
        <div class="form-check form-check-inline">
          <input class="form-check-input" value="0.1" type="radio" name="tva" id="10">
          <label class="form-check-label" for="10">10 %</label>
        </div>
        <div class="form-check form-check-inline">
          <input class="form-check-input" value="0.055" type="radio" name="tva" id="55">
          <label class="form-check-label" for="55">5,5 %</label>
        </div>
        <div class="form-check form-check-inline">
          <input class="form-check-input" value="0.021" type="radio" name="tva" id="21">
          <label class="form-check-label" for="21">2,1 %</label>
        </div>
      </div>
      <div class="row col">
        Montant TTC : &nbsp;<strong>*** €</strong>
      </div>      
      <div class="row col">
        Montant de la TVA : &nbsp;<strong>*** €</strong>
      </div>
      </div>
    </div>
  </div>
</template>
Avec un peu de style :
<style scoped>
.jumbotron {
  margin-top: 2rem;
  padding: 2rem;
}
</style>
Ce qui donne maintenant cet aspect : Il ne reste plus qu'à faire fonctionner ce formulaire !

Vue en action

Donc on entre la valeur HT et selon le taux ça nous donne la valeur TTC ainsi que le montant de la TVA. Au niveau des data on va avoir deux valeurs :
data: function() {
  return {
    valeurHT: 0,      
    taux: '0.2'
  }
},

v-model

Commençons par traiter les boutons radio :
<div class="row col mb-4">
  Taux : &nbsp;
  <div class="form-check form-check-inline">
    <input class="form-check-input" value="0.2" v-model="taux" type="radio" name="tva" id="20" checked>
    <label class="form-check-label" for="20">20 %</label>
  </div>
  <div class="form-check form-check-inline">
    <input class="form-check-input" value="0.1" v-model="taux" type="radio" name="tva" id="10">
    <label class="form-check-label" for="10">10 %</label>
  </div>
  <div class="form-check form-check-inline">
    <input class="form-check-input" value="0.055" v-model="taux" type="radio" name="tva" id="55">
    <label class="form-check-label" for="55">5,5 %</label>
  </div>
  <div class="form-check form-check-inline">
    <input class="form-check-input" value="0.021" v-model="taux" type="radio" name="tva" id="21">
    <label class="form-check-label" for="21">2,1 %</label>
  </div>
</div>
Avec v-model on établit un lien entre les boutons radio et la variable taux. Si on clique sur un bouton radio la valeur de taux va changer pour la valeur de l'attribut value de ce bouton. Les deux sont désormais liés : Vous pouvez vérifier que ça fonctionne avec l'outil de développement : Voyons maintenant le contrôle pour la valeur HT :
<div class="row col input-group mb-4">
  <input v-model="valeurHT" type="text" class="form-control">
  <div class="input-group-append">
    <span class="input-group-text">€ HT</span>
  </div>
</div>
Là on utilise encore v-model pour lier le contrôle pour la valeur HT et la variable valeurHT.

computed

Pour la valeur TTC on doit effectuer un calcul. Dans ce cas on utilise une propriété calculée computed :
<script>
export default {
  ...
  data: function() {
    return {
      valeurHT: 0,      
      taux: '0.2'
    }
  },
  computed: {
    valeurTTC: function() {
      return parseFloat(this.valeurHT) + this.valeurHT * parseFloat(this.taux);
    }
  }
}
</script>
On prévoit l'affichage dans le template :
<div class="row col">
  Montant TTC : &nbsp;<strong>{{ valeurTTC }} €</strong>
</div>
Maintenant quand on choisit un taux et qu'on entre une valeur HT ça fonctionne : Vous pouvez vérifier aussi que le changement de taux modifie de façon dynamique la valeur TTC ! Il ne nous manque plus que la valeur de la TVA dans le template :
<div class="row col">
  Montant de la TVA : &nbsp;<strong>{{ valeurTVA }} €</strong>
</div>
Et à nouveau une valeur calculée :
computed: {
  ...
  valeurTVA: function() {
    return this.valeurHT * parseFloat(this.taux);
  }
}
Et maintenant tout fonctionne : On peut simplifier le code en imposant une valeur numérique pour les v-model :
<input v-model.number="valeurHT" type="text" class="form-control">
On fait la même chose pour les boutons radio du taux et du coup le Javascript est plus léger parce qu'on évite des conversions :
computed: {
  valeurTTC: function() {
    return this.valeurHT + this.valeurTVA;
  },
  valeurTVA: function() {
    return this.valeurHT * this.taux;
  }
}
J'en ai profité pour aussi faire référence à la valeur de la TVA plutôt que de la recalculer.

Les filtres

Et l'application est terminée ! Enfin presque... Si par exemple je rentre 111 comme valeur HT j'obtiens : Ça serait quand même mieux de limiter à deux chiffres après la virgule. On peut utiliser la méthode toFixed :
computed: {
  valeurTTC: function() {
    return parseFloat(this.valeurHT + this.valeurHT * this.taux).toFixed(2);
  },
  valeurTVA: function() {
    return parseFloat(this.valeurHT * this.taux).toFixed(2);
  }
}
  C'est beaucoup mieux ainsi mais on a un peu alourdi le code... On peut conserver le code initial :
computed: {
  valeurTTC: function() {
    return this.valeurHT + this.valeurTVA;
  },
  valeurTVA: function() {
    return this.valeurHT * this.taux;
  }
},
Et ajouter un filtre :
<script>
export default {
  ...
  filters: {
    twoDecimals: function (value) {
      return parseFloat(value).toFixed(2);
    }
  }
}
</script>
Il suffit ensuite d'ajouter le filtre dans le template pour l'affichage désiré :
<div class="row col">
  Montant TTC : &nbsp;<strong>{{ valeurTTC | twoDecimals }} €</strong>
</div>      
<div class="row col">
  Montant de la TVA : &nbsp;<strong>{{ valeurTVA | twoDecimals }} €</strong>
</div>
Et cette fois on a fini notre application !

La communauté

Lorsque vous avez besoin d'une fonctionnalité avec Vue il est presque certain que quelqu'un l'a déjà réalisée. Il existe une page qui regroupe toutes les ressources. La liste est très longue et enfle rapidement au point qu'il devient parfois difficile de retrouver quelque chose.   Prenons le cas du filtre que nous venons de créer. En fait on pourrait ajouter une librairie qui comporte déjà ce filtre (il y en a en fait plusieurs) : Il suffit de l'installer :
npm install vue-currency-filter
De la charger dans main.js en précisant le symbole de l'euro dans la configuration ainsi que le nombre de décimales et la position du symbole :
import VueCurrencyFilter from 'vue-currency-filter';
Vue.use(VueCurrencyFilter, { 
  symbol : '€',
  fractionCount: 2,
  symbolPosition: 'back'
});
Et ensuite de l'utiliser :
Montant TTC : &nbsp;<strong>{{ valeurTTC | currency }}</strong>
Et vous allez retrouver le même fonctionnement ! On verra d'autres librairies bien pratiques...

Conclusion

dans ce deuxième article on a commencé à faire quelque chose de concret, une petite application de calcul de TVA. Ça nous a donné l'occasion de découvrir la double liaison avec v-model, les propriétés calculées computed et les filtres. Dans le prochain article on explorera un peu plus loin les possibilités de Vue...


Par bestmomo

Nombre de commentaires : 4