nirvair
nirvair

Reputation: 4180

how to make @click in Vuetify dynamic based on JSON objects

I have a component which shows a list. This list is dynamically populated by pages using this component.

<template>
  <v-list
    subheader
  >
    <v-subheader class="font-weight-black">Choose action</v-subheader>
    <v-divider/>
    <v-list-item
      v-for="(item, i) in model.menu"
      :key="i"
      @click="item.action"
    >
      <v-list-item-title>{{ item.title }}</v-list-item-title>
    </v-list-item>
  </v-list>

</template>

And this is the TypeScript class.

<script lang="ts">
import { Component, Vue, Watch, Prop } from 'vue-property-decorator'
import { app } from 'electron'

@Component
export default class ListItem extends Vue {
  @Prop() appStatus!: string
  @Prop() appId!: string

  model: any = {
    menu: [
      { title: 'Title One', action: 'someModalAction(appId)' },
      { title: 'Title Two', action: '' },
      { title: 'Title Three', action: '' }
    ]
  }

  someModalAction( appId: string ) {
    // show some modal here
  }
</script>

Here model object would be dynamic and other pages would pass this object as Prop() (This is just an example here).

When I click on Title One, nothing happens. However, when I change the object to

{title: 'Title One', action: this.someModalAction(this.appId)}

Then I can see the modal when the page is loaded. When I close this modal, the list item cannot be clicked then.

So, how can I pass actions to @click dynamically?

Upvotes: 0

Views: 916

Answers (3)

Kamau Brian
Kamau Brian

Reputation: 11

v-list-item v-for="(item,index) in profileItems" @click="item.action" ripple="ripple"
                           :key="index">


{
          icon: 'mdi-exit-to-app',
          href: '/',
          title: 'Logout',
          action: () => {
            this.onUserLogout()
          }
        },
      ]

Upvotes: 1

Pratik Patel
Pratik Patel

Reputation: 6978

Just make one function for calling you function on click.

To use dynamic function call it is suggested to have a helper function that receives the function name and call the corresponding function.

  data () {
    return {
      test: '',
      submitting: false,
       list: [{
        title: "One",
        action: "itemClicked"
      },
      {
        title: "Two",
        action: "itemClicked2"
      },
      {
        title: "Three",
        action: "itemClicked3"
      }
    ]
    }
  },
methods: {
    itemClicked() {
      alert('item clicked')
    },
    itemClicked2() {
      alert('item clicked 2')
    },
    itemClicked3() {
      alert('item clicked 3')
    },
    funcioncall(name){
      this[name]();
    }
  }

codepen - https://codepen.io/Pratik__007/pen/JjoVxbj?editors=1010

Upvotes: 1

Estradiaz
Estradiaz

Reputation: 3573

convert data with getter:

import { Component, Vue, Watch, Prop } from 'vue-property-decorator'
import { app } from 'electron'

@Component
export default class ListItem extends Vue {
  @Prop() appStatus!: string
  @Prop() appId!: string

  model: any = {
    menu: [
      { title: 'Title One', action: 'someModalAction' },
      { title: 'Title Two', action: '' },
      { title: 'Title Three', action: '' }
    ]
  }
  get items(){
    return this.model.menu

    .map(item => ({...item, action: item.action && () => this[item.action](this.appId)})
  }

  someModalAction( appId: string ) {
    // show some modal here
  }
<template>
  <v-list
    subheader
  >
    <v-subheader class="font-weight-black">Choose action</v-subheader>
    <v-divider/>
    <v-list-item
      v-for="(item, i) in items"
      :key="i"
      @click="item.action"
    >
      <v-list-item-title>{{ item.title }}</v-list-item-title>
    </v-list-item>
  </v-list>

</template>

Upvotes: 1

Related Questions