0

I need to load async data and then loop it out in a vue component. I understand that the loop run before I have the data but I cant figure out how to rerun or hold the loop until I have the data. One solution I have tested and that dose not work is a loaded property in Data and a isLoaded computed function and after that -

                <div v-if="isLoaded">
                    <ul v-for="item in menu.items">
                        <li>{{ item.heading }}</li>
                    </ul>
                </div>

It seems that the loop runs anyway and I got error -

TypeError: Cannot read property 'items' of undefined

The whole page seems to freeze after that error so probably cant I set the Data property loaded to true in the async function. I have tested to run the async in both created and mounted hooks.

When I leave the page and come back everything works, probably because the data has been loaded. I have also tested to set the loded property by button click and it works fine when the loop are out comment and not when the loop run.

I thought this was the common solution after googling but I cant get it to work. Whats wrong or any other suggestions (my last one is to load the data in an other page).

See also -

export default {
    data() {
        return {
            loaded: false,

and -

computed: {
    isLoaded() {

        return this.loaded

    }

2 Answers 2

1

The problems you may have met:

  1. menu is null when compile the template, so as @ittus already answered, uses v-if to control the flow.

  2. uses Vue API: $set when adding property into one object. (check Vue: Reactivity in Depth for more details)

So the codes will be like below demo:

Vue.config.productionTip = false
app = new Vue({
  el: "#app",
  data: {
    menu: null,
    loading: false
  },
  mounted: function () {
    this.loading = true
    setTimeout(() => {
      this.menu = this.menu ? this.menu : {}
      this.$set(this.menu, 'items', [{'heading': 'a1'},{'heading': 'b1'}, {'heading': 'c1'}])
      this.loading = false
    }, 1500)
  }
})
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<div id="app">
    <div v-if="!loading">
      <div v-if="menu">
        <ul v-for="item in menu.items">
            <li>{{ item.heading }}</li>
        </ul>
      </div>
      <p v-else>No Data</p>
    </div>
    <p v-else>Loading...</p>
</div>

Sign up to request clarification or add additional context in comments.

4 Comments

So thats probably my problem. I need to use $set. But the object I try to copy (menu) is from Firebase and it seems that even if I call the getter in the callback (then) I still are to quick. If I do it in your timer everything works fine except that I need to give it a name (property) so it going to be menu.menu.items in the loop.
At least I thought I used a promise. I am using vuexfire and I dont think its a promise so now I need to figure it out. This sh... is to hard for me now :(
@user2856066, not sure what you mean, if vuexfire caused something wrong, you can add it to this question or post another one. for menu.menu.items you mentioned, probably you'd like to use like this.$set(this.$data, 'menu', newMenuItems)
Thanks a lot, its working. I had several errors and things I did not know. Loading, how to use $set and a callback / promise error from the store.
1

You can simply check menu is not undefined

<div v-if="menu && menu.items">
    <ul v-for="item in menu.items">
       <li>{{ item.heading }}</li>
    </ul>
 </div>

or in where you get data:

methods: {
  getData() {
    this.loaded = false
    callApi().then(res => {
      this.menu = res // example
      this.loaded = true
    })
  }
}

 <div v-if="loaded">
   <ul v-for="item in menu.items">
     <li>{{ item.heading }}</li>
   </ul>
 </div>

3 Comments

Thanks for your answer. With your first example the error are gone but the loop never runs again (when the data are loaded) which are strange. The second example is much like I do except that I do it in created or mounted hooks.
Can you use vue-devtools to inspect the value of menu variable?
Its undefined. So thats probably my problem and not the async and loading part. Sphinx above has also a good point and I will leave a comment there.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.