Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Question]: It's possible to set active menu item for Menu component ? #6604

Open
JianJroh opened this issue Oct 18, 2024 · 2 comments
Open
Labels
Status: Needs Triage Issue will be reviewed by Core Team and a relevant label will be added as soon as possible

Comments

@JianJroh
Copy link

Describe the bug

After refersh page, i want to set active menu item for Menu component by route.

Like value props of Tabs

Reproducer

Question

PrimeVue version

latest

Vue version

4.x

Language

TypeScript

Build / Runtime

Nuxt

Browser(s)

No response

Steps to reproduce the behavior

No response

Expected behavior

No response

@JianJroh JianJroh added the Status: Needs Triage Issue will be reviewed by Core Team and a relevant label will be added as soon as possible label Oct 18, 2024
@JianJroh JianJroh changed the title [Question]It's possible to set active menu item for Menu component ? [Question]: It's possible to set active menu item for Menu component ? Oct 18, 2024
@CCodam
Copy link

CCodam commented Oct 18, 2024

Sadly It doesn't look like there's anyway to accomplish this through a prop on the Menu or option on the MenuItem.
This would be a fine feature request though.

Here's some inspiration to accomplish your task as is.

<template>
<ThemeSwitcher />
<div class="card flex justify-center">
  <Menu :model="items"> 
      <template #item="{ item, props }">
          <!-- Bind class based on the active property of the item -->
          <a v-bind="props.action" v-bind:class = "(item.active)?'p-menu-item-active':''" >
              <span :class="item.icon" />
              <span>{{ item.label }}</span>
          </a>
      </template>
  </Menu>
</div>
</template>

<script setup>
import { ref, onMounted } from 'vue'; // Import onMounted

const items = ref([
{ label: 'New', icon: 'pi pi-plus' },
{ label: 'Search', icon: 'pi pi-search' },
{ label: 'Settings', icon: 'pi pi-cog',  active: true },
{ label: 'Logout', icon: 'pi  pi-sign-out' },
]);
</script>

<style>
/* Create custom class for the active element */
.p-menu-item-active {
  color: var(--p-menu-item-focus-color) !important;
  background: var(--p-menu-item-focus-background) !important;
}
</style>

Tip

Inspiration 2
https://stackblitz.com/edit/2gwcb8?file=src%2FApp.vue
Modifying the DOM at onMounted

<template>
  <ThemeSwitcher />
  <div class="card flex justify-center">
    <Menu id="comMenuId" :model="items" /> <!-- Set id on the Menu Component -->
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue'; // Import onMounted

const items = ref([
  { label: 'New', icon: 'pi pi-plus' },
  { label: 'Search', icon: 'pi pi-search' },
  { label: 'Settings', icon: 'pi pi-cog' },
  { label: 'Logout', icon: 'pi  pi-sign-out' },
]);

// Define active element as object with label "Settings".
const activeItem = items.value.map((x) => x.label).indexOf('Settings');

onMounted(() => {
  // Add custom classes to the defined active element.
  document
    .getElementById('comMenuId_' + activeItem)
    .querySelector('.p-menu-item-content')
    .classList.add('p-menu-item-content-active');
  document
    .getElementById('comMenuId_' + activeItem)
    .querySelector('.p-menu-item-icon')
    .classList.add('p-menu-item-icon-active');
});
</script>

<style>
  /* Create custom classes for the active element */
  .p-menu-item-content-active {
    color: var(--p-menu-item-focus-color) !important;
    background: var(--p-menu-item-focus-background) !important;
  }
  .p-menu-item-icon-active {
    color: var(--p-menu-item-icon-focus-color) !important;
  }
</style>

@JianJroh
Copy link
Author

Sadly It doesn't look like there's anyway to accomplish this through a prop on the Menu or option on the MenuItem. This would be a fine feature request though.

Here's some inspiration to accomplish your task as is.

Tip

Inspiration 1 https://stackblitz.com/edit/2gwcb8-wix75g?file=src%2FApp.vue Using a template

<template>
<ThemeSwitcher />
<div class="card flex justify-center">
  <Menu :model="items"> 
      <template #item="{ item, props }">
          <!-- Bind class based on the active property of the item -->
          <a v-bind="props.action" v-bind:class = "(item.active)?'p-menu-item-active':''" >
              <span :class="item.icon" />
              <span>{{ item.label }}</span>
          </a>
      </template>
  </Menu>
</div>
</template>

<script setup>
import { ref, onMounted } from 'vue'; // Import onMounted

const items = ref([
{ label: 'New', icon: 'pi pi-plus' },
{ label: 'Search', icon: 'pi pi-search' },
{ label: 'Settings', icon: 'pi pi-cog',  active: true },
{ label: 'Logout', icon: 'pi  pi-sign-out' },
]);
</script>

<style>
/* Create custom class for the active element */
.p-menu-item-active {
  color: var(--p-menu-item-focus-color) !important;
  background: var(--p-menu-item-focus-background) !important;
}
</style>

Tip

Inspiration 2 https://stackblitz.com/edit/2gwcb8?file=src%2FApp.vue Modifying the DOM at onMounted

<template>
  <ThemeSwitcher />
  <div class="card flex justify-center">
    <Menu id="comMenuId" :model="items" /> <!-- Set id on the Menu Component -->
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue'; // Import onMounted

const items = ref([
  { label: 'New', icon: 'pi pi-plus' },
  { label: 'Search', icon: 'pi pi-search' },
  { label: 'Settings', icon: 'pi pi-cog' },
  { label: 'Logout', icon: 'pi  pi-sign-out' },
]);

// Define active element as object with label "Settings".
const activeItem = items.value.map((x) => x.label).indexOf('Settings');

onMounted(() => {
  // Add custom classes to the defined active element.
  document
    .getElementById('comMenuId_' + activeItem)
    .querySelector('.p-menu-item-content')
    .classList.add('p-menu-item-content-active');
  document
    .getElementById('comMenuId_' + activeItem)
    .querySelector('.p-menu-item-icon')
    .classList.add('p-menu-item-icon-active');
});
</script>

<style>
  /* Create custom classes for the active element */
  .p-menu-item-content-active {
    color: var(--p-menu-item-focus-color) !important;
    background: var(--p-menu-item-focus-background) !important;
  }
  .p-menu-item-icon-active {
    color: var(--p-menu-item-icon-focus-color) !important;
  }
</style>

Thanks for the tips you provided.
Looking forward to the component supporting this feature in the future.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Needs Triage Issue will be reviewed by Core Team and a relevant label will be added as soon as possible
Projects
None yet
Development

No branches or pull requests

2 participants