Vishal Gupta
Vishal Gupta

Reputation: 94

V-for not working with dynamic data in template

My template has following:

 <ul id="example-1">
        <li v-for="item in getMenus" :key="item.id">
          {{ item.name }}
        </li>
      </ul>

methods:{
 async getMenus() {
      this.$axios.setHeader('Content-Type', 'application/json', ['get'])
      this.$axios.setHeader(
        'Authorization',
        'Bearer ' + this.$store.state.auth.Token
      )

      const roleId = this.$store.state.auth.role.roleId
      const url = `/role/${roleId}/menu`
      let data = ''
      // eslint-disable-next-line vue/no-async-in-computed-properties
      const pal = await this.$axios
        .$get(url, JSON.stringify(roleId))
        .then(function(resp) {
          data = resp.data
        })
      if (pal) {
        // eslint-disable-next-line no-console
        console.log('hi')
      }
      return data
    }

} }

Above mentioned is my code. I checked my api its returing data. If i put directly my data as harcoded value then it works, if I use api then it doesnot work. I looke dinto console also that is also clear. I am new to vue. Any help will be highly appreciated.

Upvotes: 0

Views: 77

Answers (2)

palaѕн
palaѕн

Reputation: 73896

This happens because inside async getMenus method you are returning data before it is even assigned a value. A better way to resolve this issue would be to set a variable in data options like:

data() {
  return {
    loading: false,
    items: []  // This will hold all the getMenus() data
  }
},

and inside getMenus update items array like:

created() {
   this.getMenus();
},
methods: {
  async getMenus() {
    this.loading = true;

    // All other logic here...

    this.$axios.$get(url, JSON.stringify(roleId))
      .then(resp => {
        this.loading = false;
        this.items = resp.data;  // Set the response data here...
      })
      .catch(error => {
        this.loading = false;
        console.log(error);
      })
  }
}

and then update your template like:

<li v-for="item in items" :key="item.id">
    {{ item.name }}
</li>

In case, your async method is going to take some time to finish you can show a loading text or icon so that user know that at least something is happening instead of looking at a blank screen like:

<template v-if="loading">
  Loading...
</template>

<template v-else>
  <ul id="example-1">
    <li v-for="item in items" :key="item.id">
      {{ item.name }}
    </li>
  </ul>
</template>

Upvotes: 0

Anatoly
Anatoly

Reputation: 22758

You can't use async methods in v-for. Define an array in data section of a component and write results in the array at the end of getMenus function. You should call getMenus at some place in your code (for instance in mounted hook):

<li v-for="item in menuList" :key="item.id">
...
// in a component code
data: {
  return {
    menuList: []
  }
},
mounted () {
  // if you don't have any initialization after this call you can call it without await
  getMenus()
},
methods:{
 async getMenus() {
   ...
   // getting results
   const { data: menuList } = await this.$axios
        .$get(url, JSON.stringify(roleId))
   this.menuList = menuList
}

Upvotes: 1

Related Questions