I’ve copied the Grid Component Example into a single-file component (Grid.vue
). Within that component, I’m not able to access the columns
prop. console.log(this.columns)
always prints: [__ob__: Observer]
to the log. Can someone tell me why? This works fine in their example on the page and in JSFiddle.
Here’s my Grid.vue
file:
<script> export default { name: 'grid', props: { data: Array, columns: Array, filterKey: String }, data: function() { var sortOrders = {} console.log(this.columns) this.columns.forEach((column) => { sortOrders[column] = 1 }); return { sortCol: '', sortOrders: sortOrders } }, computed: { filteredData: function () { var sortCol = this.sortCol var filterKey = this.filterKey && this.filterKey.toLowerCase() var order = this.sortOrders[sortCol] || 1 var data = this.data if (filterKey) { data = data.filter((row) => { return Object.keys(row).some((key) => { return String(row[key]).toLowerCase().indexOf(filterKey) > -1 }) }) } if (sortCol) { data = data.slice().sort((a, b) => { a = a[sortCol] b = b[sortCol] return (a === b ? 0 : a > b ? 1 : -1) * order }) } return data } }, filters: { capitalize: function (str) { return str.charAt(0).toUpperCase() + str.slice(1) } }, methods: { sortBy: function (key) { this.sortCol = key console.log(this.sortOrders[key]) this.sortOrders[key] = this.sortOrders[key] * -1 console.log(this.sortOrders[key]) } }, created() { }, mounted() { // var app = this }, } </script>
I’m using this component within another component like so:
<template> <div> <form id="search"> Search <input name="query" v-model="searchQuery"> </form> <grid :data="things" :columns="thingColumns" :filterKey="searchQuery"></grid> </div> </template> <script> import Grid from './Grid.vue'; export default { name: 'things-grid', data: function() { return { things: [], thingColumns: [], searchQuery: '' } }, mounted() { var app = this app.things = [ {id: 1, this: 'this 1', that: 'that 1', thing: 'thing 1'}, {id: 2, this: 'this 2', that: 'that 2', thing: 'thing 2'}, {id: 3, this: 'this 3', that: 'that 3', thing: 'thing 3'}, {id: 4, this: 'this 4', that: 'that 4', thing: 'thing 4'}, {id: 5, this: 'this 5', that: 'that 5', thing: 'thing 5'}, ] app.thingColumns = [ 'this', 'that', 'thing' ] app.searchQuery = '' }, components: { Grid } } </script>
Advertisement
Answer
In:
<grid :data="things" :columns="thingColumns" :filterKey="searchQuery"></grid>
The value of this.thingColumns
is passed as :columns
when mounting.
Thus, the console.log(this.columns)
inside Grid.vue/data()
prints when it is mounting.
And when it is mounting, thingColumns
is empty in the parent:
data: function() { return { things: [], thingColumns: [], // initially empty searchQuery: '' } }, mounted() { var app = this // ... app.thingColumns = [ // this code only runs after it is mounted 'this', 'that', 'thing' ] // ... },
Since the console.log(this.columns)
inside Grid.vue/data()
prints when it is mounting, that is, before it is mounted, it prints an empty array:
[__ob__: Observer] // this is an empty array, the __ob__ thing is related to Vue internals
Because, well, parent’s thingColumns
will only have data after the mounted()
hook executes.
And since it is a reactive array, when you update it, it will update the child grid
component as well.
Solution:
Move the property initalization code from mounted()
to created()
:
created() { // was mounted() var app = this // ... app.thingColumns = [ 'this', 'that', 'thing' ] // ... },
This will initialize the data sooner and make it available in time for the console.log()
in the child to pick it up.