const detailsTemplate = `<div> <h2>Details</h2> <ul> <li v-for="detail in details">{{ detail }}</li> </ul> </div>`; const productTemplate = `<div class="product"> <div class="product-image"> <a :href="link"> <!-- bind the src attribute to the "image" property --> <img v-bind:src="image" :alt="description" :title="description" /><!-- :attr is shortcut for v-bind:attr --> </a> </div> <div class="product-info"> <h1 v-cloak>{{ title }}</h1> <h2>Available?</h2> <p v-cloak v-show="inStock">In stock</p> <p v-cloak v-show="!inStock">Out of stock</p> <p>Shipping: {{ shipping }}</p> <product-details :details="details"></product-details> <h2>Colors</h2> <ul> <li v-for="(variant, index) in variants" v-bind:key="variant.variantId" @mouseover="updateImage(index)" class="color-box" :style="{ backgroundColor: variant.variantColor }" /><!-- @ est le raccourci de v-on: --> </ul> <h2>Sizes</h2> <ul> <li v-for="size in sizes" :key="size">{{ size }}</li> </ul> <button v-on:click="addToCart" :disabled="!inStock" :class="{ disabledButton: !inStock }" >Add to cart</button> <div class="cart"> <p>Cart({{cart}})</p> </div> </div> </div> `; Vue.component("product-details", { props: { details: { type: Array, required: true, }, }, template: detailsTemplate, }); Vue.component("product", { props: { isPremium: { type: Boolean, required: true, } }, template: productTemplate, // Computer properties are cached until dependencies change. // => cheaper than methods. computed: { image() { const image = this.variants[this.selectedVariant].variantImage; return image; }, inStock() { return this.variants[this.selectedVariant].variantQuantity > 0; }, shipping() { if (this.isPremium) { return "Free"; } return "2.99 €"; }, title() { return [this.brand, this.product].join(' '); } }, data() { return { brand: "Vue Mastery", cart: 0, description: "Chaussettes montantes", details: [ "80% cotton", "20% polyester", "Gender-neutral", ], inventory: 15, link: "https://www.google.com/search?q=vuejs+socks", product: "Socks", selectedVariant: 0, sizes: [34, 36, 38, 40, 42, 44, 46], variants: [ { variantId: 2234, variantColor: "green", variantImage: "./assets/img/vmSocks-green-onWhite.jpg", variantQuantity: 10, }, { variantId: 2235, variantColor: "blue", variantImage: "./assets/img/vmSocks-blue-onWhite.png", variantQuantity: 0, }, ] } }, methods: { addToCart(mouseEvent) { if (this.variants[this.selectedVariant].variantQuantity < 0) { this.variants[this.selectedVariant].variantQuantity = 0; return; } this.variants[this.selectedVariant].variantQuantity--; this.cart++; if (this.variants[this.selectedVariant].variantQuantity <= 0) { this.variants[this.selectedVariant].variantQuantity = 0; } }, updateImage(index) { this.selectedVariant = index; } }, }); const app = new Vue({ el: "#app", data: { isPremium: false, } });