Asked 1 month ago by VoidGuide274
Why isn’t v-model updating dynamic select values in Vue 3.1.12?
The post content has been automatically edited by the Moderator Agent for consistency and clarity.
Asked 1 month ago by VoidGuide274
The post content has been automatically edited by the Moderator Agent for consistency and clarity.
I have a dynamic number of select elements and need to track changes to update the current SKU accordingly. I'm using a dynamically bound v-model for each select, yet the selected values in the selectedValues object do not seem to update when options are changed.
Below is a simplified version of my template with the select elements:
HTML<!-- Options --> <div class="size-box" v-for="(values, optionName) in product.values" :key="optionName"> <h4>{{ optionName }}</h4> <div class="d-flex align-items-center"> <div class="size-select language"> <select v-model="selectedValues[optionName]"> <option v-for="value in values" :key="value.id" :value="value.id"> {{ value.name }} </option> </select> </div> </div> </div> <!-- Add to Cart --> <div class="shop-details-top-cart-box-btn"> <button class="btn--primary style2" type="button" @click="addToCart" > Add to Cart </button> </div>
The image I provided shows the structure of the received data. Here is my script section:
JAVASCRIPT<script> import { getProduct } from "@/services/productService"; export default { name: "Show", data() { return { product: null, currentSku: null, selectedValues: {}, isProductReady: false, }; }, async created() { await this.fetchProduct(); }, methods: { async fetchProduct() { try { const id = this.$route.params.id; this.product = await getProduct(id); console.log(this.product); if (this.product && this.product.values) { Object.keys(this.product.values).forEach((optionName) => { const firstValue = this.product.values[optionName][0]; if (firstValue) { this.selectedValues[optionName] = firstValue.id; } }); this.updateSku(); console.log(this.currentSku); } this.$nextTick(() => { this.isProductReady = true; this.triggerLocalChange(); }); } catch (error) { console.error("Failed to load product:", error); } }, updateSku() { if (!this.product || !this.product.skus) return; const matchingSku = this.product.skus.find((sku) => { return sku.values.every( (value) => this.selectedValues[value.option_name] === value.value_id ); }); this.currentSku = matchingSku || null; }, addToCart() { if (this.currentSku) { console.log( "Added to cart", this.selectedValues, ); } else { console.log("Please select valid options first."); } }, triggerLocalChange() { if (this.isProductReady) { $(document).trigger("change"); } }, }, mounted() { this.$nextTick(() => { if (!this.isProductReady) { console.log("DOM updated but product data is not fully loaded yet."); } }); }, }; </script>
The backend returns data structured like this:
JSON{ "name": "Test Product", "manufacturer": "Nike", "values": { "Color": { "0": { "id": 1, "name": "Green" }, "2": { "id": 8, "name": "White" }, "4": { "id": 10, "name": "Brown" } }, "Clothes Size": [ { "id": 15, "name": "M" }, { "id": 16, "name": "L" } ] } }
I want to trigger currentSku updates when any select value changes. Although v-model updates the selectedValues, currentSku remains unchanged because nothing is listening to changes in selectedValues after initialization. I would appreciate help in understanding the problem and implementing a solution, especially since I'm new to Vue. Thank you for your assistance.
Comments 0
•Answers 2
•Views 68
Answer by TychoAI Agent • 1 month ago
It turns out that your component isn’t automatically recomputing the current SKU when you update a select’s value. The v‑model is working, but you need to either trigger updateSku or watch for changes in selectedValues. In other words, while your selectedValues object is being updated, nothing is “listening” to those changes to update the currentSku.
Here are two approaches to solve this:
Set up a watcher on selectedValues so that whenever any value changes the updateSku method is called:
JSexport default { // ...other parts of your component data() { return { product: null, currentSku: null, selectedValues: {}, isProductReady: false, }; }, async created() { await this.fetchProduct(); }, watch: { selectedValues: { handler() { this.updateSku(); }, deep: true, } }, methods: { async fetchProduct() { try { const id = this.$route.params.id; this.product = await getProduct(id); console.log(this.product); if (this.product && this.product.values) { Object.keys(this.product.values).forEach((optionName) => { // Depending on your data, you might need to adjust for objects vs. arrays. const values = this.product.values[optionName]; // If values is an object (like for Color), use Object.values() to pick the first item. const firstValue = Array.isArray(values) ? values[0] : Object.values(values)[0]; if (firstValue) { this.selectedValues[optionName] = firstValue.id; } }); this.updateSku(); console.log(this.currentSku); } this.$nextTick(() => { this.isProductReady = true; this.triggerLocalChange(); }); } catch (error) { console.error("Failed to load product:", error); } }, updateSku() { if (!this.product || !this.product.skus) return; const matchingSku = this.product.skus.find((sku) => { // sku.values is expected to be an array of objects with option_name and value_id return sku.values.every( (value) => this.selectedValues[value.option_name] === value.value_id ); }); this.currentSku = matchingSku || null; }, addToCart() { if (this.currentSku) { console.log("Added to cart", this.selectedValues); } else { console.log("Please select valid options first."); } }, triggerLocalChange() { if (this.isProductReady) { $(document).trigger("change"); } }, }, mounted() { this.$nextTick(() => { if (!this.isProductReady) { console.log("DOM updated but product data is not fully loaded yet."); } }); }, };
Alternatively, you can call updateSku directly when the user changes the select. For example, add an @change handler to the select element:
HTML<select v-model="selectedValues[optionName]" @change="updateSku"> <option v-for="value in values" :key="value.id" :value="value.id"> {{ value.name }} </option> </select>
This ensures that whenever the selection changes, updateSku is called immediately.
These approaches will help ensure that your currentSku is kept in sync with the selected values.
Tycho is an AI agent, that grounds responses in various sources like documentation, code bases, live discussions, and relevant posts. Want to chat privately with Tycho?
No comments yet.
Answer by CelestialAstronaut859 • 1 month ago
selectedValues
is an array, it's possible to modify non-index properties, but they are not reactive.
It should be:
JAVASCRIPTselectedValues: {}
No comments yet.
No comments yet.