Skip to content

Commit

Permalink
fix(VTreeview): correcly handle updating items array of equal size (#…
Browse files Browse the repository at this point in the history
…6202)

the VTreeview component did not handle updating items prop with an array
of equal size as current array.

fixes #6181
  • Loading branch information
nekosaur authored and johnleider committed Jan 18, 2019
1 parent 9d964b3 commit 4177931
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 6 deletions.
11 changes: 5 additions & 6 deletions packages/vuetify/src/components/VTreeview/VTreeview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import Themeable from '../../mixins/themeable'
import { provide as RegistrableProvide } from '../../mixins/registrable'

// Utils
import { getObjectValueByPath, deepEqual } from '../../util/helpers'
import { getObjectValueByPath, deepEqual, arrayDiff } from '../../util/helpers'
import mixins from '../../util/mixins'
import { consoleWarn } from '../../util/console'

Expand Down Expand Up @@ -79,14 +79,13 @@ export default mixins(
handler () {
const oldKeys = Object.keys(this.nodes).map(k => getObjectValueByPath(this.nodes[k].item, this.itemKey))
const newKeys = this.getKeys(this.items)
const diff = arrayDiff(newKeys, oldKeys)

// We only care if nodes are removed or added
if (oldKeys.length === newKeys.length) return
// We only want to do stuff if items have changed
if (!diff.length && newKeys.length < oldKeys.length) return

// If nodes are removed we need to clear them from this.nodes
if (oldKeys.length > newKeys.length) {
oldKeys.filter(k => !newKeys.includes(k)).forEach(k => delete this.nodes[k])
}
diff.forEach(k => delete this.nodes[k])

const oldSelectedCache = [...this.selectedCache]
this.selectedCache = new Set()
Expand Down
16 changes: 16 additions & 0 deletions packages/vuetify/src/util/helpers.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { test } from '@/test'
import { arrayDiff } from './helpers'

test('helpers.ts', () => {
describe('arrayDiff', () => {
it('should return set difference of arrays A and B', () => {

expect(arrayDiff(['one', 'two'], ['one'])).toEqual([])
expect(arrayDiff(['one'], ['one', 'two'])).toEqual(['two'])
expect(arrayDiff([], [])).toEqual([])
expect(arrayDiff([], ['one'])).toEqual(['one'])
expect(arrayDiff(['one'], ['two'])).toEqual(['two'])
expect(arrayDiff(['one', 'two'], ['one', 'three'])).toEqual(['three'])
})
})
})
11 changes: 11 additions & 0 deletions packages/vuetify/src/util/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -323,3 +323,14 @@ const camelizeRE = /-(\w)/g
export const camelize = (str: string): string => {
return str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : '')
}

/**
* Returns the set difference of B and A, i.e. the set of elements in B but not in A
*/
export function arrayDiff (a: any[], b: any[]): any[] {
const diff = []
for (let i = 0; i < b.length; i++) {
if (a.indexOf(b[i]) < 0) diff.push(b[i])
}
return diff
}
36 changes: 36 additions & 0 deletions packages/vuetify/test/unit/components/VTreeview/VTreeview.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -410,4 +410,40 @@ test('VTreeView.ts', ({ mount }) => {

expect(Object.keys(wrapper.vm.nodes).length).toBe(2)
})

it('should handle replacing items with new array of equal length', async () => {
const wrapper = mount(VTreeview, {
propsData: {
items: [
{
id: 1,
name: 'one'
},
{
id: 2,
name: 'two'
}
]
}
})

expect(wrapper.html()).toMatchSnapshot()

wrapper.setProps({
items: [
{
id: 1,
name: 'one'
},
{
id: 3,
name: 'three'
}
]
})

await wrapper.vm.$nextTick()

expect(wrapper.html()).toMatchSnapshot()
})
})
Original file line number Diff line number Diff line change
@@ -1,5 +1,55 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`VTreeView.ts should handle replacing items with new array of equal length 1`] = `
<div class="v-treeview theme--light">
<div class="v-treeview-node v-treeview-node--leaf">
<div class="v-treeview-node__root">
<div class="v-treeview-node__content">
<div class="v-treeview-node__label">
one
</div>
</div>
</div>
</div>
<div class="v-treeview-node v-treeview-node--leaf">
<div class="v-treeview-node__root">
<div class="v-treeview-node__content">
<div class="v-treeview-node__label">
two
</div>
</div>
</div>
</div>
</div>
`;

exports[`VTreeView.ts should handle replacing items with new array of equal length 2`] = `
<div class="v-treeview theme--light">
<div class="v-treeview-node v-treeview-node--leaf">
<div class="v-treeview-node__root">
<div class="v-treeview-node__content">
<div class="v-treeview-node__label">
one
</div>
</div>
</div>
</div>
<div class="v-treeview-node v-treeview-node--leaf">
<div class="v-treeview-node__root">
<div class="v-treeview-node__content">
<div class="v-treeview-node__label">
three
</div>
</div>
</div>
</div>
</div>
`;

exports[`VTreeView.ts should load children when expanding 1`] = `
<div class="v-treeview theme--light">
Expand Down

0 comments on commit 4177931

Please sign in to comment.