I am new in vue.js and I am trying to add trash icon in each row inside table and activate it to delete row but it does not work , also how can I make the input of one cell as drop down menu or list inside the table rows. the below script is copied from tutorial https://smarttutorials.net/dynamically-add-or-remove-table-row-using-vuejs/ your help is highly appreciated
<!DOCTYPE html>
<html>
<head>
<title>Report Generation</title>
<meta charset = "UTF-8" />
</head>
<body>
<div id="app">
<table>
<thead>
<tr>
<th scope ="col">#</th>
<th scope ="col">Item No</th>
<th scope ="col text-right">Item Name</th>
<th scope ="col text-right">Price</th>
<th scope ="col text-right">Quntatiy</th>
<th scope ="col text-right">Total</th>
</tr>
</thead>
<tr v-for="(invoice_product, index) in invoice_products" :key="index">
<td scope="row" >
<i @click="deleteRow(index, invoice_product)"></i>
</td>
<td>
<input type="text" v-model="invoice_product.product_no" />
</td>
<td>
<input type="text" v-model= "invoice_product.product_no" />
</v-col>
</td>
<td>
<input type="number" min="0" step=".01" v-model="invoice_product.product_price" @change="calculateLineTotal(invoice_product)"
/>
</td>
<td>
<input type="number" min="0" step=".01" v-model="invoice_product.product_qty" @change="calculateLineTotal(invoice_product)"
/>
</td>
<td>
<input readonly type="number" min="0" step=".01" v-model="invoice_product.line_total" />
</td>
</tr>
</table>
<button type='button' @click="addNewRow">
<i ></i>
Add
</button>
<button @click="deleteRow">
<i ></i>
Delete
</button>
</template>
</div>
<script src= "js/vue.js"> </script>
<script>
var app = new Vue({
el: "#app",
data: {
invoice_products: [{
product_no: '',
product_name: '',
product_price: '',
product_qty: '',
line_total: 0
}]
},methods: {
deleteRow(index, invoice_product) {
var idx = this.invoice_products.indexOf(invoice_product);
console.log(idx, index);
this.invoice_products.splice(idx, 2);
},
addNewRow() {
this.invoice_products.push({
product_no: '',
product_name: '',
product_price: '',
product_qty: '',
line_total: 0
});
}
}
});
</script>
</body>
</html> ```
CodePudding user response:
Probably you should move your button inside v-for and don't forget about tbody tag
<table>
<thead>
<tr>
<th scope ="col">#</th>
<th scope ="col">Item No</th>
<th scope ="col text-right">Item Name</th>
<th scope ="col text-right">Price</th>
<th scope ="col text-right">Quntatiy</th>
<th scope ="col text-right">Total</th>
</tr>
</thead>
<tbody>
<tr v-for="(invoice_product, index) in invoice_products" :key="index">
<td scope="row" >
<i @click="deleteRow(index, invoice_product)"></i>
</td>
<td>
<input type="text" v-model="invoice_product.product_no" />
</td>
<td>
<input type="text" v-model= "invoice_product.product_no" />
</td>
<td>
<input type="number" min="0" step=".01" v-model="invoice_product.product_price" @change="calculateLineTotal(invoice_product)"
/>
</td>
<td>
<input type="number" min="0" step=".01" v-model="invoice_product.product_qty" @change="calculateLineTotal(invoice_product)"
/>
</td>
<td>
<input readonly type="number" min="0" step=".01" v-model="invoice_product.line_total" />
</td>
<td>
<button type='button' @click="addNewRow">
<i ></i>
Add
</button>
</td>
<td>
<button @click="deleteRow">
<i ></i>
Delete
</button>
</td>
</tr>
</tbody>
</table>
CodePudding user response:
Try like following snippet:
var app = new Vue({
el: "#app",
data() {
return {
invoice_products: [{
id: this.uniqueId(),
product_no: '',
product_name: '',
product_price: '',
product_qty: '',
line_total: 0
}]
}
},
methods: {
deleteRow(product) {
this.invoice_products = this.invoice_products.filter(p => p.id !== product.id)
},
addNewRow() {
const id = this.uniqueId()
this.invoice_products.push({
id,
product_no: '',
product_name: '',
product_price: '',
product_qty: '',
line_total: 0
});
},
calculateLineTotal(product) {
if (product.product_price && product.product_qty) {
product.line_total = product.product_price * product.product_qty
}
this.invoice_products = [
...this.invoice_products.map((item) =>
item.id !== product.id
? item
: {
...item,
...product,
}
),
];
},
uniqueId(length=16) {
return parseInt(Math.ceil(Math.random() * Date.now()).toPrecision(length).toString().replace(".", ""))
}
}
})
<link rel="stylesheet" href="https://pro.fontawesome.com/releases/v5.10.0/css/all.css" integrity="sha384-AYmEC3Yw5cVb3ZcuHtOA93w35dYTsvhLPVnYs9eStHfGJvOvKxVfELGroGkvsg p" crossorigin="anonymous"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<button type='button' @click="addNewRow">
<i ></i>
Add
</button>
<table>
<thead>
<tr>
<th scope ="col">#</th>
<th scope ="col">Item No</th>
<th scope ="col text-right">Item Name</th>
<th scope ="col text-right">Price</th>
<th scope ="col text-right">Quntatiy</th>
<th scope ="col text-right">Total</th>
</tr>
</thead>
<tr v-for="(invoice_product, index) in invoice_products" :key="index">
<td scope="row" >
<i @click="deleteRow(invoice_product)"></i>
</td>
<td>
<input type="text" v-model="invoice_product.product_no" />
</td>
<td>
<input type="text" v-model= "invoice_product.product_name" />
</td>
<td>
<input type="number" min="0" step=".01" v-model="invoice_product.product_price" @change="calculateLineTotal(invoice_product)"
/>
</td>
<td>
<input type="number" min="0" step=".01" v-model="invoice_product.product_qty" @change="calculateLineTotal(invoice_product)"
/>
</td>
<td>
<input readonly type="number" min="0" step=".01" v-model="invoice_product.line_total" />
</td>
</tr>
</table>
</div>