199 lines
4.6 KiB
Vue
199 lines
4.6 KiB
Vue
<template>
|
|
<component
|
|
:is="baseComponent"
|
|
:to="link.path ? link.path : '/'"
|
|
class="nav-item"
|
|
:class="{ active: isActive }"
|
|
tag="li"
|
|
>
|
|
<a
|
|
v-if="isMenu"
|
|
class="sidebar-menu-item nav-link"
|
|
:class="{ active: isActive }"
|
|
:aria-expanded="!collapsed"
|
|
data-toggle="collapse"
|
|
@click.prevent="collapseMenu"
|
|
>
|
|
<template v-if="addLink">
|
|
<span class="nav-link-text">
|
|
{{ link.name }} <b class="caret"></b>
|
|
</span>
|
|
</template>
|
|
<template v-else>
|
|
<i :class="link.icon"></i>
|
|
<span class="nav-link-text">{{ link.name }} <b class="caret"></b></span>
|
|
</template>
|
|
</a>
|
|
|
|
<collapse-transition>
|
|
<div
|
|
v-if="$slots.default || this.isMenu"
|
|
v-show="!collapsed"
|
|
class="collapse show"
|
|
>
|
|
<ul class="nav nav-sm flex-column">
|
|
<slot></slot>
|
|
</ul>
|
|
</div>
|
|
</collapse-transition>
|
|
|
|
<slot
|
|
name="title"
|
|
v-if="children.length === 0 && !$slots.default && link.path"
|
|
>
|
|
<component
|
|
:to="link.path"
|
|
@click.native="linkClick"
|
|
:is="elementType(link, false)"
|
|
class="nav-link"
|
|
:class="{ active: link.active }"
|
|
:target="link.target"
|
|
:href="link.path"
|
|
>
|
|
<template v-if="addLink">
|
|
<span class="nav-link-text">{{ link.name }}</span>
|
|
</template>
|
|
<template v-else>
|
|
<i :class="link.icon"></i>
|
|
<span class="nav-link-text">{{ link.name }}</span>
|
|
</template>
|
|
</component>
|
|
</slot>
|
|
</component>
|
|
</template>
|
|
<script>
|
|
import { CollapseTransition } from 'vue2-transitions';
|
|
|
|
export default {
|
|
name: 'sidebar-item',
|
|
components: {
|
|
CollapseTransition
|
|
},
|
|
props: {
|
|
menu: {
|
|
type: Boolean,
|
|
default: false,
|
|
description:
|
|
"Whether the item is a menu. Most of the item it's not used and should be used only if you want to override the default behavior."
|
|
},
|
|
link: {
|
|
type: Object,
|
|
default: () => {
|
|
return {
|
|
name: '',
|
|
path: '',
|
|
children: []
|
|
};
|
|
},
|
|
description:
|
|
'Sidebar link. Can contain name, path, icon and other attributes. See examples for more info'
|
|
}
|
|
},
|
|
provide() {
|
|
return {
|
|
addLink: this.addChild,
|
|
removeLink: this.removeChild
|
|
};
|
|
},
|
|
inject: {
|
|
addLink: { default: null },
|
|
removeLink: { default: null },
|
|
autoClose: {
|
|
default: true
|
|
}
|
|
},
|
|
data() {
|
|
return {
|
|
children: [],
|
|
collapsed: true
|
|
};
|
|
},
|
|
computed: {
|
|
baseComponent() {
|
|
return this.isMenu || this.link.isRoute ? 'li' : 'router-link';
|
|
},
|
|
linkPrefix() {
|
|
if (this.link.name) {
|
|
let words = this.link.name.split(' ');
|
|
return words.map(word => word.substring(0, 1)).join('');
|
|
}
|
|
},
|
|
isMenu() {
|
|
return this.children.length > 0 || this.menu === true;
|
|
},
|
|
isActive() {
|
|
if (this.$route && this.$route.path) {
|
|
let matchingRoute = this.children.find(c =>
|
|
this.$route.path.startsWith(c.link.path)
|
|
);
|
|
if (matchingRoute !== undefined) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
},
|
|
methods: {
|
|
addChild(item) {
|
|
const index = this.$slots.default.indexOf(item.$vnode);
|
|
this.children.splice(index, 0, item);
|
|
},
|
|
removeChild(item) {
|
|
const tabs = this.children;
|
|
const index = tabs.indexOf(item);
|
|
tabs.splice(index, 1);
|
|
},
|
|
elementType(link, isParent = true) {
|
|
if (link.isRoute === false) {
|
|
return isParent ? 'li' : 'a';
|
|
} else {
|
|
return 'router-link';
|
|
}
|
|
},
|
|
linkAbbreviation(name) {
|
|
const matches = name.match(/\b(\w)/g);
|
|
return matches.join('');
|
|
},
|
|
linkClick() {
|
|
if (
|
|
this.autoClose &&
|
|
this.$sidebar &&
|
|
this.$sidebar.showSidebar === true
|
|
) {
|
|
this.$sidebar.displaySidebar(false);
|
|
}
|
|
},
|
|
collapseMenu() {
|
|
this.collapsed = !this.collapsed;
|
|
},
|
|
collapseSubMenu(link) {
|
|
link.collapsed = !link.collapsed;
|
|
}
|
|
},
|
|
mounted() {
|
|
if (this.addLink) {
|
|
this.addLink(this);
|
|
}
|
|
if (this.link.collapsed !== undefined) {
|
|
this.collapsed = this.link.collapsed;
|
|
}
|
|
if (this.isActive && this.isMenu) {
|
|
this.collapsed = false;
|
|
}
|
|
},
|
|
destroyed() {
|
|
if (this.$el && this.$el.parentNode) {
|
|
this.$el.parentNode.removeChild(this.$el);
|
|
}
|
|
if (this.removeLink) {
|
|
this.removeLink(this);
|
|
}
|
|
}
|
|
};
|
|
</script>
|
|
<style>
|
|
.sidebar-menu-item {
|
|
cursor: pointer;
|
|
}
|
|
</style>
|