1

I'm trying to load page contents using Vue JS. Interface is simple with one select, one textarea and one button. I'm trying to load all the contents from third party api response. First element get loaded fine, but the items that are being tried to load after don't work at all unless typed something inside the textarea. Situation is similar to this post. But in my case there are multiple iterations of loop from which I'm trying to load data.

So.

HTML

<div class="col-md-12 offset-s-1">
    <ul>
        <li v-for="title in titles">
            <div class="row">
                <div class="col-md-6">@{{ title.name }}</div>
                <div class="col-md-6">@{{ title.status }}</div>
                <div class="col-md-12">@{{ title.date }}</div>
                <div class="col-md-12">@{{ title.desc }}</div>
            </div>
            <ul>
                <li v-for="show in title.shows">
                    @{{ show.title }}
                    <ul>
                        <li v-for="episode in show.episodes">
                            <div class="col-md-12">@{{ episode.title }}</div>
                            <div class="col-md-12" v-html="episode.status"><b>Episode Status</b>: @{{ episode.status }}</div>
                            <div class="col-md-12"><b>Episode Update Date</b>: @{{ episode.date }}</div>
                            <div class="col-md-12"><b>Episode Description</b>: @{{ episode.desc }}</div>
                            <div class="col-md-12"><b>Episode Release Year</b>: @{{ episode.year }}</div>
                        </li>
                    </ul>
                </li>
            </ul>
        </li>
    </ul>
</div>

JS:

 response.seasons.forEach(function (season, seasonIndex) {
    axios.get('api requested uri').then(function (season) {
        self.titles[index].shows[seasonIndex].episodes = season.data.episodes;

        season.data.episodes.forEach(function (episode, episodeIndex) {
            axios.get('api requested uri').then(function (episodes) {
                episodes.data.show_id = show.data.id;
                self.saveEpisode(episodes.data, index, seasonIndex, episodeIndex);
            }).catch(function (error) {
                console.log(error);
            });
        });
    }).catch(function (error) {
        console.log(error);
    });
});


saveEpisode: function (data, index, seasonIndex, episodeIndex) {
    var self = this;
    axios.post(baseUrl + 'save-episode', data).then(function (response) {
        self.titles[index].shows[seasonIndex].episodes[episodeIndex].status = response.data.status;
        self.titles[index].shows[seasonIndex].episodes[episodeIndex].date = response.data.date;
        self.titles[index].shows[seasonIndex].episodes[episodeIndex].year = response.data.year;
        self.titles[index].shows[seasonIndex].episodes[episodeIndex].desc = response.data.desc;
    }).catch(function (error) {
        console.log(error);
    });
}

Response coming from first request being rendered fine, but after that nothing happens. How this can be control with Vue JS. Should I create HTML snippets and append those to div as I receive response from API or is there any other way to achieve this?

data declaration.

data: {
    title: null,
    titles: [],
    type: 'movie'
}

First request is simple ajax request and it passes response data into function, there it's being set.

self.titles[index].shows = response.seasons;
self.titles[index].date = show.data.date;
self.titles[index].desc = show.data.desc;

Thanks.

Narendra Jadhav
  • 10,052
  • 15
  • 33
  • 44
Mubin
  • 4,325
  • 5
  • 33
  • 55
  • Can you show your data declaration? Also, which one is the code about the "first request" and the code about the "after"? This is a key detail – acdcjunior Mar 30 '18 at 23:43
  • @acdcjunior updated the question with mentioned key details. – Mubin Mar 31 '18 at 06:01
  • I see there is a close request as well, it's a genuine issue that I faced during my code, and I guess SO is the right place to ask help for troubles of this sort. I really tried my best to solve it; but wasn't able to. – Mubin Mar 31 '18 at 06:03
  • What is `shows` supposed to be? An array or an object? – acdcjunior Mar 31 '18 at 06:05
  • Can you show an example of the JSON returned by the API request? – acdcjunior Mar 31 '18 at 06:06

1 Answers1

1

You are most probably runing into a Vue's Change Detection/Reactivity caveats. I suggest you give the docs a quick look. It should help you a lot in the long run. This is one of the most common issues when using Vue.

The general/safe solution right now would be to always use Vue.set() instead of setting/creating properties in datas objects.

For example, instead of:

self.titles[index] = {some: value}; // supposing nothing existed at position `index`

Do:

Vue.set(self.titles, index, {some: value}); // now value updates

It is not necessary to always use Vue.set() (it is really only need when creating/adding new properties), but without looking closely at every point of your code that sets data, it is impossible to know where it is dispensable.

There are some workarounds, like:

saveEpisode: function(data, index, seasonIndex, episodeIndex) {
    var self = this;
    axios.post(baseUrl + 'save-episode', data).then(function(response) {
        var currentTitle = self.titles[index];            // get the value from the `data`s object
        self.titles[index] = null;                        // important: erase the property

        currentTitle.shows[seasonIndex].episodes[episodeIndex].status = response.data.status;
        currentTitle.shows[seasonIndex].episodes[episodeIndex].date = response.data.date;
        currentTitle.shows[seasonIndex].episodes[episodeIndex].year = response.data.year;
        currentTitle.shows[seasonIndex].episodes[episodeIndex].desc = response.data.desc;

        Vue.set(self.titles, index, currentTitle);        // set it back using Vue.set()
    }).catch(function(error) {
        console.log(error);
    });
}

But, in this case, ideally, episodes would already be reactive and you would use Vue.set to add its new index.

tony19
  • 125,647
  • 18
  • 229
  • 307
acdcjunior
  • 132,397
  • 37
  • 331
  • 304