I am trying to understand how to keep the state of the treeview after a page refresh.
For example, I have a treeview of folders. I click on a folder it should expand.
After that, I can click on that item inside the folder (is a link to a page, therefore the whole page is refreshed.)
The problem is the treeview closes the folders back up again and doesn't keep its previous state.
I need it to be static so even after page reload the treeview does not lose its state.
This bit of code is my treeview:
v-list.py-2(v-else, dense)
v-treeview(v-model="tree", :items="treeData", activatable, :open.sync="openIds", @update:open="getOpenIds", item-key="name", open-on-click)
template(v-slot:prepend="{item, open}")
v-list-item(v-if="item.isFolder", link, :href='`/` + item.locale + `/` + item.path', :input-value='path === item.path')
v-list-item-avatar(size="24", tile)
v-icon {{ open ? 'mdi-folder-open' : 'mdi-folder' }}
v-list-item-title {{item.title}}
v-list-item.noFolders(v-else, :href='`/` + item.locale + `/` + item.path', :key='`childpage-` + item.id', :input-value='path === item.path')
v-list-item-avatar(size="24", tile)
v-icon mdi-text-box
v-list-item-title {{item.title}}
Also, I should mention that the data is dynamic. I am generating the tree (as an Object) using a method.
async buildTree(items){
this.$store.commit(`loadingStart`, 'browse-load')
for(let item of items){
if(item.isFolder){
let result = await this.$apollo.query({
query: gql`
query ($parent: Int, $locale: String!) {
pages {
tree(parent: $parent, mode: ALL, locale: $locale) {
id
path
title
isFolder
pageId
parent
locale
}
}
}
`,
fetchPolicy: 'cache-first',
variables: {
parent: item.id,
locale: this.locale
}
})
item.children = _.get(result, 'data.pages.tree', [])
for(let kid of item.children){
if(item.isFolder){
//kid.name = ""
kid.children = []
}
}
this.buildTree(item.children)
console.log(this.treeData )
}
}
this.$store.commit(`loadingStop`, 'browse-load')
And that's actually the method that is supposed to save the tree state to the local storage.
getOpenIds(items){
const memory = JSON.stringify(items)
this.sessionIds = sessionStorage.setItem('items2', memory)
this.openIds = JSON.parse(sessionStorage.getItem('items2'))
console.log(this.openIds)
},
I have tried the suggestions but for some reason, the tree doesn't react to the local storage. IS there something to do with the fact that the method is async?
You can use one of these 2 possibilities below (there are probably more):
You can use localStorage to keep a record of all your folders' state.
Then you can add a computed property to get the data from the local storage if it exists and apply it inside your component.
Next time you can add a JSfiddle with your example so someone could provide you with a detailed solution :)
How to use: when someone clicks on a folder you should have a v-on:click handler where you store in local storage the new state
function onClickHandler(folderName: string, isOpen: boolean) {
localStorage.setItem(folderName, isOpen);
}
The next thing you should do is get the state for each folder from local storage and apply it - if it doesn't exist just return false.
function getFolderState(folderName: string) {
localStorage.getItem(folderName);
}
Apply it on the v-list-item element and make sure to pass in the same folder name for both functions.
There is a built-in feature in Vue that keeps your component alive instead of dismounting when it's removed from the DOM.
You can use the keep-alive element to wrap your component. It will result in keeping all the component's state when switching between screens.
<keep-alive>
<your-component />
</keep-alive>