1
votes

Problem:

I'm trying to figure out how to pass a value of a clicked item into another component


See codepen: https://codepen.io/anon/pen/zRXBNY

In the codepen menu of an item is triggered by right click

Let's say we have a loop (this iterator component) that's displaying all the items of object items

<v-data-iterator
  :items="items"
  hide-actions
  class="ma-4"
>
  <v-flex
    slot="item"
    slot-scope="props"
    xs12 sm6 md4 lg3
  >
    <v-card @contextmenu="show" class="ma-3 elevation-4">
      <v-card-title>
        <h4>{{ props.item.name }}</h4>
      </v-card-title>
    </v-card>
  </v-flex>
</v-data-iterator>

And we also have this "menu" component in the same .vue component:

<v-menu 
  absolute
  offset-y 
  :position-x="x"
  :position-y="y" 
  v-model="showMenu"
>
  <v-list>
    <p class="white ma-3">menu for item: [TITLE]</p>
    <v-list-tile 
       v-for="item in menuItems" 
       :key="item.title" @click=""
    >
      <v-list-tile-title>
        {{ item.title }}
      </v-list-tile-title>
    </v-list-tile>
    <v-text-field 
      class="ma-3" 
      label="rename">
    </v-text-field>  
  </v-list>
</v-menu>

Question:

How do we trigger the menu component and pass the data of that particular item in it (so that we can do something with it)? As an example I put this menu for item: [TITLE] paragraph there, I don't understand how do we pass the title of the clicked item there?

1

1 Answers

3
votes

It seem a bit messy to me (i'm not very familiar with Vuetify), but the first solution that comes to my mind is to pass item object to the handler. So your code goes as:

<v-card @contextmenu="show($event, props.item)" class="ma-3 elevation-4"></v-card>

Then once the event is fired and handler function is called you can store the item you clicked on:

show (e, item) {
    this.selectedItem = item;
    e.preventDefault()
// ...

Now you can use the item inside the model component as:

<v-list>
    <p class="white ma-3">
        menu for item: {{selectedItem.name}}
    </p>
//...

Full demo:

new Vue({
  el: '#app',
  methods: {
    show (e, item) {
      this.selectedItem = item;
      e.preventDefault()
      this.showMenu = false
      this.x = e.clientX
      this.y = e.clientY
      this.$nextTick(() => {
        this.showMenu = true
      })
    }
  },
  data: () => ({
    x: 0,
    y: 0,
    selectedItem: {},    
    showMenu: false,
    menuItems: [
      { title: 'copy' },
      { title: 'paste' },
      { title: 'delete' }
    ],
    items: [
        {
          value: false,
          name: 'Frozen Yogurt'
        },
        {
          value: false,
          name: 'Ice cream sandwich'
        },
        {
          value: false,
          name: 'Eclair'
        },
        {
          value: false,
          name: 'Cupcake'
        }
      ]
  })
})
<link href="https://unpkg.com/vuetify/dist/vuetify.min.css" rel="stylesheet"/>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vuetify/dist/vuetify.min.js"></script>
<div id="app" >
  <v-app id="inner" class="grey lighten-3"> 
    <h1 class="ma-2 ml-4">right click on an item to trigger menu</h1>
<!--  ITEMS ON THE PAGE -->
    <v-data-iterator
      :items="items"
      hide-actions
      class="ma-4"
    >
      <v-flex
        slot="item"
        slot-scope="props"
        xs12 sm6 md4 lg3
      >
        <v-card @contextmenu="show($event, props.item)" class="ma-3 elevation-4">
          <v-card-title>
            <h4>{{ props.item.name }}</h4>
          </v-card-title>
        </v-card>
      </v-flex>
    </v-data-iterator>
    
<!-- MENU COMPONENT -->
    <v-menu 
      absolute
      offset-y 
      :position-x="x"
      :position-y="y" 
      v-model="showMenu"
    >
      <v-list>
        <p class="white ma-3">menu for item: {{selectedItem.name}}</p>
        <v-list-tile 
           v-for="item in menuItems" 
           :key="item.title" @click=""
        >
          <v-list-tile-title>
            {{ item.title }}
          </v-list-tile-title>
        </v-list-tile>
        <v-text-field 
          class="ma-3" 
          label="rename">
        </v-text-field>  
      </v-list>
    </v-menu>
  </v-app>
</div>