169 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			169 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
| <template>
 | |
|   <div>
 | |
|     <div
 | |
|       :class="[
 | |
|         { 'col-md-4': vertical && !tabNavWrapperClasses },
 | |
|         { 'col-12': centered && !tabNavWrapperClasses },
 | |
|         tabNavWrapperClasses
 | |
|       ]"
 | |
|     >
 | |
|       <ul
 | |
|         class="nav nav-pills"
 | |
|         role="tablist"
 | |
|         :class="[
 | |
|           `nav-pills-${type}`,
 | |
|           { 'flex-column': vertical },
 | |
|           { 'justify-content-center': centered },
 | |
|           tabNavClasses
 | |
|         ]"
 | |
|       >
 | |
|         <li
 | |
|           v-for="tab in tabs"
 | |
|           class="nav-item active"
 | |
|           data-toggle="tab"
 | |
|           role="tablist"
 | |
|           aria-expanded="true"
 | |
|           :key="tab.id"
 | |
|         >
 | |
|           <a
 | |
|             data-toggle="tab"
 | |
|             role="tablist"
 | |
|             :href="`#${tab.id}`"
 | |
|             @click.prevent="activateTab(tab)"
 | |
|             :aria-expanded="tab.active"
 | |
|             class="nav-link"
 | |
|             :class="{ active: tab.active }"
 | |
|           >
 | |
|             <tab-item-content :tab="tab"> </tab-item-content>
 | |
|           </a>
 | |
|         </li>
 | |
|       </ul>
 | |
|     </div>
 | |
|     <div
 | |
|       class="tab-content"
 | |
|       :class="[
 | |
|         { 'tab-space': !vertical },
 | |
|         { 'col-md-8': vertical && !tabContentClasses },
 | |
|         tabContentClasses
 | |
|       ]"
 | |
|     >
 | |
|       <slot></slot>
 | |
|     </div>
 | |
|   </div>
 | |
| </template>
 | |
| 
 | |
| <script>
 | |
| export default {
 | |
|   name: 'tabs',
 | |
|   components: {
 | |
|     TabItemContent: {
 | |
|       props: ['tab'],
 | |
|       render(h) {
 | |
|         return h('div', [this.tab.$slots.title || this.tab.title]);
 | |
|       }
 | |
|     }
 | |
|   },
 | |
|   provide() {
 | |
|     return {
 | |
|       addTab: this.addTab,
 | |
|       removeTab: this.removeTab
 | |
|     };
 | |
|   },
 | |
|   props: {
 | |
|     type: {
 | |
|       type: String,
 | |
|       default: 'primary',
 | |
|       validator: value => {
 | |
|         let acceptedValues = [
 | |
|           'primary',
 | |
|           'info',
 | |
|           'success',
 | |
|           'warning',
 | |
|           'danger'
 | |
|         ];
 | |
|         return acceptedValues.indexOf(value) !== -1;
 | |
|       }
 | |
|     },
 | |
|     activeTab: {
 | |
|       type: String,
 | |
|       default: '',
 | |
|       description: 'Active tab name'
 | |
|     },
 | |
|     tabNavWrapperClasses: {
 | |
|       type: [String, Object],
 | |
|       default: '',
 | |
|       description: 'ul wrapper css classes'
 | |
|     },
 | |
|     tabNavClasses: {
 | |
|       type: [String, Object],
 | |
|       default: '',
 | |
|       description: 'ul css classes'
 | |
|     },
 | |
|     tabContentClasses: {
 | |
|       type: [String, Object],
 | |
|       default: '',
 | |
|       description: 'tab content css classes'
 | |
|     },
 | |
|     vertical: Boolean,
 | |
|     centered: Boolean,
 | |
|     value: String
 | |
|   },
 | |
|   data() {
 | |
|     return {
 | |
|       tabs: []
 | |
|     };
 | |
|   },
 | |
|   methods: {
 | |
|     findAndActivateTab(title) {
 | |
|       let tabToActivate = this.tabs.find(t => t.title === title);
 | |
|       if (tabToActivate) {
 | |
|         this.activateTab(tabToActivate);
 | |
|       }
 | |
|     },
 | |
|     activateTab(tab) {
 | |
|       if (this.handleClick) {
 | |
|         this.handleClick(tab);
 | |
|       }
 | |
|       this.deactivateTabs();
 | |
|       tab.active = true;
 | |
|     },
 | |
|     deactivateTabs() {
 | |
|       this.tabs.forEach(tab => {
 | |
|         tab.active = false;
 | |
|       });
 | |
|     },
 | |
|     addTab(tab) {
 | |
|       const index = this.$slots.default.indexOf(tab.$vnode);
 | |
|       if (!this.activeTab && index === 0) {
 | |
|         tab.active = true;
 | |
|       }
 | |
|       if (this.activeTab === tab.name) {
 | |
|         tab.active = true;
 | |
|       }
 | |
|       this.tabs.splice(index, 0, tab);
 | |
|     },
 | |
|     removeTab(tab) {
 | |
|       const tabs = this.tabs;
 | |
|       const index = tabs.indexOf(tab);
 | |
|       if (index > -1) {
 | |
|         tabs.splice(index, 1);
 | |
|       }
 | |
|     }
 | |
|   },
 | |
|   mounted() {
 | |
|     this.$nextTick(() => {
 | |
|       if (this.value) {
 | |
|         this.findAndActivateTab(this.value);
 | |
|       }
 | |
|     });
 | |
|   },
 | |
|   watch: {
 | |
|     value(newVal) {
 | |
|       this.findAndActivateTab(newVal);
 | |
|     }
 | |
|   }
 | |
| };
 | |
| </script>
 | |
| 
 | |
| <style scoped></style>
 |