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.

5
  • 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 Commented Mar 30, 2018 at 23:43
  • @acdcjunior updated the question with mentioned key details. Commented Mar 31, 2018 at 6: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. Commented Mar 31, 2018 at 6:03
  • What is shows supposed to be? An array or an object? Commented Mar 31, 2018 at 6:05
  • Can you show an example of the JSON returned by the API request? Commented Mar 31, 2018 at 6:06

1 Answer 1

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.

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

1 Comment

I'm new to Vue, need to learn a lot of things. TY for your awesome answer :)

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.