Using {{action}} to target an event on a different route

Assuming I have an event route like

App.FooRoute = Ember.Route.extend({
  events: {
    anAction: function(){
    }
  }
})

      

How can I call it from the view of another route / controller?

<a {{action anAction target='???'}}> a link </a>

      

+3


source to share


2 answers


Let's say you have routes like this:

App.Router
  |
  + FooRoute
  |
  + BarRoute

      

What would it mean to send an action from FooRoute

to BarRoute

? The user switched to /foo

, so the parameters FooModel

, FooController

and FooView

were initialized, but Bar*

there are no tags . What will the action do?

Case 1: Action manipulates a bar

In this case, the condition BarModel

is a prerequisite for FooRoute

. The most common way to solve this problem is to use nested routes:

App.Router.map(function() {
  this.resource('bar', function() {
    this.route('foo');
  }
});

      

The user navigates to /bars/123/foo

and clicks on the link, calling anAction

. Ember will automatically trigger this action down the route hierarchy, so you can simply define anAction

on BarRoute

.

Case 2: action does not require a bar

In this case, the absence of a is BarModel

not required. anAction

does some things that are not actually related to Foo

, but not related to Bar

. We can use the same bubble trick, but instead of defining anAction

on, BarRoute

we define it on the main router.



Case 3: the action requires a global object

Let's say the action requires the "current user". This case is a lot like # 2 in that you don't need to insert routes. However, this requires having a globally addressable controller eg App.currentUserController

. You can directly specify it as target

{{action}}

.

Case 4: Do You Really Want To Target The BarController

If none of the above options are appropriate, you can use controllerFor

to set the property barController

to FooController

:

App.FooRoute = Ember.Route.extend({
  setupController: function(controller) {
    var barController = this.controllerFor('bar');
    controller.set('barController', barController);
  }
});

      

Then you can do {{action anAction target=barController}}

.

Summary

Ember will automatically try the action against the controller and then raise the route hierarchy. If the models depend on other models, you might need nested routes or global controllers to make sure your preconditions are connected.

+2


source


As explained in the Ember Docs , you can use a built-in mixing called Ember.ViewTargetActionSupport to dispatch actions to another controller or view or route in your application.

A simple way to solve your problem is as follows:

  • An event called in the template is processed in the current view
  • This view has an Em.ViewTargetActionSupport mixed in
  • This event, written in your opinion, calls the this.triggerAction function defining the action you are trying to call in another view / controller / route (target)

Current template:

<a {{action 'actionInView' target='view'}}>Click me</a>

      



View:

App.CurrentView = Em.View.extend(Em.ViewTargetActionSupport, { // Note the mixin
  actions: { // Actions hash
    actionInView: {
      this.triggerAction({ // Without a target this will bubble through the routes
        action: 'theActionToCall', // Name of the action you *actually* want to call
        target: App.TargetController, // Or whatever the name of your target is
      });
    },
  },
});

      

Target controller:

App.TargetController = Em.ObjectController.extend({
  actions: {
    theActionToCall: {
      // This is where you do the action stuff that you *actually* are trying to do
    },
  },
});

      

Basically, the action called actionInView doesn't mean anything, but it invokes the action you really want but can't access because it's in a different part of your application. I do not specify the target, then you can put the action on the parent route or the application route and it will be called.

0


source







All Articles