Last active
November 21, 2019 13:02
-
-
Save Alexisgt01/33a9a77c2a11d1b189433c00897644e9 to your computer and use it in GitHub Desktop.
[MODULES] Tabs page storage with Vue cli, Vuex, Vuetify & Vue Router
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<div> | |
<v-btn @click="addPage({ | |
name: 'Item', //Must be unique !! | |
route: '/item', | |
})"></v-btn> | |
</div> | |
</template> | |
<script> | |
import {mapActions} from 'vuex'; | |
export default { | |
name: 'vue', | |
methods: { | |
...mapActions('routes', [ | |
'addPage', | |
]) | |
} | |
}; | |
</script> | |
<style scoped></style> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import router from '@/routes' | |
/* eslint-disable no-console */ | |
const state = { | |
open: [], | |
}; | |
// getters | |
const getters = { | |
open: state => state.open, | |
}; | |
// actions | |
const actions = { | |
addPage: ({commit, state}, route) => { | |
let openned = state.open.find(o => o.name === route.name); | |
if (!openned) { | |
commit('ADD_PAGE', { | |
name: route.name, // must be unique !! | |
route: route.route, | |
}) | |
} | |
if (router.currentRoute.path !== route.route) { | |
router.push({path: route.route}) | |
} | |
}, | |
closePage: ({getters, commit}, name) => { | |
let allTab = getters.open; | |
let tabToClose = getters.open.find(o => o.name === name); | |
let tabToCloseIndex = allTab.indexOf(tabToClose); | |
if (tabToClose.route === router.currentRoute.path) { | |
if (tabToCloseIndex !== 0) { | |
if (allTab.length === tabToCloseIndex + 1) { | |
router.push({path: getters.open[tabToCloseIndex - 1].route}) | |
} else { | |
router.push({path: getters.open[tabToCloseIndex + 1].route}) | |
} | |
} else { | |
if (allTab.length !== 1) { | |
router.push({path: getters.open[tabToCloseIndex + 1].route}) | |
} else { | |
router.push({path: '/dashboard'}) | |
commit('ADD_PAGE', { | |
name: 'Dashboard', | |
route: '/dashboard', | |
}) | |
} | |
} | |
} | |
commit('CLOSE_PAGE', { | |
index: tabToCloseIndex, | |
}) | |
} | |
}; | |
// mutations | |
const mutations = { | |
ADD_PAGE: (state, route) => { | |
state.open.push({ | |
name: route.name, | |
route: route.route, | |
}) | |
}, | |
CLOSE_PAGE: (state, index) => { | |
state.open.splice(index.index, 1); | |
}, | |
}; | |
export default { | |
namespaced: true, | |
state, | |
getters, | |
actions, | |
mutations | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- ADD SOME SHORT CODE TO next/previous TAB --> | |
<!-- PLEASE ADD THIS LIB --> | |
<!-- https://github.com/jaywcjlove/hotkeys --> | |
<template> | |
<v-card class="custom-tabs" elevation="0"> | |
<v-tabs> | |
<v-tab v-for="(tab, n) in open" :key="n" :to="{ path: tab.route }"> | |
<v-icon @click.native.prevent="closePage(tab.name)" class="mr-2" size="12">fa fa-times</v-icon> | |
{{tab.name}} | |
</v-tab> | |
</v-tabs> | |
<v-divider></v-divider> | |
</v-card> | |
</template> | |
<script> | |
/* eslint-disable no-console */ | |
/* eslint-disable no-unused-vars */ | |
import {mapGetters, mapActions} from 'vuex' | |
import hotkeys from 'hotkeys-js'; | |
export default { | |
name: "tabs", | |
computed: { | |
/** | |
* Get open page | |
*/ | |
...mapGetters('routes', { | |
open: 'open', | |
}) | |
}, | |
created() { | |
let self = this; | |
/** | |
* Shortcode event "n" | |
* check the tab position relative to others and push accordingly to right | |
* @params {object} event - event emit | |
**/ | |
hotkeys('n', function (event) { | |
// Prevent the default refresh event under WINDOWS system | |
event.preventDefault(); | |
setTimeout(function () { | |
let allTab = self.open; | |
let countTab = self.open.length; | |
let currentRoute = self.$route.path; | |
let currentTab = allTab.find(o => o.route === currentRoute); | |
let currentIndex = allTab.indexOf(currentTab); | |
if (countTab - 1 !== currentIndex) { | |
let nextRoute = allTab[currentIndex + 1].route; | |
self.$router.push(nextRoute); | |
} | |
}, 80); | |
}); | |
/** | |
* Shortcode event "p" | |
* check the tab position relative to others and push accordingly to left | |
* @params {object} event - event emit | |
**/ | |
hotkeys('p', function (event) { | |
// Prevent the default refresh event under WINDOWS system | |
event.preventDefault(); | |
setTimeout(function () { | |
let allTab = self.open; | |
let countTab = self.open.length; | |
let currentRoute = self.$route.path; | |
let currentTab = allTab.find(o => o.route === currentRoute); | |
let currentIndex = allTab.indexOf(currentTab); | |
if (currentIndex !== 0 && countTab > 1) { | |
let previousRoute = allTab[currentIndex - 1].route; | |
self.$router.push(previousRoute); | |
} | |
}, 80); | |
}); | |
}, | |
methods: { | |
/** | |
* Close the selected tab | |
*/ | |
...mapActions('routes', [ | |
'closePage', | |
]) | |
} | |
} | |
</script> | |
<style scoped> | |
.custom-tabs { | |
left: 80px; | |
width: calc(100% - 80px); | |
} | |
</style> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<v-card> | |
<v-tabs background-color="deep-purple accent-4" center-active dark icons-and-text> | |
<v-tab v-for="(tab, n) in open" :key="n" :to="{ path: tab.route }"> | |
{{tab.name}} | |
<v-icon @click.native.prevent="closePage(tab.name)" size="12" right>fa fa-times</v-icon> | |
</v-tab> | |
</v-tabs> | |
</v-card> | |
</template> | |
<script> | |
import {mapGetters, mapActions} from 'vuex' | |
export default { | |
name: "tabs", | |
computed: { | |
...mapGetters('routes', { | |
open: 'open', | |
}) | |
}, | |
methods: { | |
...mapActions('routes', [ | |
'closePage', | |
]) | |
} | |
} | |
</script> | |
<style scoped> | |
</style> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment