So, I have an app with multiple child components. Basically a spreadsheet.
I want to be able to calculate the sum of the components when any cell changes. I've figured out a way to store all the values of the cells by caching them when a change event is propagated. But, is this the best way? Is there a better way to dynamically grab the children? I understand props
are the way to send data down, but how do I pull data up?
This is the HTML:
<html>
<head>
</head>
<body>
<span id="calculator">
<template v-for="i in 5">
<cell v-bind:index="i" v-on:total="total"></cell>
</template>
{{ subtotal }}
{{ cells }}
</span>
<script src="vue.js"></script>
<script src="app.js"></script>
</body>
</html>
And the app.js:
Vue.component( 'cell', {
template: "<input v-model='value' v-on:change='total' size='10' type='text'/>",
props: {
index: Number
},
data: function() {
return {
value: 0
};
},
methods: {
total: function() {
console.log( "Value is now: " + this.value + " for index: " + this.index )
this.$emit( 'total', this.value, this.index )
}
}
});
var app = new Vue( {
data: {
subtotal: 0,
cells: []
},
el: "#calculator",
methods: {
total: function( value, indexPlusOne ) {
var index = indexPlusOne-1;
var v = parseInt( value );
Vue.set( this.cells, index, v);
console.log( "Inside the total function: " + v + " " + index );
this.subtotal = 0;
for( var i = 0; i < this.cells.length; i++ ) {
if( this.cells[i] ) {
this.subtotal += this.cells[i];
}
}
}
}
});
The best way is to use
v-model
for your customcell
component to pull data up.Ref: https://v2.vuejs.org/v2/guide/components.html#Form-Input-Components-using-Custom-Events
As explained in the link above,
<input v-model="something">
is a syntactic sugar for:So, your ideal solution would be like:
From within the cell component, you may pass value back to parent (root) component by:
this.$emit("input", newValue)
. The parent component (root) remains clean, and you may simply use a computed property forsubTotal
.But this will not work if you have a plain list of integers, like
this.cells = [1,2,3,4]
and attempt to pass the values to cell component usingv-model
. You will get the following error:If you are ok to modify your
this.cells
to array of objects, then you have a clean way of doing it like:Here is a working jsFiddle for this example: https://jsfiddle.net/mani04/9b7n3qmt/