3

I'm giving Vue.js a try and so far I'm loving it because it's much simpler than angular. I'm currently using vue-router and vue-resource in my single page app, which connects to an API on the back end. I think I've got things mostly working with a the primary app.js, which loads vue-router and vue-resource, and several separate components for each route.

Here's my question: How do I use props to pass global data to the child components when the data is fetched using an asynchronous AJAX call? For example, the list of users can be used in just about any child component, so I would like the primary app.js to fetch the list of users and then allow each child component to have access to that list of users. The reason I would like to have the app.js fetch the list of users is so I only have to make one AJAX call for the entire app. Is there something else I should be considering?

When I use the props in the child components right now, I only get the empty array that the users variable was initialized as, not the data that gets fetched after the AJAX call. Here is some sample code:

Simplified App.js

var Vue = require('vue');

var VueRouter = require('vue-router')
Vue.use(VueRouter);
var router = new VueRouter({
    // Options
});

router.map({
    '*': {
        component: {
            template: '<p>Not found!</p>'
        }
    },
    '/' : require('./components/dashboard.js'),
});

Vue.use(require('vue-resource'));

var App = Vue.extend({
    ready: function() {
        this.fetchUsers();
    },

    data: function() {
        return {
            users: [],
        };
    },

    methods: {
        fetchUsers: function() {
            this.$http.get('/api/v1/users/list', function(data, status, response) {
                this.users = data;
            }).error(function (data, status, request) {
                // handle error
            });
        }
    }
});

router.start(App, '#app')

Simplified app.html

<div id="app" v-cloak>
    <router-view users = "{{ users }}">
    </router-view>
</div>

Simplified dashboard.js

module.exports = {
    component: {
        ready: function() {
            console.log(this.users);
        },

        props: ['users'],
    },
};

When dashboard.js gets run, it prints an empty array to the console because that's what app.js initializes the users variable as. How can I allow dashboard.js to have access to the users variable from app.js? Thanks in advance for your help!

p.s. I don't want to use the inherit: true option because I don't want ALL the app.js variables to be made available in the child components.

2 Answers 2

4

I believe this is actually working and you are being misled by the asynchronous behavior of $http. Because your $http call does not complete immediately, your console.log is executing before the $http call is complete.

Try putting a watch on the component against users and put a console.log in that handler.

Like this:

module.exports = {
    component: {
        ready: function() {
            console.log(this.users);
        },

        props: ['users'],

        watch: {
            users: {
                handler: function (newValue, oldValue) {
                    console.log("users is now", this.users);
                },
                deep: true
            }
        }
    }
};
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for the suggestion. I tried what you said, and the "users is now..." never gets fired :-(
Any errors in the Javascript console? And what version of Vue are you using?
No errors in the JS console. Vue.js v0.12.12, latest that's pulled in from npm.
Actually, David, you're my hero! There was a stupid mistake I made on my end. The answer you gave was right on!
3

In the new version of Vue 1.0.0+ you can simply do the following, users inside your component is automatically updated:

<div id="app" v-cloak>
    <router-view :users="users"></router-view>
</div>

Comments

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.