Browse Source

Step 10: forms.

Frederic G. MARAND 4 years ago
parent
commit
89ce347fe5
2 changed files with 84 additions and 0 deletions
  1. 2 0
      .idea/.gitignore
  2. 82 0
      main.js

+ 2 - 0
.idea/.gitignore

@@ -1,2 +1,4 @@
 # Default ignored files
 /workspace.xml
+# Datasource local storage ignored files
+/dataSources/

+ 82 - 0
main.js

@@ -44,6 +44,19 @@ const productTemplate = `<div class="product">
         >Add to cart</button>
         <button v-on:click="removeFromCart">Remove</button>
       </div>
+
+    <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>{{ review.rating }}</p>
+          <p>{{ review.review }}</p>
+        </li>
+      </ul>
+    </div>
+    <product-review @review-submitted="addReview"></product-review>
     </div>
 `;
 
@@ -57,6 +70,71 @@ Vue.component("product-details", {
     template: detailsTemplate,
 });
 
+Vue.component("product-review", {
+    template: `
+        <form class="review-form" @submit.prevent="onSubmit">
+          <p v-if="errors.length">
+            <b>Please correct the following errror(s):</b>
+            <ul>
+              <li v-for="error in errors">{{ error }}</li>
+            </ul>
+          </p>
+
+          <p>
+            <label for="name">Name:</label>
+            <input id="name" v-model="name">
+          </p>
+          <p>
+            <label for="review">Review:</label>
+            <textarea id="review" v-model="review"></textarea>
+          </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>
+            <input type="submit" value="Submit">
+          </p>
+        </form>
+    `,
+    data() {
+        return {
+            name: null,
+            review: null,
+            rating: null,
+            errors: [],
+        }
+    },
+    methods: {
+        onSubmit(evt) {
+            this.errors = [];
+            if (this.name && this.review && this.rating) {
+                const productReview = {
+                    name: this.name,
+                    rating: this.rating,
+                    review: this.review,
+                };
+                this.$emit("review-submitted", productReview);
+                this.name = null;
+                this.rating = null;
+                this.review = null;
+            } else {
+                for (const field of ["name", "rating", "review"]) {
+                    if (!this[field]) {
+                        this.errors.push(`${field} required`);
+                    }
+                }
+            }
+        }
+    }
+});
+
 Vue.component("product", {
     props: {
         isPremium: {
@@ -97,6 +175,7 @@ Vue.component("product", {
             inventory: 15,
             link: "https://www.google.com/search?q=vuejs+socks",
             product: "Socks",
+            reviews: [],
             selectedVariant: 0,
             sizes: [34, 36, 38, 40, 42, 44, 46],
             variants: [
@@ -120,6 +199,9 @@ Vue.component("product", {
             this.variants[this.selectedVariant].variantQuantity--;
             this.$emit("add-to-cart", this.variants[this.selectedVariant].variantId);
         },
+        addReview(productReview) {
+            this.reviews.push(productReview);
+        },
         removeFromCart() {
             this.variants[this.selectedVariant].variantQuantity++;
             this.$emit("remove-from-cart", this.variants[this.selectedVariant].variantId);