Send an action from application controller to another controller


#1

I have a nav-button component that has an action on it, I want to get that action to bubble up to the watch-list controller, but the nav-button component is rendered inside a navigation-menu component, which is rendered inside the application template. So the bubbling happens up the chain until it reaches the application controller. How can I get it to go to the right controller?


#2

I might be wrong, but I believe as we are moving towards a “controller-less” world in ember, you should put most, if not all, of your “top level” action handlers in the route instead of the controller. If you do this, I’m pretty sure that any sent actions, if not handled by the controller, will start to bubble up the current route hierarchy, starting with the leaf-most route first, so you should be able to handle the action in the watch-list route, before it gets to your application route. And since the watch-list route stores a reference to its controller, you can then send data back down to it as needed.

https://guides.emberjs.com/v1.10.0/templates/actions/#toc_action-bubbling


#3

So from the nav-button what must I do to get the watch-list route to catch the action?

I tried adding return true; in the action handler on the nav-button component but nothing happens, I don’t get anything in the console either.


#4

When the action is invoked, is your current route the watch-list route (i.e. the url is something like myapp.com/watch-list)? If it is, you should just be able to edit the watch-list.js route to include an handler for that action, which will be called as long as the application controller isn’t already handling the action (or if it is, it must return true to cause the action to bubble up to the routes).

If you want, you can post the relevant code in those files (the nav-button component, watch-list route, application controller, ect), to make it easier for us to see whats going on.


#5

Just got word from the team that may change the way this is being done, lol so I may not need it. I’m gonna post the code real quick however because I think this is good info to know.

This is a bit complicated so hopefully it’s easy to follow

I am using this dynamic-link addon for a dynamic-link component that can change from a link-to to an action.

That is rendered inside the nav-button component like

{{#dynamic-link params=params.linkParams}}
	{{fa-icon icon=params.icon}}
	{{#if params.label.left}}<span class="label label-left">{{params.label.left}}</span><i class="triangle triangle-right"></i>{{/if}}
	{{#if params.text}}<span class="text">{{params.text}}</span>{{/if}}
	{{#if params.label.right}}<i class="triangle triangle-left"></i><span class="label label-right">{{params.label.right}}</span>{{/if}}
{{/dynamic-link}}

The nav-button is defined in the navigation-menu component like

<ul class="primary-navigation-items">
	{{#each navigationService.visibleNavItems as |menuItem|}}
    {{nav-button params=menuItem}}
  {{/each}}
</ul>

The nav items are then defined in the route like soo

activate() {
    this.get('navigationService').set('navigationMenuItems',[
      ...
      Ember.Object.create({
        linkParams:  {
          action: "biddingItems"
        },
        icon: "star",
        size: 60
      }),
      Ember.Object.create({
        linkParams:  {
          action: "watchingItems"
        },
        icon: "exclamation",
        size: 60
      }),
      ...
    ]);
	}

(there is a service that splits this list into two separate arrays, a visible array and an invisible one that goes into an offscreen menu)

The navigation-menu is defined in the application template.

When I click the button with the biddingItems action defined on it, it expects the nav-button component to catch it, and if I define an action, if I use dev tools to break on exceptions (because otherwise it will attempt to follow the link to #) I see the message that was caught as

"<bidr@component:nav-button::ember790> had no action handler for: biddingItems"

But on the route for watch-list (which is the current URL) I have an action handler defined

actions: {
    biddingItems() {
      console.log('bidding items finally')
    }
  }

But it’s not being called at all. I’m starting to wonder if the dynamic-link component may be my source of contention but I’m not positive.


#6

Hmm, what does the actions hash in your nav-button.js component look like, are you handling the biddingItems action there? If not, you may need to add a handler there, then manually send the action up, as the nav-button component may be swallowing the action sent by the dynamic-link. So you might have to do something like this:

//components/nav-button.js
    
actions: {  
    biddingItems: function(myParams) {
        this.sendAction('biddingItems', myParams);
    }
}

#7

It wasn’t, but I just added it, and the link is no longer trying to follow but it appears that it’s also not sending the action up? Do I need to define an action attribute on the nav-button component or something similar?


#8

There also is an application controller defined as well, not sure if that might be messing some things up?