Accessing Computed Property of Child Component in Vuejs | Arroba IT
Skip to content
vuejs datatables

Accessing Computed Property of Child Component in Vuejs

Nov 27, 2017

When coming from jQuery with its DataTables, you will wonder what to use in VueJS land. There are some implementations but none of them come close to it. In my opinion the best option so far is the DataTable from Spatie, its slick, fast and well documented and if you know Spatie, you can imagine that they are behind there stuff.

That beeing said, I am using it for a while and as the amount of rows in the current project grows, I needed a total of all rows in the footer. The Demopage shows an example with the sum of all songs. A bit too much for me as I just wanted to show the overall count of rows, but I got the idea: Just display the length of the array, which I passed to the component and voilá the footer showed the 30 items correctly.

But ... this only works until you have a filter like on the demo page; then 30 are still shown, even if you filtered the table to 10. You can see this on the demo page: Just type "Ringo" into the filter. The entries will be filtered to one row, but the total at the bottom will remain the same.

In the documentation of the package you can see that you can pass a `scope` to the footer template with the lines ... but this also contains only the original and not the filtered data.

Note: In VueJS 2.5 or above use slot-scope instead of scope.

After a peek in the code, I figured out that the component provides a computed property called displayedRows, which –  as the name already says – keeps the displayed rows or in other words, the filtered rows. How can I access this?

First, I added the ref property to the table component: table-component(ref="table"). This acts as a gateway to the internals of the table. With this.$refs.table.displayedRows.length I get the current amount of the filtered rows, which kind of worked. To proceed, you should keep in mind:

  1. it is not possible to access $refs in a computed property, because the child component might not be loaded at the time the computed property is built

  2. even 1) would not be true, using it in a computed property won't work because $refs is not reactive, meaning it will stay with the initial value forever

  3. And because of 2) you can not use it in mounted() and assign the value to a local data variable

What about a watcher, you may asked. Yeah, close, but a normal watcher won't work, because $refs may undefined when mounted, as already mentioned. So, how can I watch it as soon it is mounted? Lets have a look of the final code:

2 <table-component
3 :data="[
4 { firstName: 'John', birthday: '04/10/1940'},
5 { firstName: 'Paul', birthday: '18/06/1942'},
6 { firstName: 'George', birthday: '25/02/1943'},
7 { firstName: 'Ringo', birthday: '07/07/1940'},
8 ]"
9 sort-by="firstName"
10 sort-order="asc"
11 ref="table"
12 >
13 <table-column show="firstName" label="First name"></table-column>
14 <table-column show="birthday" label="Birthday" :filterable="false" data-type="date:DD/MM/YYYY"></table-column>
15 <template slot="tfoot">
16 <th>&nbsp;</th>
17 <th>Total: {{ sum }}</th>
18 </template>
19 </table-component>
22 // some code
23 data() {
24 return {
25 sum: 0,
26 }
27 },
29 mounted() {
30 this.$watch(() => this.$refs.table.displayedRows.length, (value) => { this.sum = value;})
31 },

Now the footer row shows the current filtered row count.