Vue.js untuk pemula, pelajaran 10: formulir

Hari ini, di Pelajaran 10 kursus Vue, kita akan membahas tentang cara bekerja dengan formulir. Formulir memungkinkan Anda mengumpulkan masukan pengguna. Selain itu, disini kita akan membahas validasi form, yaitu mengecek apa yang dimasukkan ke dalamnya.







Vue.js pemula pelajaran 1: contoh Vue

Vue.js untuk pemula, pelajaran 2: mengikat atribut

Vue.js pemula pelajaran 3: rendering bersyarat

Vue.js pemula pelajaran 4: daftar rendering

Vue .js untuk pemula pelajaran 5: pemrosesan acara

Vue.js pemula pelajaran 6: mengikat kelas dan gaya

Vue.js pemula pelajaran 7: properti yang dihitung

Pelajaran pemula Vue.js 8: komponen

Vue. js untuk pemula pelajaran 9: acara khusus



Tujuan pelajaran



Kami akan membuat formulir yang memungkinkan pengunjung situs untuk mengirimkan ulasan produk. Dalam hal ini, review hanya dapat dikirim jika semua isian formulir sudah diisi, yang harus diisi.



Kode awal



Inilah yang ada sekarang index.html:



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

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


Ini terlihat seperti ini 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);
    }
  }
})


Tugas



Kami membutuhkan pengunjung situs untuk dapat memberikan ulasan tentang produk, tetapi situs kami belum memiliki sarana untuk menerima data dari pengguna. Bentuk adalah sarana seperti itu.



Solusi dari masalah tersebut



Bagi kami, untuk menyelesaikan tugas di hadapan kami, kami perlu membuat formulir. Mari kita mulai dengan membuat komponen baru khusus untuk bekerja dengan formulir. Mari kita sebut komponen ini product-review. Nama ini dipilih karena komponen tersebut akan mendukung formulir untuk mengumpulkan review produk. Komponen product-reviewakan disarangkan di dalam komponen product.



Mari mendaftarkan komponen baru, mulai membentuk templatnya dan melengkapinya dengan beberapa data:



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


Seperti yang Anda lihat, ada sebuah elemen di template komponen <input>, dan ada properti di data komponen data, sementara itu kosong.



Bagaimana cara mengikat apa yang dimasukkan pengguna ke dalam bidang ke properti name?



Di pelajaran sebelumnya, kita membahas tentang data binding menggunakan arahan v-bind, tapi kemudian kita hanya membahas tentang pengikatan satu arah. Aliran data beralih dari properti yang menyimpan data ke kontrol yang membuatnya. Dan sekarang kita membutuhkan apa yang dimasukkan pengguna ke dalam bidang akan berada di properti yang namedisimpan dalam data komponen. Dengan kata lain, kami ingin aliran data diarahkan dari bidang input ke properti.



Direktif V-model



Arahan v-modelmemungkinkan pengorganisasian data mengikat dua arah. Dengan skema kerja ini, jika sesuatu yang baru muncul di bidang masukan, ini menyebabkan perubahan pada data. Dan, oleh karena itu, ketika data berubah, status kontrol yang menggunakan data ini diperbarui.



Mari tambahkan arahan ke bidang input v-modeldan ikat bidang ini ke properti namedari data komponen.



<input v-model="name">


Sekarang mari tambahkan kode formulir lengkap ke templat komponen:



<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>


Seperti yang Anda lihat, v-modelbidang input, textareadan dilengkapi dengan arahan select. Harap dicatat bahwa saat menyiapkan bidang select, pengubah digunakan .number(kami akan membicarakannya lebih detail di bawah). Ini memungkinkan Anda untuk mengubah data yang sesuai menjadi sebuah tipe Number, sementara itu biasanya direpresentasikan dalam sebuah string.



Mari tambahkan kumpulan data komponen dengan menambahkan ke dalamnya data yang terikat dengan kontrol yang dijelaskan di atas:



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


Di bagian atas Templat formulir, Anda bisa melihat bahwa saat formulir dikirim, metode disebut onSubmit. Kami akan segera membuat metode ini. Tapi pertama-tama, mari kita bicara tentang peran konstruksi .prevent.



Ini adalah pengubah acara. Ini mencegah halaman dimuat ulang setelah acara dimunculkan submit. Ada juga pengubah acara berguna lainnya . Benar, kami tidak akan membicarakannya.



Kami sekarang siap membuat metode onSubmit. Mari kita mulai dengan kode ini:



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


Seperti yang Anda lihat, metode ini membuat objek berdasarkan data yang dimasukkan oleh pengguna. Referensi ke sana ditulis ke variabel productReview. Di sini kita drop di nullnilai properti name, review, rating. Tapi pekerjaan itu belum selesai. Kami masih perlu mengirim ke suatu tempat productReview. Ke mana mengirim objek ini?



Masuk akal untuk menyimpan ulasan produk di tempat yang sama di mana data komponen disimpan product. Mengingat bahwa komponen tersebut product-reviewbersarang di dalam sebuah komponen product, kita dapat mengatakan bahwa itu product-reviewadalah anak dari komponen tersebut product. Seperti yang kita pelajari di pelajaran sebelumnya, Anda bisa menggunakan kejadian yang dihasilkan dengan mengirim data dari komponen anak ke komponen induk $emit.



Mari kita perbaiki metodenya 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
}


Sekarang kami membuat acara dengan nama review-submitteddan meneruskan objek yang baru dibuat di dalamnya productReview.



Selanjutnya, kita perlu mengatur mendengarkan acara ini dengan menempatkan yang productberikut di template :



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


Baris ini berbunyi seperti ini: "Ketika sebuah peristiwa terjadi review-submitted, metode addReviewkomponen perlu dijalankan product."



Berikut kode untuk metode ini:



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


Metode ini mengambil objek productReviewyang berasal dari metode onSubmit, dan kemudian meletakkannya ke dalam larik yang reviewsdisimpan dalam data komponen product. Tetapi belum ada larik seperti itu dalam data komponen ini. Jadi mari tambahkan di sana:



reviews: []


Hebat! Elemen formulir sekarang terikat ke data komponen product-review. Data ini digunakan untuk membuat objek productReview. Dan objek ini diteruskan, saat formulir dikirimkan, ke komponen product. Hasilnya, objek productReviewditambahkan ke larik reviews, yang disimpan dalam data komponen product.



Menampilkan review produk



Sekarang yang tersisa hanyalah menampilkan di halaman produk review yang ditinggalkan oleh pengunjung situs. Kami akan melakukan ini di komponen productdengan menempatkan kode yang sesuai di atas kode yang komponen product-reviewditempatkan di komponen 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>


Di sini kami membuat daftar ulasan menggunakan direktif v-fordan menampilkan data yang disimpan dalam objek reviewmenggunakan notasi titik. 



Di tag, <p>kami memeriksa apakah ada sesuatu dalam array reviews(dengan memeriksa panjangnya). Jika tidak ada dalam array, kami mencetak pesan There are no reviews yet.





Halaman formulir umpan balik



Validasi formulir



Formulir sering kali berisi bidang yang harus diisi sebelum mengirimkan formulir. Misalnya, kami tidak ingin pengguna mengirimkan ulasan dengan bidang teks ulasan kosong.



Beruntung bagi kami, HTML5 mendukung required. Penggunaannya terlihat seperti ini:



<input required >


Konstruksi seperti itu akan mengarah ke tampilan otomatis dari pesan kesalahan jika pengguna mencoba mengirimkan formulir di mana bidang yang diperlukan kosong.





Pesan kesalahan



Memiliki validator bidang formulir standar di browser sangat bagus, karena dapat membebaskan kita dari membuat validator bidang kita sendiri. Tetapi cara pemeriksaan data standar dilakukan mungkin, dalam beberapa kasus khusus, tidak cocok untuk kita. Dalam situasi ini, masuk akal untuk menulis kode validasi formulir Anda sendiri.



Validasi formulir kustom



Mari kita bicara tentang cara membuat sistem validasi formulir Anda sendiri.



Mari sertakan sebuah product-reviewarray untuk menyimpan pesan kesalahan ke dalam data komponen . Sebut saja errors:



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


Kami ingin menambahkan informasi larik ini tentang kesalahan yang terjadi dalam situasi di mana bidang formulir kosong. Kami berbicara tentang kode berikut:



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


Baris pertama memberi tahu sistem nameuntuk memasukkan errorspesan kesalahan ke dalam larik jika kolomnya kosong Name required. String lain yang memvalidasi bidang reviewdan berfungsi serupa rating. Jika ada yang kosong, arraypesan kesalahan akan dikirim ke array .



Di mana meletakkan kode ini?



Karena kita ingin pesan kesalahan ditulis ke larik hanya ketika, ketika mencoba mengirimkan formulir, ternyata isiannya name, reviewatau submittidak terisi, kita dapat menempatkan kode ini di metode onSubmit. Selain itu, kami akan menulis ulang kode yang sudah ada di dalamnya, menambahkan beberapa pemeriksaan ke dalamnya:



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.")
  }
}


Sekarang kami memeriksa bidang name, reviewdan rating. Jika ada data di semua bidang ini, kami membuat objek berdasarkan data tersebut productReviewdan mengirimkannya ke komponen induk. Kemudian properti terkait disetel ulang.



Jika setidaknya salah satu bidang ternyata kosong, kami menempatkan errorspesan kesalahan dalam larik , tergantung pada apa yang tidak dimasukkan pengguna sebelum mengirimkan formulir.



Yang tersisa hanyalah menampilkan kesalahan ini, yang dapat dilakukan dengan kode berikut:



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


Di sini direktif digunakan v-if, yang dengannya kita memeriksa errorskeberadaan pesan kesalahan di dalamnya (sebenarnya, kita menganalisis panjang array). Jika ada sesuatu di dalam larik, sebuah elemen akan ditampilkan <p>, yang bila diterapkan v-for, akan menampilkan daftar kesalahan dari larik errors.





Pesan Kesalahan



Kami sekarang memiliki sistem validasi formulir kami sendiri.



Menggunakan pengubah .number



Pengubah yang .numberdigunakan dalam direktif v-modelbisa sangat berguna. Namun saat mengaplikasikannya, perlu diingat bahwa ada satu masalah yang terkait dengannya. Jika nilai terkait kosong, itu akan direpresentasikan sebagai string, bukan angka. The Vue Buku Resep menawarkan solusi untuk masalah ini. Ini terdiri dalam secara eksplisit mengubah nilai yang sesuai menjadi tipe numerik:



Number(this.myNumber)


Bengkel



Tambahkan pertanyaan berikut ke formulir: "Apakah Anda akan merekomendasikan produk ini?" Buat agar pengguna dapat membalasnya menggunakan tombol radio ya dan tidak. Periksa jawaban atas pertanyaan ini dan masukkan data yang relevan ke dalam objek productReview.



  • Berikut adalah template yang dapat Anda gunakan untuk mengatasi masalah ini.
  • Inilah solusi untuk masalah tersebut.


Hasil



Hari ini kami berbicara tentang bekerja dengan formulir. Inilah hal terpenting yang telah Anda pelajari hari ini:



  • Anda dapat menggunakan arahan untuk mengatur pengikatan data dua arah ke elemen formulir v-model.
  • Pengubah .numbermemberitahu Vue untuk mentransmisikan nilai yang sesuai ke tipe numerik. Tetapi ketika mengerjakannya, ada satu masalah terkait dengan fakta bahwa nilai kosong tetap menjadi string.
  • Pengubah acara .preventmemungkinkan Anda untuk mencegah pemuatan ulang halaman setelah formulir dikirimkan.
  • Dengan Vue, Anda dapat menerapkan mekanisme yang cukup sederhana untuk validasi formulir kustom.


Apakah kamu mengerjakan PR hari ini?



Vue.js pemula pelajaran 1: contoh Vue

Vue.js untuk pemula, pelajaran 2: mengikat atribut

Vue.js pemula pelajaran 3: rendering bersyarat

Vue.js pemula pelajaran 4: daftar rendering

Vue .js untuk pemula pelajaran 5: pemrosesan acara

Vue.js pemula pelajaran 6: mengikat kelas dan gaya

Vue.js pemula pelajaran 7: properti yang dihitung

Pelajaran pemula Vue.js 8: komponen

Vue. js untuk pemula pelajaran 9: acara khusus






All Articles