Home > Blockchain >  How to create dynamic onclick elements in vuejs without repeating same value
How to create dynamic onclick elements in vuejs without repeating same value

Time:05-30

I am trying to create a form in vuejs, where a group of inputs can be append onclick. It works fine, but the problem is, All inputs return the same value. I am sharing an image here :

enter image description here

I am sharing my code from template :

<div  v-for="(input,k) in data.invoice_product" :key="k">
    <div >
         <div >
              <select  v-model="data.invoice_product.product_id" 
               @change="getProductCost">
                  <option v-for="(product, i) in products" :key="i" :value="product.id">{{ 
                  product.product_name }}</option>
               </select>
         </div>
         <div >
              <input type="text"  placeholder="Quantity" v- 
               model="data.invoice_product.quantity" @keyup="getProductCost">
         </div>
         <div >
              <input type="text"  placeholder="Total" v- 
              model="data.invoice_product.total">
         </div>
         <div >
              <span>
                   <i  @click="removeElement(k)" v-show="k || ( !k 
                   && data.invoice_product.length > 1)">Remove</i>
                   <i  @click="addElement(k)" v-show="k == 
                   data.invoice_product.length-1">Add fields</i>
              </span>
          </div>
     </div>
 </div>

from my script (I am excluding irrelevant code segments) :

export default {
data() {
    return {
        data : {
            customer_id : '',
            vat : ''
        },
        inputs: [{
               product_id : '',
               quantity : '',
               total : ''
        }],
        input: {
               product_id : '',
               quantity : '',
               total : ''
         },
        products : []
    }
},

methods : {
   getProductCost() {
       axios.get('/api/product-cost? 
     product_id=' this.item.product_id '&&quantity=' this.item.quantity, 
       this.data).then(response => {
           this.input.total = response.data
       })
    },
   addElement() {
       this.data.invoice_product.push({
            product_id : '',
            quantity : '',
            total : ''
       })
    },

    removeElement (index) {
       this.data.invoice_product.splice(index, 1)
    },
}

Input returns null if I use "input" instead :

enter image description here

CodePudding user response:

The problem is not providing correct data to v-model.

Here, you make an iteration, where you get "input" as an element.

<div  v-for="(input,k) in data.invoice_product" :key="k">

But here, you are providing "data.invoice_product" instead of "input".

<select  v-model="data.invoice_product.product_id" 
           @change="getProductCost">

Just change "data.invoice_product.product_id" to "input.product_id", and also do it for other inputs.

CodePudding user response:

You are already looping through data.invoice_product with this

<div  v-for="(input,k) in data.invoice_product"> .... </div>

so the v-model on your select tag should be

<select v-model="input.product_id"> .... </select>

instead of

<select v-model="data.invoice_product.product_id"> .... </select>

Similar case for your input tags for Quantity and Total.

So, the code in your template should be something like this:

<div  v-for="(input,k) in data.invoice_product" :key="k">
    <div >
         <div >
              <select  v-model="input.product_id" 
               @change="getProductCost">
                  <option v-for="(product, i) in products" :key="i" :value="product.id">{{ 
                  product.product_name }}</option>
               </select>
         </div>
         <div >
              <input type="text"  placeholder="Quantity" v- 
               model="input.quantity" @keyup="getProductCost">
         </div>
         <div >
              <input type="text"  placeholder="Total" v- 
              model="input.total">
         </div>
         <div >
              <span>
                   <i  @click="removeElement(k)" v-show="k || ( !k 
                   && data.invoice_product.length > 1)">Remove</i>
                   <i  @click="addElement(k)" v-show="k == 
                   data.invoice_product.length-1">Add fields</i>
              </span>
          </div>
     </div>
 </div>

[Updated]

Your scripts should be left as it was before:

export default {
data() {
    return {
        data : {
            customer_id : '',
            vat : '',
            invoice_product: [{
               product_id : '',
               quantity : '',
               total : ''
            }],
        },
    
        input: {
               product_id : '',
               quantity : '',
               total : ''
         },
        products : []
    }
},

methods : {
   addElement() {
       this.data.invoice_product.push(this.input)
    },

    removeElement (index) {
       this.data.invoice_product.splice(index, 1)
    },
}

  • Related