简体   繁体   中英

How do I call a controller action from an Ember route while doing a transition?

My objective is to display a fancy "loading..." graphic on my page while Ember fetches model data through the Ember route.

This led me to http://emberjs.com/guides/routing/loading-and-error-substates/ . That inspired me to create an action on my page's controller which would show the "loading" overlay window in the DOM. For example, here's my controller:

controllers/users.js:

export default Ember.ArrayController.extend({
    ...
    actions: {
        displayLoading: function() {
            // Show the DOM element that says "Loading..."
        },
        ...
    }
});

I'd like to call that while my data is loading, so I then define a route as follows:

routes/users.js:

export default Ember.Route.extend({
    model: function( params ) {
        return this.store.find('user', params );
    },

    actions: {
        loading: function(transition, originRoute) {
            transition.send('displayLoading');
        }
    }
});

But when I do this, I get this error:

Uncaught Error: Nothing handled the action 'displayLoading'. If you did handle the action, this error can be caused by returning true from an action handler in a controller, causing the action to bubble.

So my question is where can I define this action so that my loading method will be able to call it?

Note that trying this.send('displayLoading') gave me this error:

Can't trigger action 'displayLoading' because your app hasn't finished transitioning into its first route. To trigger an action on destination routes during a transition, you can call .send() on the Transition object passed to the model/beforeModel/afterModel hooks. .

Update: I am able to catch this action on the route itself, but then I still can't call the action on my controller.

Update #2: Thanks to @kingpin2k's answer, I've resolved this. For those interested, here is a full solution:

controllers/users.js:

export default Ember.ArrayController.extend( {
    actions: {
        showLoading: function() {
            this.set('isLoading', true);
        },

        hideLoading: function() {
            this.set('isLoading', false);
        },
    }
});

routers/users.js:

export default Ember.Route.extend({

    model: function( params ) {
        return this.store.find('user', params );
    },

    actions: {
        loading: function() {
            this.controllerFor('users').send('showLoading');
        },
        didTransition: function() {
            this.controllerFor('users').send('hideLoading');
        }
    }

});

A key insight was that I can set an isLoading property on my controller which determines whether my modal "Loading..." window is showing in the Handlebars template.

use controllerFor , http://emberjs.com/api/classes/Ember.Route.html#method_controllerFor

    loading: function(transition, originRoute) {
        var controller = this.controllerFor('foo');
        controller.send('displayLoading');
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM