Search code examples
vuejs3primevue

TieredMenu componente of PrimeVue does not update location according to button that invokes it


I have a problem with the TieredMenu component of the primevue framework.

I have the following template

<template>
    <table>
        <tr v-for="item in data" :key="item.id">
            <td><button @click="toggle">options</button></td>
            <td>{{ item.label }}</td>
        </tr>
    </table>
    
    <TieredMenu ref="tieredMenuRef" :model="menuModel" popup/>
</template>

<script setup>
    import { ref } from 'vue';
    
    const data = [...];
    const menuModel = [...];
    const tieredMenuRef = ref(null);
    
    const toggle = (event) => {
        tieredMenuRef.value.toggle(event);
    };
</script>

The problem is that the TieredMenu component always appears under the first button that calls it, the TieredMenu component should appear under each button that calls it. Any help on how I can solve the problem.

Note: I am using vue 3.

EDIT 1: Using DataTable component of PrimeVue

<DataTable :value="data" size="small" selectionMode="single" stripedRows>
    <Column style="width: 50px">
        <template #body="slotProps">
            <Button icon="pi pi-ellipsis-v" @click="toggle($event, slotProps.index)" rounded text/>
            <TieredMenu ref="tieredMenuRef" :model="menuModel" popup/>
        </template>
    </Column>
    <Column field="label" header="LABEL"></Column>
</DataTable>

Solution

  • Add the TieredMenu component to the v-for. You want to place one below each button. This will mean that tieredMenuRef will be an array of refs, and to target the correct one to popup you'll need to pass the correct index, so the v-for itself and the toggle method will need to slightly change

    <tr v-for="(item, i) in data" :key="item.id">
        <td><button @click="toggle($event, i)">options</button></td>
        <td>{{ item.label }}</td>
        <TieredMenu ref="tieredMenuRef" :model="menuModel" popup />
    </tr>
    
    const tieredMenuRef = ref([])
    
    const toggle = (event, i) => {
      tieredMenuRef.value[i].toggle(event)
    }
    

    StackBlitz example


    For the specific case of being within a PrimeVue DataTable, because there is no looping of rows, you can put the v-for directly on the <TieredMenu> and place it outside of the DataTable

      <TieredMenu
        v-for="item in data"
        :key="item.id"
        ref="tieredMenuRef"
        :model="menuModel"
        popup
      />
    

    Here is that StackBlitz example