Vue3 component with list definition in inner html

I want to create context menu. By the nature of the contextmenu depending on the location of usage the entries differ. Therefor I am trying to create a Vue.js 3 component that allows a list to be defined within its innerHtml, rather than passing the list as a prop.

A example usage I have in mind should look like the following example:

<!-- when using in a list of articles -->
<contextMenu>
    <item name="copy" @click="copyMethod"/>
    <item name="delete" @click="deleteMethod"/>
</contextMenu>

<!-- in a list of users -->
<contextMenu>
    <item name="edit user" @click="editMethod"/>
    <item name="delete user" @click="deleteMethod"/>
</contextMenu>

as far as I unterstood, slots are not the solution to my problem since they seem to be the inverse.

Something like this but without the list as property

const ContextMenu = {
  template:
  `<div>
    <span v-for="entry in entries" :key="entry.name">
        <router-link :to="entry.to" >
            <v-button>{{ entry.name }}</v-button>
        </router-link>
    </span>
</div>`   
}

>Solution :

I think the slots are exactly what you need in this case.

const { createApp, ref } = Vue;

const vButton = { 
  props: ['name'],
  template: `<button type="button" :name="name"><slot></slot></button>` 
}

const ContextMenuItem = {
  components: { vButton },
  props: ['entry'],
  template: `<router-link :to="entry.to"><v-button>{{ entry.name }}</v-button></router-link>`   
}

const ContextMenu = { 
 components: { ContextMenuItem },
  template: `<div><slot></slot></div>`
}

const App = {
  components: {
    vButton, ContextMenuItem, ContextMenu
  },
  methods: {
    copyMethod() { console.log('copyMethod()')},
    editMethod() { console.log('editMethod()')},
    deleteMethod() { console.log('deleteMethod()')},
  }
}

const app = createApp(App)
app.mount('#app')
<div id="app">  
    <!-- when using in a list of articles -->
    <context-menu>
        <context-menu-item :entry="{ name: 'copy'}" @click="copyMethod"></context-menu-item>&nbsp;
        <context-menu-item :entry="{ name: 'delete'}" @click="deleteMethod"></context-menu-item>
    </context-menu>
    <br />
    <!-- in a list of users -->
    <context-menu>
        <context-menu-item :entry="{ name: 'edit-user'}" @click="editMethod"></context-menu-item>&nbsp;
        <context-menu-item :entry="{ name: 'delete-user'}" @click="deleteMethod"></context-menu-item>
    </context-menu>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>

Leave a Reply