Sunkhern
Sunkhern

Reputation: 278

Iterating with v-for on dynamic item

I'm trying to iterate through a db object I fetch during created(), I get the values in a console.log but the v-for template part remains empty. My sub-question is : is this good practice ? I'm quite new to Vue and my searches on this issue make me think it's a lifecycle issue.

Thanks for the help.

TEMPLATE PART :

 .content(v-for="(content, key, index) in contents")
   h3 {{key}}
   .line
   | {{getValue(content)}} // this is blank

METHODS PART:

getValue(value) {
  PagesService.fetchDataWrap({
    id: value
  }).then((response) => {
    const test = response.data.values[0].value
    console.log(test) //this is working and gives the right value
    return test
  })
},
getPage() {
  PagesService.fetchPage({
    id: this.$route.params.page
  }).then((response) => {
    this.name = response.data.result.name
    this.langs = response.data.result.langs
    this.project = response.data.result.parent
    this.contents = response.data.result.values
  })
  this.getProject()
}

console.log(this.contents) result :

{__ob__: Observer}
footer: "5a29943b719236225dce6191"
header: "5a29a9f080568b2484b31ee1"

which is the values I want to send when v-for iterates on contents so the getValue can process it to fetch corresponding values

Upvotes: 2

Views: 1360

Answers (1)

Phil
Phil

Reputation: 164730

I wouldn't recommend attempting to output the value of an asynchronous method. It's highly unlikely that it will work correctly.

Instead, populate your contents array / object fully during the created hook. For example, this can replace the contents hash value with whatever comes back from fetchDataWrap...

getPage () {
  PagesService.fetchPage({
    id: this.$route.params.page
  }).then(response => {
    this.name = response.data.result.name
    this.langs = response.data.result.langs
    this.project = response.data.result.parent

    let contents = response.data.result.values
    Promise.all(Object.keys(contents).map(key => {
      // map each key to a "fetchDataWrap" promise
      return PageService.fetchDataWrap({
        id: contents[key]
      }).then(res => {
        // replace the hash with the resolved value
        contents[key] = res.data.values[0].value
      })
    }).then(() => {
      // all done, assign the data property
      this.contents = contents
    })
  })
}

Then you can trust that the content has been loaded for rendering

.content(v-for="(content, key, index) in contents")
  h3 {{key}}
  .line
  | {{content}}

Upvotes: 2

Related Questions