vue.jsvue-componentlaravel-spark

Vue-multiselect inconsistent reactive options


So I'm building an application using Laravel Spark, and therefore taking the opportunity to learn some Vue.js while I'm at it.

It's taken longer for me to get my head around it than I would have liked but I have nearly got Vue-multiselect working for a group of options, the selected options of which are retrieved via a get request and then updated.

The way in which I've got this far may well be far from the best, so bear with me, but it only seems to load the selected options ~60% of the time. To be clear - there are never any warnings/errors logged in the console, and if I check the network tab the requests to get the Tutor's instruments are always successfully returning the same result...

I've declared a global array ready:

var vm = new Vue({
    data: {
        tutorinstruments: []
    }
});

My main component then makes the request and updates the variable:

    getTutor() {
        this.$http.get('/get/tutor')
            .then(response => {
                this.tutor = response.data;
                this.updateTutor();
            });
    },

    updateTutor() {
        this.updateTutorProfileForm.profile = this.tutor.profile;
        vm.tutorinstruments = this.tutor.instruments;
    },

My custom multiselect from Vue-multiselect then fetches all available instruments and updates the available instruments, and those that are selected:

    getInstruments() {
        this.$http.get('/get/instruments')
            .then(response => {
                this.instruments = response.data;
                this.updateInstruments();
            });
    },

    updateInstruments() {
        this.options = this.instruments;
        this.selected = vm.tutorinstruments;
    },

The available options are always there.

Here's a YouTube link to how it looks if you refresh the page over and over

I'm open to any suggestions and welcome some help please!


Solution

  • Your global array var vm = new Vue({...}) is a separate Vue instance, which lives outside your main Vue instance that handles the user interface.

    This is the reason you are using both this and vm in your components. In your methods, this points to the Vue instance that handles the user interface, while vm points to your global array that you initialized outside the Vue instance.

    Please check this guide page once more: https://v2.vuejs.org/v2/guide/instance.html

    If you look at the lifecycle diagram that initializes all the Vue features, you will notice that it mentions Vue instance in a lot of places. These features (reactivity, data binding, etc.) are designed to operate within a Vue instance, and not across multiple instances. It may work once in a while when the timing is right, but not guaranteed to work.

    To resolve this issue, you can redesign your app to have a single Vue instance to handle the user interface and also data.

    Ideally I would expect your tutorinstruments to be loaded in a code that initializes your app (using mounted hook in the root component), and get stored in a Vuex state. Once you have the data in your Vuex state, it can be accessed by all the components.

    Vuex ref: https://vuex.vuejs.org/en/intro.html

    Hope it helps! I understand I haven't given you a direct solution to your question. Maybe we can wait for a more direct answer if you are not able to restructure your app into a single Vue instance.