Vue.js pour les débutants, leçon 10: formulaires

Aujourd'hui, dans la leçon 10 du cours Vue, nous allons parler de la façon de travailler avec les formulaires. Les formulaires vous permettent de collecter les données saisies par l'utilisateur. De plus, nous discuterons ici de la validation du formulaire, c'est-à-dire de la vérification de ce qui y est entré.







Vue.js pour les débutants Leçon 1: Instance de Vue

Vue.js pour les débutants, Leçon 2: Liaison d'attributs

Vue.js pour les débutants, Leçon 3: Rendu conditionnel

Vue.js pour les débutants, Leçon 4: Listes de rendu

Vue .js pour les débutants leçon 5: traitement des événements

Vue.js pour débutants leçon 6: lier les classes et les styles

Vue.js pour débutants leçon 7: propriétés calculées

Vue.js pour débutants leçon 8: composants

Vue. js pour les débutants leçon 9: événements personnalisés



Le but de la leçon



Nous allons créer un formulaire permettant aux visiteurs du site de soumettre des avis sur les produits. Dans le même temps, il est nécessaire que la révision ne puisse être envoyée que si tous les champs du formulaire sont remplis, ce qui doit être rempli.



Code initial



Voici ce qu'il y a maintenant index.html:



<div id="app">
  <div class="cart">
    <p>Cart({{ cart.length }})</p>
  </div>

  <product :premium="premium" @add-to-cart="updateCart"></product>
</div>


Cela ressemble à ceci main.js:



Vue.component('product', {
  props: {
    premium: {
      type: Boolean,
      required: true
    }
  },
  template: `
  <div class="product">
    <div class="product-image">
      <img :src="image" />
    </div>

    <div class="product-info">
      <h1>{{ title }}</h1>
      <p v-if="inStock">In stock</p>
      <p v-else>Out of Stock</p>
      <p>Shipping: {{ shipping }}</p>

      <ul>
        <li v-for="detail in details">{{ detail }}</li>
      </ul>
      <div
        class="color-box"
        v-for="(variant, index) in variants"
        :key="variant.variantId"
        :style="{ backgroundColor: variant.variantColor }"
        @mouseover="updateProduct(index)"
      ></div>

      <button
        v-on:click="addToCart"
        :disabled="!inStock"
        :class="{ disabledButton: !inStock }"
      >
        Add to cart
      </button>

    </div>
  </div>
  `,
  data() {
    return {
      product: 'Socks',
      brand: 'Vue Mastery',
      selectedVariant: 0,
      details: ['80% cotton', '20% polyester', 'Gender-neutral'],
      variants: [
        {
          variantId: 2234,
          variantColor: 'green',
          variantImage: './assets/vmSocks-green.jpg',
          variantQuantity: 10
        },
        {
          variantId: 2235,
          variantColor: 'blue',
          variantImage: './assets/vmSocks-blue.jpg',
          variantQuantity: 0
        }
      ]
    }
  },
    methods: {
      addToCart() {
        this.$emit('add-to-cart', this.variants[this.selectedVariant].variantId);
      },
      updateProduct(index) {
        this.selectedVariant = index;
        console.log(index);
      }
    },
    computed: {
      title() {
        return this.brand + ' ' + this.product;
      },
      image() {
        return this.variants[this.selectedVariant].variantImage;
      },
      inStock() {
        return this.variants[this.selectedVariant].variantQuantity;
      },
      shipping() {
        if (this.premium) {
          return "Free";
        } else {
          return 2.99
        }
      }
    }
})

var app = new Vue({
  el: '#app',
  data: {
    premium: true,
    cart: []
  },
  methods: {
    updateCart(id) {
      this.cart.push(id);
    }
  }
})


Tâche



Nous voulons que les visiteurs du site puissent laisser des avis sur les produits, mais notre site n'a pas encore les moyens de recevoir des données des utilisateurs. Les formulaires sont de tels moyens.



La solution du problème



Pour résoudre la tâche qui nous attend, nous devons créer un formulaire. Commençons par créer un nouveau composant spécifiquement pour travailler avec un formulaire. Appelons ce composant product-review. Ce nom a été choisi car le composant prendra en charge le formulaire de collecte des avis sur les produits. Le composant product-reviewsera imbriqué dans le composant product.



Enregistrons un nouveau composant, commençons à former son modèle et équipons-le de quelques données:



Vue.component('product-review', {
  template: `
    <input>
  `,
  data() {
    return {
      name: null
    }
  }
})


Comme vous pouvez le voir, il y a un élément dans le modèle de composant <input>, et il y a une propriété dans les données du composant data, alors qu'il est vide.



Comment lier ce que l'utilisateur entre dans un champ à une propriété name?



Dans les leçons précédentes, nous avons parlé de la liaison de données à l'aide de directives v-bind, mais nous n'avons considéré que la liaison unidirectionnelle. Le flux de données est passé de la propriété qui stocke les données au contrôle qui les rend. Et maintenant, nous avons besoin que ce que l'utilisateur entre dans le champ apparaisse dans la propriété namestockée dans les données du composant. En d'autres termes, nous voulons que le flux de données soit dirigé du champ d'entrée vers la propriété.



Directive modèle V



La directive v-modelpermet d'organiser la liaison de données bidirectionnelle. Avec ce schéma de travail, si quelque chose de nouveau apparaît dans le champ de saisie, cela entraîne une modification des données. Et, en conséquence, lorsque les données changent, l'état du contrôle qui utilise ces données est mis à jour.



Ajoutons une directive au champ d'entrée v-modelet lions ce champ à une propriété à namepartir des données du composant.



<input v-model="name">


Ajoutons maintenant le code de formulaire complet au modèle de composant:



<form class="review-form" @submit.prevent="onSubmit">
  <p>
    <label for="name">Name:</label>
    <input id="name" v-model="name" placeholder="name">
  </p>

  <p>
    <label for="review">Review:</label>
    <textarea id="review" v-model="review"></textarea>
  </p>

  <p>
    <label for="rating">Rating:</label>
    <select id="rating" v-model.number="rating">
      <option>5</option>
      <option>4</option>
      <option>3</option>
      <option>2</option>
      <option>1</option>
    </select>
  </p>

  <p>
    <input type="submit" value="Submit">  
  </p>

</form>


Comme vous pouvez le voir, les v-modelchamps input, textareaet sont équipés de la directive select. Veuillez noter que lors de la configuration du champ select, un modificateur a été utilisé .number(nous en parlerons plus en détail ci-dessous). Cela vous permet de convertir les données correspondantes en un type Number, alors qu'elles sont généralement représentées dans une chaîne.



Complétons l'ensemble de données du composant en y ajoutant les données auxquelles les contrôles décrits ci-dessus sont liés:



data() {
  return {
    name: null,
    review: null,
    rating: null
  }
}


En haut du modèle de formulaire, vous pouvez voir que lorsque le formulaire est soumis, une méthode est appelée onSubmit. Nous créerons bientôt cette méthode. Mais d'abord, parlons du rôle de la construction .prevent.



Ceci est un modificateur d'événement. Il empêche la page d'être rechargée après le déclenchement de l'événement submit. Il existe également d'autres modificateurs d'événements utiles . Certes, nous n'en parlerons pas.



Nous sommes maintenant prêts à créer une méthode onSubmit. Commençons par ce code:



onSubmit() {
  let productReview = {
    name: this.name,
    review: this.review,
    rating: this.rating
  }
  this.name = null
  this.review = null
  this.rating = null
}


Comme vous pouvez le voir, cette méthode crée un objet basé sur les données saisies par l'utilisateur. Une référence à celle-ci est écrite dans une variable productReview. Nous laissons tomber ici dans la nullvaleur des propriétés name, review, rating. Mais le travail n'est pas encore terminé. Nous devons encore envoyer quelque part productReview. Où envoyer cet objet?



Il est judicieux de stocker les avis sur les produits au même endroit où les données des composants sont stockées product. Étant donné que le composant est product-reviewimbriqué dans un composant product, on peut dire qu'il product-reviews'agit d'un enfant du composant product. Comme nous l'avons appris dans la leçon précédente, pour envoyer des données des composants enfants aux composants parents, vous pouvez utiliser les événements générés par $emit.



Affinons la méthode onSubmit:



onSubmit() {
  let productReview = {
    name: this.name,
    review: this.review,
    rating: this.rating
  }
  this.$emit('review-submitted', productReview)
  this.name = null
  this.review = null
  this.rating = null
}


Maintenant, nous générons un événement avec un nom review-submittedet y passons l'objet nouvellement créé productReview.



Ensuite, nous devons organiser l'écoute de cet événement en plaçant les éléments productsuivants dans le modèle :



<product-review @review-submitted="addReview"></product-review>


Cette ligne se lit comme suit: "Lorsqu'un événement se produit review-submitted, la méthode du addReviewcomposant doit être exécutée product."



Voici le code de cette méthode:



addReview(productReview) {
  this.reviews.push(productReview)
}


Cette méthode prend l'objet productReviewqui provient de la méthode onSubmit, puis le place dans un tableau reviewsstocké dans les données du composant product. Mais il n'y a pas encore de tableau de ce type dans les données de ce composant. Alors ajoutons-le ici:



reviews: []


Merveilleux! Les éléments du formulaire sont maintenant liés aux données du composant product-review. Ces données sont utilisées pour créer l'objet productReview. Et cet objet est passé, lors de la soumission du formulaire, au composant product. En conséquence, l'objet est productReviewajouté au tableau reviews, qui est stocké dans les données du composant product.



Affichage des avis sur les produits



Il ne reste plus qu'à afficher sur la page produit les avis laissés par les visiteurs du site. Nous allons faire cela dans le composant producten plaçant le code correspondant au-dessus du code avec lequel le composant product-reviewest placé dans le composant product.



<div>
 <h2>Reviews</h2>
 <p v-if="!reviews.length">There are no reviews yet.</p>
 <ul>
   <li v-for="review in reviews">
   <p>{{ review.name }}</p>
   <p>Rating: {{ review.rating }}</p>
   <p>{{ review.review }}</p>
   </li>
 </ul>
</div>


Ici, nous créons une liste de critiques à l'aide de la directive v-foret affichons les données stockées dans l'objet en reviewutilisant la notation par points. 



Dans la balise, <p>nous vérifions s'il y a quelque chose dans le tableau reviews(en vérifiant sa longueur). S'il n'y a rien dans le tableau, nous imprimons un message There are no reviews yet.





Page du formulaire de commentaires



Validation du formulaire



Les formulaires contiennent souvent des champs qui doivent être remplis avant de soumettre le formulaire. Par exemple, nous ne voulons pas que les utilisateurs soumettent des avis dans lesquels le champ de texte de l'avis est vide.



Heureusement pour nous, HTML5 prend en charge le required. Son utilisation ressemble à ceci:



<input required >


Une telle construction entraînera l'affichage automatique d'un message d'erreur si l'utilisateur tente de soumettre un formulaire dans lequel le champ requis est vide.





Message d'erreur



Avoir des validateurs de champ de formulaire standard dans le navigateur est très agréable, car cela peut nous libérer de la création de nos propres validateurs de champ. Mais la manière dont la vérification standard des données est effectuée peut, dans certains cas particuliers, ne pas nous convenir. Dans cette situation, il est judicieux d'écrire votre propre code de validation de formulaire.



Validation de formulaire personnalisé



Parlons de la façon de créer votre propre système de validation de formulaire.



Incluons un product-reviewtableau pour stocker les messages d'erreur dans les données du composant . Appelons ça errors:



data() {
  return {
    name: null,
    review: null,
    rating: null,
    errors: []
  }
}


Nous aimerions ajouter à ce tableau des informations sur les erreurs qui se produisent dans les situations où les champs de formulaire sont vides. Nous parlons du code suivant:



if(!this.name) this.errors.push("Name required.")
if(!this.review) this.errors.push("Review required.")
if(!this.rating) this.errors.push("Rating required.")


La première de ces lignes indique au système namede mettre errorsun message d'erreur dans le tableau si le champ est vide Name required. Les autres chaînes qui valident les champs reviewet fonctionnent de la même manière rating. Si l'un d'entre eux est vide, arrayun message d'erreur sera envoyé à la baie .



Où mettre ce code?



Puisque nous voulons que les messages d'erreur à écrire au tableau que lorsque, en essayant de soumettre le formulaire, il se trouve que les champs sont name, reviewou ne sont submitpas remplies, nous pouvons placer ce code dans la méthode onSubmit. De plus, nous réécrirons le code qui s'y trouve déjà, en y ajoutant quelques vérifications:



onSubmit() {
  if(this.name && this.review && this.rating) {
    let productReview = {
      name: this.name,
      review: this.review,
      rating: this.rating
    }
    this.$emit('review-submitted', productReview)
    this.name = null
    this.review = null
    this.rating = null
  } else {
    if(!this.name) this.errors.push("Name required.")
    if(!this.review) this.errors.push("Review required.")
    if(!this.rating) this.errors.push("Rating required.")
  }
}


Maintenant, nous vérifions les champs name, reviewet rating. S'il y a des données dans tous ces champs, nous créons un objet basé sur eux productReviewet l'envoyons au composant parent. Ensuite, les propriétés correspondantes sont réinitialisées.



Si au moins l'un des champs s'avère vide, nous mettons errorsun message d'erreur dans le tableau , en fonction de ce que l'utilisateur n'a pas entré avant de soumettre le formulaire.



Il ne reste plus qu'à afficher ces erreurs, ce qui peut être fait avec le code suivant:



<p v-if="errors.length">
  <b>Please correct the following error(s):</b>
  <ul>
    <li v-for="error in errors">{{ error }}</li>
  </ul>
</p>


Ici, une directive est utilisée v-ifavec laquelle nous vérifions le tableau errorspour la présence de messages d'erreur (en fait, nous analysons la longueur du tableau). S'il y a quelque chose dans le tableau, un élément est affiché <p>, qui, lorsqu'il est appliqué v-for, affiche une liste des erreurs du tableau errors.





Messages d'erreur



Nous avons maintenant notre propre système de validation de formulaire.



Utilisation du modificateur .number



Le modificateur .numberutilisé dans la directive v-modelpeut être très utile. Mais lors de son application, gardez à l'esprit qu'il y a un problème qui lui est associé. Si la valeur correspondante est vide, elle sera représentée sous forme de chaîne et non de nombre. Le livre de recettes Vue offre une solution à ce problème. Il consiste à convertir explicitement la valeur correspondante en un type numérique:



Number(this.myNumber)


Atelier



Ajoutez la question suivante au formulaire: "Recommanderiez-vous ce produit?" Faites en sorte que l'utilisateur puisse y répondre en utilisant les boutons radio «oui» et «non». Vérifiez la réponse à cette question et incluez les données pertinentes dans l'objet productReview.



  • Voici un modèle que vous pouvez utiliser pour résoudre ce problème.
  • Voici la solution au problème.


Résultat



Aujourd'hui, nous avons parlé de travailler avec des formulaires. Voici la chose la plus importante que vous ayez apprise aujourd'hui:



  • Vous pouvez utiliser la directive pour organiser la liaison de données bidirectionnelle pour former des éléments v-model.
  • Le modificateur .numberindique à Vue de convertir la valeur correspondante en un type numérique. Mais lorsque vous travaillez avec, il y a un problème lié au fait que les valeurs vides restent des chaînes.
  • Le modificateur d'événement .preventvous permet d'empêcher le rechargement de la page après l'envoi du formulaire.
  • Avec Vue, vous pouvez implémenter un mécanisme assez simple pour la validation de formulaire personnalisé.


Avez-vous fait vos devoirs aujourd'hui?



Vue.js pour les débutants Leçon 1: Instance de Vue

Vue.js pour les débutants, Leçon 2: Liaison d'attributs

Vue.js pour les débutants, Leçon 3: Rendu conditionnel

Vue.js pour les débutants, Leçon 4: Listes de rendu

Vue .js pour les débutants leçon 5: traitement des événements

Vue.js pour débutants leçon 6: lier les classes et les styles

Vue.js pour débutants leçon 7: propriétés calculées

Vue.js pour débutants leçon 8: composants

Vue. js pour les débutants leçon 9: événements personnalisés






All Articles