Encountered an issue that I can easily resolve, but not sure how to handle it in the "vue way" or in a declarative manner. Typically, I resort to traditional DOM manipulation, which makes it challenging for me to follow Vue's recommended approach.
The issue arises with a two-product array where one product has only one item in stock. When added to the cart, it should not be possible to add it again. As we iterate over the array, an error message is displayed conditionally on each item due to the v-if
evaluation being true.
How can this be dealt with declaratively, rather than conventionally? Normally, I would pass in $event
, extract the current target, and use insertAdjacentHTML
. However, I'm unsure of how to achieve this declaratively when handling logic after receiving a response from an API.
<body>
<div id="app">
<div v-for="(product, index) in products" class="product__wrapper" style="position: relative; background: #ccc; margin: 24px;">
<p>{{ product.title }}</p>
<button @click="addToCart(product.id)">add to cart</button>
<div v-if="lastItemIsInCart" class="error">All items are currently in your cart</div>
</div>
</div>
<script type="module">
Vue.createApp({
name: 'test-app',
data() {
return {
products: [],
lastItemIsInCart: null
}
},
mounted() {
fetch('/products')
.then(res => res.json())
.then(data => {
this.products = data.products
})
},
methods: {
addToCart(productId) {
fetch(`/cart/add/${productId}`)
.then(res => res.json())
.then(data => {
// unique to this api
if (data.status !== 200) {
throw new Error(data.description)
}
})
.catch(err => {
console.error(err.message) // all xyz products are in your cart
// set this.lastItemIsInCart to true for a specific product so that v-if doesn't become true for each item in the list
})
}
}
}).mount('#app')
</script>
</body>