I have a vue component which contains this table, which also has a component inside its only row:
<template>
<b-table :items="records">
<template slot="row-details">
<child-component/>
</template>
</b-table>
</template>
I'm keeping the data inside the table very simple, for sample purposes:
data() {
return {
records: [{
name: "Parent Row",
_showDetails: true
}]
};
}
The child-component
inside the row is quite simple too:
<template>
<div>
<p>{{number}}</p>
</div>
</template>
<script>
export default {
data() {
return {
number: Math.random(),
isUpdating: console.log("Updating Child Component")
};
},
}
</script>
If I add a new row in the parent table using records.push(newRow)
everything works fine, I can see the new row and, in the child component, number
does not change.
BUT If I add the new row using records.unshift(newRow)
the child component is reloaded, the "Updating child component" message shows and number
changes every time.
Is this the expected behaviour? How can I keep the number
so it does not change when I unshift a new record?
I have created a working sample here.
To minimize re-renders of child components in a b-table, and if your data has a field that is unique for every row (i.e. an ID or primary key), set the primary-key
prop to the name of the field that contains the unique row ID. This unique ID will be used as the Vue key
for each <tr>
element. Vue will then know if it needs to re-render the children or not.
Otherwise, what is happening is that b-table uses the row's index as the key. By pushing new rows on the table, the previous rows' Vue key
stays the same (and hence not re-rendered), but if you shift on the top of the rows, those that previously has indexes of 0
, 1
, 2
, etc have been replaced by new rows... and the entire table and it's contents (children) must be re-rendered.
EDIT/UPDATE:
I've discovered the root cause. The row-details
slot was always using the row's index as its :key
, and not incorporating the primary key value (if available). PR https://github.com/bootstrap-vue/bootstrap-vue/pull/4025 will fix this issue and will be available in the 2.0.0 stable release (being released today hopefully).
UPDATE 2:
BootstrapVue v2.0.0 stable has just been released (2019-09-06)