Fixed #1244 - Templating for Menus

pull/1281/head
Cagatay Civici 2021-05-17 14:58:53 +03:00
parent eb32efc9e1
commit d7c01c8f6e
33 changed files with 482 additions and 121 deletions

View File

@ -13,10 +13,18 @@ const BreadcrumbProps = [
} }
]; ];
const BreadcrumbSlots = [
{
name: "item",
description: "Template of a menuitem."
}
];
module.exports = { module.exports = {
breadcrumb: { breadcrumb: {
name: "Breadcrumb", name: "Breadcrumb",
description: "Breadcrumb provides contextual information about page hierarchy.", description: "Breadcrumb provides contextual information about page hierarchy.",
props: BreadcrumbProps props: BreadcrumbProps,
slots: BreadcrumbSlots
} }
}; };

View File

@ -31,10 +31,18 @@ const ContextMenuProps = [
} }
]; ];
const ContextMenuSlots = [
{
name: "item",
description: "Template of a menuitem."
}
];
module.exports = { module.exports = {
contextmenu: { contextmenu: {
name: "ContextMenu", name: "ContextMenu",
description: "ContextMenu displays an overlay menu on right click of its target.", description: "ContextMenu displays an overlay menu on right click of its target.",
props: ContextMenuProps props: ContextMenuProps,
slots: ContextMenuSlots
} }
}; };

View File

@ -13,10 +13,18 @@ const MegaMenuProps = [
} }
]; ];
const MegaMenuSlots = [
{
name: "item",
description: "Template of a menuitem."
}
];
module.exports = { module.exports = {
megamenu: { megamenu: {
name: "MegaMenu", name: "MegaMenu",
description: "MegaMenu is navigation component that displays submenus together.", description: "MegaMenu is navigation component that displays submenus together.",
props: MegaMenuProps props: MegaMenuProps,
slots: MegaMenuSlots
} }
}; };

View File

@ -31,10 +31,18 @@ const MenuProps = [
} }
]; ];
const MenuSlots = [
{
name: "item",
description: "Template of a menuitem."
}
];
module.exports = { module.exports = {
menu: { menu: {
name: "Menu", name: "Menu",
description: "Menu is a navigation / command component that supports dynamic and static positioning.", description: "Menu is a navigation / command component that supports dynamic and static positioning.",
props: MenuProps props: MenuProps,
slots: MenuSlots
} }
}; };

View File

@ -15,6 +15,10 @@ const MenubarSlots = [
{ {
name: "end", name: "end",
description: "Custom content after the content" description: "Custom content after the content"
},
{
name: "item",
description: "Template of a menuitem."
} }
]; ];

View File

@ -7,10 +7,18 @@ const PanelMenuProps = [
} }
]; ];
const PanelMenuSlots = [
{
name: "item",
description: "Template of a menuitem."
}
];
module.exports = { module.exports = {
panelmenu: { panelmenu: {
name: "PanelMenu", name: "PanelMenu",
description: "PanelMenu is a hybrid of Accordion and Tree components", description: "PanelMenu is a hybrid of Accordion and Tree components",
props: PanelMenuProps props: PanelMenuProps,
slots: PanelMenuSlots
} }
}; };

View File

@ -19,10 +19,18 @@ const StepsProps = [
} }
]; ];
const StepsSlots = [
{
name: "item",
description: "Template of a menuitem."
}
];
module.exports = { module.exports = {
steps: { steps: {
name: "steps", name: "steps",
description: "Steps components is an indicator for the steps in a wizard workflow.", description: "Steps components is an indicator for the steps in a wizard workflow.",
props: StepsProps props: StepsProps,
slots: StepsSlots
} }
}; };

View File

@ -13,10 +13,18 @@ const TabMenuProps = [
} }
]; ];
const TabMenuSlots = [
{
name: "item",
description: "Template of a menuitem."
}
];
module.exports = { module.exports = {
tabmenu: { tabmenu: {
name: "TabMenu", name: "TabMenu",
description: "TabMenu is a navigation component that displays items as tab headers.", description: "TabMenu is a navigation component that displays items as tab headers.",
props: TabMenuProps props: TabMenuProps,
slots: TabMenuSlots
} }
}; };

View File

@ -31,10 +31,18 @@ const TieredMenuProps = [
} }
]; ];
const TieredMenuSlots = [
{
name: "item",
description: "Template of a menuitem."
}
];
module.exports = { module.exports = {
tieredmenu: { tieredmenu: {
name: "TieredMenu", name: "TieredMenu",
description: "TieredMenu displays submenus in nested overlays.", description: "TieredMenu displays submenus in nested overlays.",
props: TieredMenuProps props: TieredMenuProps,
slots: TieredMenuSlots
} }
}; };

View File

@ -1,10 +1,10 @@
<template> <template>
<nav class="p-breadcrumb p-component" aria-label="Breadcrumb"> <nav class="p-breadcrumb p-component" aria-label="Breadcrumb">
<ul> <ul>
<BreadcrumbItem v-if="home" :item="home" class="p-breadcrumb-home" /> <BreadcrumbItem v-if="home" :item="home" class="p-breadcrumb-home" :template="$slots.item"/>
<template v-for="item of model" :key="item.label" > <template v-for="item of model" :key="item.label" >
<li class="p-breadcrumb-chevron pi pi-chevron-right"></li> <li class="p-breadcrumb-chevron pi pi-chevron-right"></li>
<BreadcrumbItem :item="item" /> <BreadcrumbItem :item="item" :template="$slots.item" />
</template> </template>
</ul> </ul>
</nav> </nav>

View File

@ -1,5 +1,6 @@
<template> <template>
<li :class="containerClass" v-if="visible()"> <li :class="containerClass" v-if="visible()">
<template v-if="!template">
<router-link v-if="item.to" :to="item.to" custom v-slot="{navigate, href}"> <router-link v-if="item.to" :to="item.to" custom v-slot="{navigate, href}">
<a :href="href" class="p-menuitem-link" @click="onClick($event, navigate)"> <a :href="href" class="p-menuitem-link" @click="onClick($event, navigate)">
<span v-if="item.icon" :class="iconClass"></span> <span v-if="item.icon" :class="iconClass"></span>
@ -10,6 +11,8 @@
<span v-if="item.icon" :class="iconClass"></span> <span v-if="item.icon" :class="iconClass"></span>
<span v-if="item.label" class="p-menuitem-text">{{item.label}}</span> <span v-if="item.label" class="p-menuitem-text">{{item.label}}</span>
</a> </a>
</template>
<component v-else :is="template" :item="item"></component>
</li> </li>
</template> </template>
@ -17,7 +20,8 @@
export default { export default {
name: 'BreadcrumbItem', name: 'BreadcrumbItem',
props: { props: {
item: null item: null,
template: null
}, },
methods: { methods: {
onClick(event, navigate) { onClick(event, navigate) {

View File

@ -2,7 +2,7 @@
<Teleport :to="appendTo"> <Teleport :to="appendTo">
<transition name="p-contextmenu" @enter="onEnter" @leave="onLeave" @after-leave="onAfterLeave"> <transition name="p-contextmenu" @enter="onEnter" @leave="onLeave" @after-leave="onAfterLeave">
<div :ref="containerRef" :class="containerClass" v-if="visible" v-bind="$attrs"> <div :ref="containerRef" :class="containerClass" v-if="visible" v-bind="$attrs">
<ContextMenuSub :model="model" :root="true" @leaf-click="onLeafClick" /> <ContextMenuSub :model="model" :root="true" @leaf-click="onLeafClick" :template="$slots.item"/>
</div> </div>
</transition> </transition>
</Teleport> </Teleport>

View File

@ -4,6 +4,7 @@
<template v-for="(item, i) of model" :key="item.label + i.toString()"> <template v-for="(item, i) of model" :key="item.label + i.toString()">
<li role="none" :class="getItemClass(item)" :style="item.style" v-if="visible(item) && !item.separator" <li role="none" :class="getItemClass(item)" :style="item.style" v-if="visible(item) && !item.separator"
@mouseenter="onItemMouseEnter($event, item)"> @mouseenter="onItemMouseEnter($event, item)">
<template v-if="!template">
<router-link v-if="item.to && !item.disabled" :to="item.to" custom v-slot="{navigate, href}"> <router-link v-if="item.to && !item.disabled" :to="item.to" custom v-slot="{navigate, href}">
<a :href="href" @click="onItemClick($event, item, navigate)" :class="getLinkClass(item)" v-ripple role="menuitem"> <a :href="href" @click="onItemClick($event, item, navigate)" :class="getLinkClass(item)" v-ripple role="menuitem">
<span :class="['p-menuitem-icon', item.icon]"></span> <span :class="['p-menuitem-icon', item.icon]"></span>
@ -16,7 +17,9 @@
<span class="p-menuitem-text">{{item.label}}</span> <span class="p-menuitem-text">{{item.label}}</span>
<span class="p-submenu-icon pi pi-angle-right" v-if="item.items"></span> <span class="p-submenu-icon pi pi-angle-right" v-if="item.items"></span>
</a> </a>
<ContextMenuSub :model="item.items" v-if="visible(item) && item.items" :key="item.label + '_sub_'" </template>
<component v-else :is="template" :item="item"></component>
<ContextMenuSub :model="item.items" v-if="visible(item) && item.items" :key="item.label + '_sub_'" :template="template"
@leaf-click="onLeafClick" :parentActive="item === activeItem" /> @leaf-click="onLeafClick" :parentActive="item === activeItem" />
</li> </li>
<li :class="['p-menu-separator', item.class]" :style="item.style" v-if="visible(item) && item.separator" :key="'separator' + i.toString()" role="separator"></li> <li :class="['p-menu-separator', item.class]" :style="item.style" v-if="visible(item) && item.separator" :key="'separator' + i.toString()" role="separator"></li>
@ -44,6 +47,10 @@ export default {
parentActive: { parentActive: {
type: Boolean, type: Boolean,
default: false default: false
},
template: {
type: Object,
default: null
} }
}, },
watch: { watch: {

View File

@ -4,6 +4,7 @@
<template v-for="(category,index) of model" :key="category.label + '_' + index"> <template v-for="(category,index) of model" :key="category.label + '_' + index">
<li v-if="visible(category)" :class="getCategoryClass(category)" :style="category.style" <li v-if="visible(category)" :class="getCategoryClass(category)" :style="category.style"
@mouseenter="onCategoryMouseEnter($event, category)" role="none"> @mouseenter="onCategoryMouseEnter($event, category)" role="none">
<template v-if="!$slots.item">
<router-link v-if="category.to && !category.disabled" :to="category.to" custom v-slot="{navigate, href}"> <router-link v-if="category.to && !category.disabled" :to="category.to" custom v-slot="{navigate, href}">
<a :href="href" :class="getLinkClass(category)" @click="onCategoryClick($event, category, navigate)" @keydown="onCategoryKeydown($event, category)" role="menuitem" v-ripple> <a :href="href" :class="getLinkClass(category)" @click="onCategoryClick($event, category, navigate)" @keydown="onCategoryKeydown($event, category)" role="menuitem" v-ripple>
<span v-if="category.icon" :class="getCategoryIcon(category)"></span> <span v-if="category.icon" :class="getCategoryIcon(category)"></span>
@ -16,6 +17,8 @@
<span class="p-menuitem-text">{{category.label}}</span> <span class="p-menuitem-text">{{category.label}}</span>
<span v-if="category.items" :class="getCategorySubMenuIcon()"></span> <span v-if="category.items" :class="getCategorySubMenuIcon()"></span>
</a> </a>
</template>
<component v-else :is="$slots.item" :item="item"></component>
<div class="p-megamenu-panel" v-if="category.items"> <div class="p-megamenu-panel" v-if="category.items">
<div class="p-megamenu-grid"> <div class="p-megamenu-grid">
<div v-for="(column,columnIndex) of category.items" :key="category.label + '_column_' + columnIndex" :class="getColumnClassName(category)"> <div v-for="(column,columnIndex) of category.items" :key="category.label + '_column_' + columnIndex" :class="getColumnClassName(category)">
@ -23,6 +26,7 @@
<li :class="getSubmenuHeaderClass(submenu)" :style="submenu.style" role="presentation">{{submenu.label}}</li> <li :class="getSubmenuHeaderClass(submenu)" :style="submenu.style" role="presentation">{{submenu.label}}</li>
<template v-for="(item, i) of submenu.items" :key="item.label + i.toString()"> <template v-for="(item, i) of submenu.items" :key="item.label + i.toString()">
<li role="none" :class="getSubmenuItemClass(item)" :style="item.style" v-if="visible(item) && !item.separator"> <li role="none" :class="getSubmenuItemClass(item)" :style="item.style" v-if="visible(item) && !item.separator">
<template v-if="!$slots.item">
<router-link v-if="item.to && !item.disabled" :to="item.to" custom v-slot="{navigate, href}"> <router-link v-if="item.to && !item.disabled" :to="item.to" custom v-slot="{navigate, href}">
<a :href="href" :class="getLinkClass(item)" @click="onLeafClick($event, item, navigate)" role="menuitem" v-ripple> <a :href="href" :class="getLinkClass(item)" @click="onLeafClick($event, item, navigate)" role="menuitem" v-ripple>
<span v-if="item.icon" :class="['p-menuitem-icon', item.icon]"></span> <span v-if="item.icon" :class="['p-menuitem-icon', item.icon]"></span>
@ -34,6 +38,8 @@
<span class="p-menuitem-text">{{item.label}}</span> <span class="p-menuitem-text">{{item.label}}</span>
<span :class="getSubmenuIcon()" v-if="item.items"></span> <span :class="getSubmenuIcon()" v-if="item.items"></span>
</a> </a>
</template>
<component v-else :is="$slots.item" :item="item"></component>
</li> </li>
<li :class="['p-menu-separator', item.class]" :style="item.style" v-if="visible(item) && item.separator" :key="'separator' + i.toString()" role="separator"></li> <li :class="['p-menu-separator', item.class]" :style="item.style" v-if="visible(item) && item.separator" :key="'separator' + i.toString()" role="separator"></li>
</template> </template>

View File

@ -5,14 +5,16 @@
<ul class="p-menu-list p-reset" role="menu"> <ul class="p-menu-list p-reset" role="menu">
<template v-for="(item, i) of model" :key="item.label + i.toString()"> <template v-for="(item, i) of model" :key="item.label + i.toString()">
<template v-if="item.items && visible(item) && !item.separator"> <template v-if="item.items && visible(item) && !item.separator">
<li class="p-submenu-header" v-if="item.items">{{item.label}}</li> <li class="p-submenu-header" v-if="item.items">
<slot name="item" :item="item">{{item.label}}</slot>
</li>
<template v-for="(child, j) of item.items" :key="child.label + i + j"> <template v-for="(child, j) of item.items" :key="child.label + i + j">
<Menuitem v-if="visible(child) && !child.separator" :item="child" @click="itemClick" /> <Menuitem v-if="visible(child) && !child.separator" :item="child" @click="itemClick" :template="$slots.item" />
<li v-else-if="visible(child) && child.separator" :class="['p-menu-separator', child.class]" :style="child.style" :key="'separator' + i + j" role="separator"></li> <li v-else-if="visible(child) && child.separator" :class="['p-menu-separator', child.class]" :style="child.style" :key="'separator' + i + j" role="separator"></li>
</template> </template>
</template> </template>
<li v-else-if="visible(item) && item.separator" :class="['p-menu-separator', item.class]" :style="item.style" :key="'separator' + i.toString()" role="separator"></li> <li v-else-if="visible(item) && item.separator" :class="['p-menu-separator', item.class]" :style="item.style" :key="'separator' + i.toString()" role="separator"></li>
<Menuitem v-else :key="item.label + i.toString()" :item="item" @click="itemClick" /> <Menuitem v-else :key="item.label + i.toString()" :item="item" @click="itemClick" :template="$slots.item" />
</template> </template>
</ul> </ul>
</div> </div>

View File

@ -1,5 +1,6 @@
<template> <template>
<li :class="containerClass" role="none" :style="item.style" v-if="visible()"> <li :class="containerClass" role="none" :style="item.style" v-if="visible()">
<template v-if="!template">
<router-link v-if="item.to && !item.disabled" :to="item.to" custom v-slot="{navigate, href}"> <router-link v-if="item.to && !item.disabled" :to="item.to" custom v-slot="{navigate, href}">
<a :href="href" @click="onClick($event, navigate)" :class="linkClass" v-ripple role="menuitem"> <a :href="href" @click="onClick($event, navigate)" :class="linkClass" v-ripple role="menuitem">
<span :class="['p-menuitem-icon', item.icon]"></span> <span :class="['p-menuitem-icon', item.icon]"></span>
@ -10,6 +11,8 @@
<span :class="['p-menuitem-icon', item.icon]"></span> <span :class="['p-menuitem-icon', item.icon]"></span>
<span class="p-menuitem-text">{{item.label}}</span> <span class="p-menuitem-text">{{item.label}}</span>
</a> </a>
</template>
<component v-else :is="template" :item="item"></component>
</li> </li>
</template> </template>
@ -21,7 +24,8 @@ export default {
inheritAttrs: false, inheritAttrs: false,
emits: ['click'], emits: ['click'],
props: { props: {
item: null item: null,
template: null
}, },
methods: { methods: {
onClick(event, navigate) { onClick(event, navigate) {

View File

@ -6,7 +6,7 @@
<a ref="menubutton" tabindex="0" class="p-menubar-button" @click="toggle($event)"> <a ref="menubutton" tabindex="0" class="p-menubar-button" @click="toggle($event)">
<i class="pi pi-bars" /> <i class="pi pi-bars" />
</a> </a>
<MenubarSub ref="rootmenu" :model="model" :root="true" :mobileActive="mobileActive" @leaf-click="onLeafClick"/> <MenubarSub ref="rootmenu" :model="model" :root="true" :mobileActive="mobileActive" @leaf-click="onLeafClick" :template="$slots.item"/>
<div class="p-menubar-end" v-if="$slots.end"> <div class="p-menubar-end" v-if="$slots.end">
<slot name="end"></slot> <slot name="end"></slot>
</div> </div>

View File

@ -3,6 +3,7 @@
<template v-for="(item, i) of model" :key="item.label + i.toString()"> <template v-for="(item, i) of model" :key="item.label + i.toString()">
<li role="none" :class="getItemClass(item)" :style="item.style" v-if="visible(item) && !item.separator" <li role="none" :class="getItemClass(item)" :style="item.style" v-if="visible(item) && !item.separator"
@mouseenter="onItemMouseEnter($event, item)"> @mouseenter="onItemMouseEnter($event, item)">
<template v-if="!template">
<router-link v-if="item.to && !item.disabled" :to="item.to" custom v-slot="{navigate, href}"> <router-link v-if="item.to && !item.disabled" :to="item.to" custom v-slot="{navigate, href}">
<a :href="href" @click="onItemClick($event, item, navigate)" :class="getLinkClass(item)" v-ripple @keydown="onItemKeyDown($event, item)" role="menuitem"> <a :href="href" @click="onItemClick($event, item, navigate)" :class="getLinkClass(item)" v-ripple @keydown="onItemKeyDown($event, item)" role="menuitem">
<span :class="['p-menuitem-icon', item.icon]"></span> <span :class="['p-menuitem-icon', item.icon]"></span>
@ -15,8 +16,10 @@
<span class="p-menuitem-text">{{item.label}}</span> <span class="p-menuitem-text">{{item.label}}</span>
<span :class="getSubmenuIcon()" v-if="item.items"></span> <span :class="getSubmenuIcon()" v-if="item.items"></span>
</a> </a>
</template>
<component v-else :is="template" :item="item"></component>
<MenubarSub :model="item.items" v-if="visible(item) && item.items" :key="item.label + '_sub_'" :mobileActive="mobileActive" <MenubarSub :model="item.items" v-if="visible(item) && item.items" :key="item.label + '_sub_'" :mobileActive="mobileActive"
@leaf-click="onLeafClick" @keydown-item="onChildItemKeyDown" :parentActive="item === activeItem" /> @leaf-click="onLeafClick" @keydown-item="onChildItemKeyDown" :parentActive="item === activeItem" :template="template" />
</li> </li>
<li :class="['p-menu-separator', item.class]" :style="item.style" v-if="visible(item) && item.separator" :key="'separator' + i.toString()" role="separator"></li> <li :class="['p-menu-separator', item.class]" :style="item.style" v-if="visible(item) && item.separator" :key="'separator' + i.toString()" role="separator"></li>
</template> </template>
@ -50,6 +53,10 @@ export default {
mobileActive: { mobileActive: {
type: Boolean, type: Boolean,
default: false default: false
},
template: {
type: Object,
default: null
} }
}, },
documentClickListener: null, documentClickListener: null,

View File

@ -3,6 +3,7 @@
<template v-for="(item, index) of model" :key="item.label + '_' + index"> <template v-for="(item, index) of model" :key="item.label + '_' + index">
<div v-if="visible(item)" :class="getPanelClass(item)" :style="item.style"> <div v-if="visible(item)" :class="getPanelClass(item)" :style="item.style">
<div :class="getHeaderClass(item)" :style="item.style"> <div :class="getHeaderClass(item)" :style="item.style">
<template v-if="!$slots.item">
<router-link v-if="item.to && !item.disabled" :to="item.to" custom v-slot="{navigate, href}"> <router-link v-if="item.to && !item.disabled" :to="item.to" custom v-slot="{navigate, href}">
<a :href="href" class="p-panelmenu-header-link" @click="onItemClick($event, item, navigate)" role="treeitem"> <a :href="href" class="p-panelmenu-header-link" @click="onItemClick($event, item, navigate)" role="treeitem">
<span v-if="item.icon" :class="getPanelIcon(item)"></span> <span v-if="item.icon" :class="getPanelIcon(item)"></span>
@ -15,12 +16,14 @@
<span v-if="item.icon" :class="getPanelIcon(item)"></span> <span v-if="item.icon" :class="getPanelIcon(item)"></span>
<span class="p-menuitem-text">{{item.label}}</span> <span class="p-menuitem-text">{{item.label}}</span>
</a> </a>
</template>
<component v-else :is="$slots.item" :item="item"></component>
</div> </div>
<transition name="p-toggleable-content"> <transition name="p-toggleable-content">
<div class="p-toggleable-content" v-show="item === activeItem" <div class="p-toggleable-content" v-show="item === activeItem"
role="region" :id="ariaId +'_content' " :aria-labelledby="ariaId +'_header'"> role="region" :id="ariaId +'_content' " :aria-labelledby="ariaId +'_header'">
<div class="p-panelmenu-content" v-if="item.items"> <div class="p-panelmenu-content" v-if="item.items">
<PanelMenuSub :model="item.items" class="p-panelmenu-root-submenu" /> <PanelMenuSub :model="item.items" class="p-panelmenu-root-submenu" :template="$slots.item" />
</div> </div>
</div> </div>
</transition> </transition>

View File

@ -2,6 +2,7 @@
<ul class="p-submenu-list" role="tree"> <ul class="p-submenu-list" role="tree">
<template v-for="(item, i) of model" :key="item.label + i.toString()"> <template v-for="(item, i) of model" :key="item.label + i.toString()">
<li role="none" :class="getItemClass(item)" :style="item.style" v-if="visible(item) && !item.separator"> <li role="none" :class="getItemClass(item)" :style="item.style" v-if="visible(item) && !item.separator">
<template v-if="!template">
<router-link v-if="item.to && !item.disabled" :to="item.to" custom v-slot="{navigate, href}"> <router-link v-if="item.to && !item.disabled" :to="item.to" custom v-slot="{navigate, href}">
<a :href="href" :class="getLinkClass(item)" @click="onItemClick($event, item, navigate)" role="treeitem" :aria-expanded="isActive(item)"> <a :href="href" :class="getLinkClass(item)" @click="onItemClick($event, item, navigate)" role="treeitem" :aria-expanded="isActive(item)">
<span :class="['p-menuitem-icon', item.icon]"></span> <span :class="['p-menuitem-icon', item.icon]"></span>
@ -14,9 +15,11 @@
<span :class="['p-menuitem-icon', item.icon]"></span> <span :class="['p-menuitem-icon', item.icon]"></span>
<span class="p-menuitem-text">{{item.label}}</span> <span class="p-menuitem-text">{{item.label}}</span>
</a> </a>
</template>
<component v-else :is="template" :item="item"></component>
<transition name="p-toggleable-content"> <transition name="p-toggleable-content">
<div class="p-toggleable-content" v-show="item === activeItem"> <div class="p-toggleable-content" v-show="item === activeItem">
<PanelMenuSub :model="item.items" v-if="visible(item) && item.items" :key="item.label + '_sub_'" /> <PanelMenuSub :model="item.items" v-if="visible(item) && item.items" :key="item.label + '_sub_'" :template="template" />
</div> </div>
</transition> </transition>
</li> </li>
@ -32,6 +35,10 @@ export default {
model: { model: {
type: null, type: null,
default: null default: null
},
template: {
type: Object,
default: null
} }
}, },
data() { data() {

View File

@ -3,6 +3,7 @@
<ul role="tablist"> <ul role="tablist">
<template v-for="(item,index) of model" :key="item.to"> <template v-for="(item,index) of model" :key="item.to">
<li v-if="visible(item)" :class="getItemClass(item)" :style="item.style" role="tab" :aria-selected="isActive(item)" :aria-expanded="isActive(item)"> <li v-if="visible(item)" :class="getItemClass(item)" :style="item.style" role="tab" :aria-selected="isActive(item)" :aria-expanded="isActive(item)">
<template v-if="!$slots.item">
<router-link :to="item.to" v-if="!isItemDisabled(item)" custom v-slot="{navigate, href}"> <router-link :to="item.to" v-if="!isItemDisabled(item)" custom v-slot="{navigate, href}">
<a :href="href" class="p-menuitem-link" @click="onItemClick($event, item, navigate)" role="presentation"> <a :href="href" class="p-menuitem-link" @click="onItemClick($event, item, navigate)" role="presentation">
<span class="p-steps-number">{{index + 1}}</span> <span class="p-steps-number">{{index + 1}}</span>
@ -13,6 +14,8 @@
<span class="p-steps-number">{{index + 1}}</span> <span class="p-steps-number">{{index + 1}}</span>
<span class="p-steps-title">{{item.label}}</span> <span class="p-steps-title">{{item.label}}</span>
</span> </span>
</template>
<component v-else :is="$slots.item" :item="item"></component>
</li> </li>
</template> </template>
</ul> </ul>

View File

@ -4,17 +4,23 @@
<template v-for="(item,i) of model" :key="item.label + '_' + i.toString()"> <template v-for="(item,i) of model" :key="item.label + '_' + i.toString()">
<router-link v-if="item.to && !item.disabled" :to="item.to" custom v-slot="{navigate, href, isActive, isExactActive}"> <router-link v-if="item.to && !item.disabled" :to="item.to" custom v-slot="{navigate, href, isActive, isExactActive}">
<li :class="getRouteItemClass(item,isActive,isExactActive)" :style="item.style" v-if="visible(item)" role="tab"> <li :class="getRouteItemClass(item,isActive,isExactActive)" :style="item.style" v-if="visible(item)" role="tab">
<template v-if="!$slots.item">
<a :href="href" class="p-menuitem-link" @click="onItemClick($event, item, navigate)" role="presentation" v-ripple> <a :href="href" class="p-menuitem-link" @click="onItemClick($event, item, navigate)" role="presentation" v-ripple>
<span :class="getItemIcon(item)" v-if="item.icon"></span> <span :class="getItemIcon(item)" v-if="item.icon"></span>
<span class="p-menuitem-text">{{item.label}}</span> <span class="p-menuitem-text">{{item.label}}</span>
</a> </a>
</template>
<component v-else :is="$slots.item" :item="item"></component>
</li> </li>
</router-link> </router-link>
<li v-else-if="visible(item)" :class="getItemClass(item)" role="tab"> <li v-else-if="visible(item)" :class="getItemClass(item)" role="tab">
<template v-if="!$slots.item">
<a :href="item.url" class="p-menuitem-link" :target="item.target" @click="onItemClick($event, item)" role="presentation" :tabindex="item.disabled ? null : '0'" v-ripple> <a :href="item.url" class="p-menuitem-link" :target="item.target" @click="onItemClick($event, item)" role="presentation" :tabindex="item.disabled ? null : '0'" v-ripple>
<span :class="getItemIcon(item)" v-if="item.icon"></span> <span :class="getItemIcon(item)" v-if="item.icon"></span>
<span class="p-menuitem-text">{{item.label}}</span> <span class="p-menuitem-text">{{item.label}}</span>
</a> </a>
</template>
<component v-else :is="$slots.item" :item="item"></component>
</li> </li>
</template> </template>
<li ref="inkbar" class="p-tabmenu-ink-bar"></li> <li ref="inkbar" class="p-tabmenu-ink-bar"></li>
@ -38,15 +44,19 @@ export default {
default: true default: true
} }
}, },
timeout: null,
mounted() { mounted() {
this.updateInkBar(); this.updateInkBar();
}, },
updated() { updated() {
this.updateInkBar(); this.updateInkBar();
}, },
beforeUnmount() {
clearTimeout(this.timeout);
},
watch: { watch: {
$route() { $route() {
setTimeout(() => this.updateInkBar(), 50); this.timeout = setTimeout(() => this.updateInkBar(), 50);
} }
}, },
methods: { methods: {

View File

@ -2,7 +2,7 @@
<Teleport :to="appendTo" :disabled="!popup"> <Teleport :to="appendTo" :disabled="!popup">
<transition name="p-connected-overlay" @enter="onEnter" @leave="onLeave" @after-leave="onAfterLeave"> <transition name="p-connected-overlay" @enter="onEnter" @leave="onLeave" @after-leave="onAfterLeave">
<div :ref="containerRef" :class="containerClass" v-if="popup ? visible : true" v-bind="$attrs" @click="onOverlayClick"> <div :ref="containerRef" :class="containerClass" v-if="popup ? visible : true" v-bind="$attrs" @click="onOverlayClick">
<TieredMenuSub :model="model" :root="true" :popup="popup" @leaf-click="onLeafClick"/> <TieredMenuSub :model="model" :root="true" :popup="popup" @leaf-click="onLeafClick" :template="$slots.item" />
</div> </div>
</transition> </transition>
</Teleport> </Teleport>

View File

@ -3,6 +3,7 @@
<template v-for="(item, i) of model" :key="item.label + i.toString()"> <template v-for="(item, i) of model" :key="item.label + i.toString()">
<li :class="getItemClass(item)" :style="item.style" v-if="visible(item) && !item.separator" <li :class="getItemClass(item)" :style="item.style" v-if="visible(item) && !item.separator"
@mouseenter="onItemMouseEnter($event, item)" role="none"> @mouseenter="onItemMouseEnter($event, item)" role="none">
<template v-if="!template">
<router-link v-if="item.to && !item.disabled" :to="item.to" custom v-slot="{navigate, href}"> <router-link v-if="item.to && !item.disabled" :to="item.to" custom v-slot="{navigate, href}">
<a :href="href" @click="onItemClick($event, item, navigate)" :class="getLinkClass(item)" v-ripple @keydown="onItemKeyDown($event, item)" role="menuitem"> <a :href="href" @click="onItemClick($event, item, navigate)" :class="getLinkClass(item)" v-ripple @keydown="onItemKeyDown($event, item)" role="menuitem">
<span :class="['p-menuitem-icon', item.icon]"></span> <span :class="['p-menuitem-icon', item.icon]"></span>
@ -15,7 +16,9 @@
<span class="p-menuitem-text">{{item.label}}</span> <span class="p-menuitem-text">{{item.label}}</span>
<span class="p-submenu-icon pi pi-angle-right" v-if="item.items"></span> <span class="p-submenu-icon pi pi-angle-right" v-if="item.items"></span>
</a> </a>
<TieredMenuSub :model="item.items" v-if="visible(item) && item.items" :key="item.label + '_sub_'" </template>
<component v-else :is="template" :item="item"></component>
<TieredMenuSub :model="item.items" v-if="visible(item) && item.items" :key="item.label + '_sub_'" :template="template"
@leaf-click="onLeafClick" @keydown-item="onChildItemKeyDown" :parentActive="item === activeItem" /> @leaf-click="onLeafClick" @keydown-item="onChildItemKeyDown" :parentActive="item === activeItem" />
</li> </li>
<li :class="['p-menu-separator', item.class]" :style="item.style" v-if="visible(item) && item.separator" :key="'separator' + i.toString()" role="separator"></li> <li :class="['p-menu-separator', item.class]" :style="item.style" v-if="visible(item) && item.separator" :key="'separator' + i.toString()" role="separator"></li>
@ -46,6 +49,10 @@ export default {
parentActive: { parentActive: {
type: Boolean, type: Boolean,
default: false default: false
},
template: {
type: Object,
default: null
} }
}, },
documentClickListener: null, documentClickListener: null,

View File

@ -32,6 +32,17 @@ export default {
} }
} }
</code></pre>
<h5>Templating</h5>
<p>Breadcrumb offers content customization with the <i>item</i> template that receives the menuitem instance from the model as a parameter.</p>
<pre v-code><code><template v-pre>
&lt;Breadcrumb :home="home" :model="items"&gt;
&lt;template #item="{item}"&gt;
&lt;a :href="item.url"&gt;{{item.label}}&lt;/a&gt;
&lt;/template&gt;
&lt;/Breadcrumb&gt;
</template>
</code></pre> </code></pre>
<h5>Properties</h5> <h5>Properties</h5>
@ -63,6 +74,24 @@ export default {
</table> </table>
</div> </div>
<h5>Slots</h5>
<div class="doc-tablewrapper">
<table class="doc-table">
<thead>
<tr>
<th>Name</th>
<th>Parameters</th>
</tr>
</thead>
<tbody>
<tr>
<td>item</td>
<td>item: Menuitem instance</td>
</tr>
</tbody>
</table>
</div>
<h5>Styling</h5> <h5>Styling</h5>
<p>Following is the list of structural style classes, for theming classes visit <router-link to="/theming">theming</router-link> page.</p> <p>Following is the list of structural style classes, for theming classes visit <router-link to="/theming">theming</router-link> page.</p>
<div class="doc-tablewrapper"> <div class="doc-tablewrapper">

View File

@ -183,6 +183,17 @@ export default {
} }
} }
</code></pre>
<h5>Templating</h5>
<p>ContextMenu offers content customization with the <i>item</i> template that receives the menuitem instance from the model as a parameter.</p>
<pre v-code><code><template v-pre>
&lt;ContextMenu :model="items"&gt;
&lt;template #item="{item}"&gt;
&lt;a :href="item.url"&gt;{{item.label}}&lt;/a&gt;
&lt;/template&gt;
&lt;/ContextMenu&gt;
</template>
</code></pre> </code></pre>
<h5>Properties</h5> <h5>Properties</h5>
@ -262,6 +273,24 @@ export default {
</table> </table>
</div> </div>
<h5>Slots</h5>
<div class="doc-tablewrapper">
<table class="doc-table">
<thead>
<tr>
<th>Name</th>
<th>Parameters</th>
</tr>
</thead>
<tbody>
<tr>
<td>item</td>
<td>item: Menuitem instance</td>
</tr>
</tbody>
</table>
</div>
<h5>Styling</h5> <h5>Styling</h5>
<p>Following is the list of structural style classes, for theming classes visit <router-link to="/theming">theming</router-link> page.</p> <p>Following is the list of structural style classes, for theming classes visit <router-link to="/theming">theming</router-link> page.</p>
<div class="doc-tablewrapper"> <div class="doc-tablewrapper">

View File

@ -143,11 +143,16 @@ export default {
</code></pre> </code></pre>
<h5>Custom Content</h5> <h5>Custom Content</h5>
<p>Any content inside the megamenu will be displayed on the right side by default. You may use ".p-megamenu-custom" style class to change the location of the content.</p> <p>Any content inside the megamenu will be displayed on the right side by default. You may use ".p-megamenu-custom" style class to change the location of the content.
Additionally, MegaMenu offers content customization with the <i>item</i> template that receives the menuitem instance from the model as a parameter.
</p>
<pre v-code><code><template v-pre> <pre v-code><code><template v-pre>
&lt;MegaMenu :model="items"&gt; &lt;MegaMenu :model="items"&gt;
&lt;InputText placeholder="Search" type="text" /&gt; &lt;InputText placeholder="Search" type="text" /&gt;
&lt;Button label="Logout" icon="pi pi-power-off" /&gt; &lt;Button label="Logout" icon="pi pi-power-off" /&gt;
&lt;template #item="{item}"&gt;
&lt;a :href="item.url"&gt;{{item.label}}&lt;/a&gt;
&lt;/template&gt;
&lt;/MegaMenu&gt; &lt;/MegaMenu&gt;
</template> </template>
</code></pre> </code></pre>
@ -181,6 +186,24 @@ export default {
</table> </table>
</div> </div>
<h5>Slots</h5>
<div class="doc-tablewrapper">
<table class="doc-table">
<thead>
<tr>
<th>Name</th>
<th>Parameters</th>
</tr>
</thead>
<tbody>
<tr>
<td>item</td>
<td>item: Menuitem instance</td>
</tr>
</tbody>
</table>
</div>
<h5>Styling</h5> <h5>Styling</h5>
<p>Following is the list of structural style classes, for theming classes visit <router-link to="/theming">theming</router-link> page.</p> <p>Following is the list of structural style classes, for theming classes visit <router-link to="/theming">theming</router-link> page.</p>
<div class="doc-tablewrapper"> <div class="doc-tablewrapper">

View File

@ -84,6 +84,17 @@ toggle(event) {
this.$refs.menu.toggle(event); this.$refs.menu.toggle(event);
} }
</code></pre>
<h5>Templating</h5>
<p>Menu offers content customization with the <i>item</i> template that receives the menuitem instance from the model as a parameter.</p>
<pre v-code><code><template v-pre>
&lt;Menu :model="items"&gt;
&lt;template #item="{item}"&gt;
&lt;a :href="item.url"&gt;{{item.label}}&lt;/a&gt;
&lt;/template&gt;
&lt;/Menu&gt;
</template>
</code></pre> </code></pre>
<h5>Properties</h5> <h5>Properties</h5>
@ -164,6 +175,24 @@ toggle(event) {
</table> </table>
</div> </div>
<h5>Slots</h5>
<div class="doc-tablewrapper">
<table class="doc-table">
<thead>
<tr>
<th>Name</th>
<th>Parameters</th>
</tr>
</thead>
<tbody>
<tr>
<td>item</td>
<td>item: Menuitem instance</td>
</tr>
</tbody>
</table>
</div>
<h5>Styling</h5> <h5>Styling</h5>
<p>Following is the list of structural style classes, for theming classes visit <router-link to="/theming">theming</router-link> page.</p> <p>Following is the list of structural style classes, for theming classes visit <router-link to="/theming">theming</router-link> page.</p>
<div class="doc-tablewrapper"> <div class="doc-tablewrapper">

View File

@ -155,12 +155,15 @@ export default {
</code></pre> </code></pre>
<h5>Custom Content</h5> <h5>Custom Content</h5>
<p>Two slots named "start" and "end" are provided to embed content before or after the menubar.</p> <p>Two slots named "start" and "end" are provided to embed content before or after the menubar. In additon Menubar, offers item customization with the <i>item</i> template that receives the menuitem instance from the model as a parameter.</p>
<pre v-code><code><template v-pre> <pre v-code><code><template v-pre>
&lt;Menubar :model="items"&gt; &lt;Menubar :model="items"&gt;
&lt;template #start&gt; &lt;template #start&gt;
Before Before
&lt;/template&gt; &lt;/template&gt;
&lt;template #item="{item}"&gt;
&lt;a :href="item.url"&gt;{{item.label}}&lt;/a&gt;
&lt;/template&gt;
&lt;template #end&gt; &lt;template #end&gt;
After After
&lt;/template&gt; &lt;/template&gt;
@ -209,6 +212,10 @@ export default {
<td>end</td> <td>end</td>
<td>-</td> <td>-</td>
</tr> </tr>
<tr>
<td>item</td>
<td>item: Menuitem instance</td>
</tr>
</tbody> </tbody>
</table> </table>
</div> </div>

View File

@ -141,6 +141,17 @@ export default {
} }
} }
</code></pre>
<h5>Templating</h5>
<p>PanelMenu offers content customization with the <i>item</i> template that receives the menuitem instance from the model as a parameter.</p>
<pre v-code><code><template v-pre>
&lt;PanelMenu :model="items"&gt;
&lt;template #item="{item}"&gt;
&lt;a :href="item.url"&gt;{{item.label}}&lt;/a&gt;
&lt;/template&gt;
&lt;/PanelMenu&gt;
</template>
</code></pre> </code></pre>
<h5>Properties</h5> <h5>Properties</h5>
@ -166,6 +177,24 @@ export default {
</table> </table>
</div> </div>
<h5>Slots</h5>
<div class="doc-tablewrapper">
<table class="doc-table">
<thead>
<tr>
<th>Name</th>
<th>Parameters</th>
</tr>
</thead>
<tbody>
<tr>
<td>item</td>
<td>item: Menuitem instance</td>
</tr>
</tbody>
</table>
</div>
<h5>Styling</h5> <h5>Styling</h5>
<p>Following is the list of structural style classes, for theming classes visit <router-link to="/theming">theming</router-link> page.</p> <p>Following is the list of structural style classes, for theming classes visit <router-link to="/theming">theming</router-link> page.</p>
<div class="doc-tablewrapper"> <div class="doc-tablewrapper">

View File

@ -49,6 +49,17 @@ export default {
&lt;Steps :model="items" :readonly="false" /&gt; &lt;Steps :model="items" :readonly="false" /&gt;
&lt;router-view /&gt; &lt;router-view /&gt;
</code></pre>
<h5>Templating</h5>
<p>Steps offers content customization with the <i>item</i> template that receives the menuitem instance from the model as a parameter.</p>
<pre v-code><code><template v-pre>
&lt;Steps :model="items"&gt;
&lt;template #item="{item}"&gt;
&lt;a :href="item.url"&gt;{{item.label}}&lt;/a&gt;
&lt;/template&gt;
&lt;/Steps&gt;
</template>
</code></pre> </code></pre>
<h5>Properties</h5> <h5>Properties</h5>
@ -86,6 +97,24 @@ export default {
</table> </table>
</div> </div>
<h5>Slots</h5>
<div class="doc-tablewrapper">
<table class="doc-table">
<thead>
<tr>
<th>Name</th>
<th>Parameters</th>
</tr>
</thead>
<tbody>
<tr>
<td>item</td>
<td>item: Menuitem instance</td>
</tr>
</tbody>
</table>
</div>
<h5>Styling</h5> <h5>Styling</h5>
<p>Following is the list of structural style classes, for theming classes visit <router-link to="/theming">theming</router-link> page.</p> <p>Following is the list of structural style classes, for theming classes visit <router-link to="/theming">theming</router-link> page.</p>
<div class="doc-tablewrapper"> <div class="doc-tablewrapper">

View File

@ -32,6 +32,17 @@ export default {
} }
} }
</code></pre>
<h5>Templating</h5>
<p>TabMenu offers content customization with the <i>item</i> template that receives the menuitem instance from the model as a parameter.</p>
<pre v-code><code><template v-pre>
&lt;TabMenu :model="items"&gt;
&lt;template #item="{item}"&gt;
&lt;a :href="item.url"&gt;{{item.label}}&lt;/a&gt;
&lt;/template&gt;
&lt;/TabMenu&gt;
</template>
</code></pre> </code></pre>
<h5>Properties</h5> <h5>Properties</h5>
@ -63,6 +74,24 @@ export default {
</table> </table>
</div> </div>
<h5>Slots</h5>
<div class="doc-tablewrapper">
<table class="doc-table">
<thead>
<tr>
<th>Name</th>
<th>Parameters</th>
</tr>
</thead>
<tbody>
<tr>
<td>item</td>
<td>item: Menuitem instance</td>
</tr>
</tbody>
</table>
</div>
<h5>Styling</h5> <h5>Styling</h5>
<p>Following is the list of structural style classes, for theming classes visit <router-link to="/theming">theming</router-link> page.</p> <p>Following is the list of structural style classes, for theming classes visit <router-link to="/theming">theming</router-link> page.</p>
<div class="doc-tablewrapper"> <div class="doc-tablewrapper">

View File

@ -171,6 +171,17 @@ toggle(event) {
this.$refs.menu.toggle(event); this.$refs.menu.toggle(event);
} }
</code></pre>
<h5>Templating</h5>
<p>TieredMenu offers content customization with the <i>item</i> template that receives the menuitem instance from the model as a parameter.</p>
<pre v-code><code><template v-pre>
&lt;TieredMenu :model="items"&gt;
&lt;template #item="{item}"&gt;
&lt;a :href="item.url"&gt;{{item.label}}&lt;/a&gt;
&lt;/template&gt;
&lt;/TieredMenu&gt;
</template>
</code></pre> </code></pre>
<h5>Properties</h5> <h5>Properties</h5>
@ -251,6 +262,24 @@ toggle(event) {
</table> </table>
</div> </div>
<h5>Slots</h5>
<div class="doc-tablewrapper">
<table class="doc-table">
<thead>
<tr>
<th>Name</th>
<th>Parameters</th>
</tr>
</thead>
<tbody>
<tr>
<td>item</td>
<td>item: Menuitem instance</td>
</tr>
</tbody>
</table>
</div>
<h5>Styling</h5> <h5>Styling</h5>
<p>Following is the list of structural style classes, for theming classes visit <router-link to="/theming">theming</router-link> page.</p> <p>Following is the list of structural style classes, for theming classes visit <router-link to="/theming">theming</router-link> page.</p>
<div class="doc-tablewrapper"> <div class="doc-tablewrapper">