[Vuejs]-Change v-model value without changin the actual data

1πŸ‘

Can we have two versions of products? One for the server, one for v-models.

var server_products = [
    { id: 1, name: "Prod 1", stock: 5 },
    { id: 2, name: "Prod 2", stock: 6 }
]

//...

data: () => ({
    products = server_products
})
updateStock(stock, productId) {
  server_products.forEach((product) => {
      if(product.id === productId && stock !== product.stock){
        product.stock = stock
        // do ajax
      }
  })
},
//...

If not than you can use vue’s watch property so vue finds changes to the array for you.

//...
data: () => ({
    products: [
        { id: 1, name: "Prod 1", stock: 5 },
        { id: 2, name: "Prod 2", stock: 6 }
    ]
}),
watch: {
    'products': {
        handler: function(newValue) {
            // do ajax
        },
        deep: true
    }
}
//...

1πŸ‘

Personally this feels like a higher level question to which your flow of product editing needs tweaking. Here is what I can think of:

  1. User enters all the information.
  2. User hits submit button.
  3. Check whether of not the stock count is empty or 0.
  4. Return an error message if it is.
  5. Submit and update otherwise.

It might be worth looking into vuelidate that handles such validation in JavaScript. Meanwhile, we are also coming up with a tool called CRUDS DS (a WIP) that handles such situation with ease.

πŸ‘€CRUD DS

1πŸ‘

The best way is to create a ProductComponent and watch every product separately inside its own component, as shown below:

Product.vue

<ProductComponent 
   v-for="product in products" 
   :product="product" 
   :key="product.id" />

ProductComponent.vue

<template>
   <tr>
      <td>{{ product.name }}</td>
      <td>
          <input
            type="text"
            class="form-control"
            v-model="product.price"
            @paste.prevent
          />
        </td>
        <td>
            <input
            type="text"
            class="form-control"
            maxlength="999"
            v-model="product.stock"
            @paste.prevent
            @keypress="onlyNumber($event)"
            @blur="updateStock($event.target.value, product.id)"
          />
       </td>
   </tr>
</template>

<script>
export default {
  props: {
    product: {
      type: Object,
      default: {},
    },
  },

  data: () => ({ actual_stock: "" })
  
  // this is for handle stock cannot be empty or GTE:0
  // also you dont need handleInputStock anymore
  watch: {
     product: {
        handler(val) {
           this.actual_stock = val.stock;
        },
        immediate: true,
     },
     "product.stock": function (newVal, oldVal) {
        this.product.stock = +newVal;
     },
  },

  methods: {
     updateStock(stock, productId) {
        if (!(stock == this.actual_stock)) {
           // do ajax
        }
     }
  }
}
</script>

If you want to handle it on parent side, you may use $emit to send an event upwards.

πŸ‘€Aslam H

Leave a comment