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>
 |