Reputation: 2031
I am learning Vue.
Now, I am trying to add data with the price and finally, it calculates total price:
Here is the HTML
<div id="app">
<form @submit.prevent="addItem">
<table border="1" cellpadding="10" width="300">
<tr>
<td colspan="2"><strong>Add New Item</strong></td>
</tr>
<tr>
<td>
<input type="text" name="" v-model="newItem" placeholder="Item Name">
</td>
<td>
<input type="number" name="" v-model="newItemPrice" placeholder="Item Price">
</td>
</tr>
</table>
</form>
<br>
<table border="1" cellpadding="10" width="400">
<tr>
<th>Item Name</th>
<th>Item Price</th>
</tr>
<tr v-for="(item, index) in items" :key="index">
<td>{{ item.name }}</td>
<td><input type="number" name="" v-model="item.price"></td>
<td><button @click="removeItem(index)">X</button></td>
</tr>
<tr>
<td>Total</td>
<td><strong>{{ total }}</strong></td>
</tr>
</table>
</div>
Here is the Vue Instance:
new Vue({
el : '#app',
data : {
items: [
{ name: 'Rice', price : 12.60 },
{ name: 'Oil', price : 22.00 },
{ name: 'Mango', price : 32.50 },
{ name: 'Orange', price : 42.00 },
],
newItem : '',
newItemPrice : '',
},
computed: {
total() {
var total = 0;
this.items.forEach( item => {
total += parseFloat( item.price );
})
return total;
}
},
methods: {
addItem() {
this.items.push({
name: this.newItem,
price: 0
});
},
removeItem( index ) {
this.items.splice( index, 1 )
}
}
});
You can see it's by default showing item name and price. I want to add new item using the v-model called newItem
But It's not adding the new item to the table
BUT
If I remove the Item Price column I mean this line:
<td>
<input type="number" name="" v-model="newItemPrice" placeholder="Item Price">
</td>
then it's adding the new item perfectly :(
can you tell me what's wrong here?
Upvotes: 1
Views: 384
Reputation: 73886
This happens because of browser implementation. As mentioned in W3C Specs:
When there is only one single-line text input field in a form, the user agent should accept Enter in that field as a request to submit the form.
But in case of multiple elements, the enter
keypress does not trigger the form submit and thus you get this behaviour.
To resolve this you can simply use @keyup.enter.prevent="addItem"
to listen to the enter
keypress on each input and call the addItem()
function like:
new Vue({
el: '#app',
data: {
items: [{name:"Rice",price:12.6},{name:"Oil",price:22},{name:"Mango",price:32.5},{name:"Orange",price:42}],
newItem: '',
newItemPrice: null,
},
computed: {
total() {
var total = 0;
this.items.forEach(item => {
total += parseFloat(item.price);
})
return total;
}
},
methods: {
addItem() {
this.items.push({
name: this.newItem,
price: 0
});
},
removeItem(index) {
this.items.splice(index, 1)
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet">
<div id="app">
<form @submit.prevent="addItem">
<table border="1" cellpadding="10" width="300">
<tr>
<td colspan="2"><strong>Add New Item</strong></td>
</tr>
<tr>
<td>
<input type="text" name="" v-model="newItem" placeholder="Item Name"
@keyup.enter.prevent="addItem">
</td>
<td>
<input type="number" name="" v-model="newItemPrice" placeholder="Item Price"
@keyup.enter.prevent="addItem">
</td>
</tr>
</table>
</form>
<br>
<table border="1" cellpadding="10" width="400">
<tr>
<th>Item Name</th>
<th>Item Price</th>
</tr>
<tr v-for="(item, index) in items" :key="index">
<td>{{ item.name }}</td>
<td><input type="number" name="" v-model="item.price"></td>
<td><button @click="removeItem(index)">X</button></td>
</tr>
<tr>
<td>Total</td>
<td><strong>{{ total }}</strong></td>
</tr>
</table>
</div>
Upvotes: 0
Reputation: 9491
See two issues with the fiddle:
After fixing both of them it works well in this fiddle.
Upvotes: 1
Reputation: 3270
You should put a new line in your form, my suggestion is to put just above the close form tag </form>
:
<input type="submit" value="add">
Another fix to do is in your methods addItem()
addItem() {
this.items.push({
name: this.newItem,
price: this.newItemPrice
});
}
Where it is the number 0
you should provide the this.newItemPrice
to it work properly.
Upvotes: 0