# Calling a route action from a component fails

**URL:** <https://discuss.emberjs.com/t/calling-a-route-action-from-a-component-fails/14687>\
**Category:** Questions\
**Created:** [May 2, 2018, 3:52pm UTC](https://discuss.emberjs.com/t/calling-a-route-action-from-a-component-fails/14687 "2018-05-02T15:52:38Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![belgoros](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/belgoros/32/16101_2.png) [@belgoros](https://discuss.emberjs.com/u/belgoros)\
**Post date:** [May 2, 2018, 3:52pm UTC](https://discuss.emberjs.com/t/calling-a-route-action-from-a-component-fails/14687/1 "2018-05-02T15:52:38Z")

</div>

I tried to use `sendAction` to call another route action from component like [that](https://medium.com/developer-paradise/ember-send-and-sendaction-5e6ac9c80841):

```auto
# components/holiday-hour.js

actions: {
...
    deleteHoliday(holiday) {
      this.sendAction('deleteHoliday', holiday);
    },
  }

```

I have `deleteHoliday` action defined in `holiday-hours.js`router:

```auto
# routes/holiday-hours.js

actions: {
...
deleteHoliday(holiday) {
      console.log('ROUTE-> deleteHoliday called');
      let holidayToDelete = this.store.peekRecord('holiday-hour', holiday.get('id'));
      holidayToDelete.destroyRecord().then(function() {
        this.get('flashMessages').success(route.get('i18n').t('flash.holiday.removed'));
      });
    },

```

Here is how the action is triggered from the component template:

```auto
# templates/components/holiday-hour.hbs

<button type="button" class="btn btn-danger btn-sm mt-1" {{action 'deleteHoliday' holiday}}>
      <span class="oi oi-trash"></span>
</button>

```

And it is never called ☹ What is wrong with that ? Thank you.

---

<div class="post-metadata">

**Author:** ![larryh](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/larryh/32/16498_2.png) [@larryh](https://discuss.emberjs.com/u/larryh)\
**Post date:** [May 3, 2018, 12:52pm UTC](https://discuss.emberjs.com/t/calling-a-route-action-from-a-component-fails/14687/2 "2018-05-03T12:52:41Z")

</div>

Hi,

Contrary to what the doc that your link pointed to says, and this snippet from an Ember book:

_sendAction(‘onClick’, …) sends the action name passed in to the component (updateRating in the above case) with some optional parameters. That action will be handled by the first handler on the “controller, then current route, then active routes” path. In our case, the bands.band.songs route will have the privilege to do so._

It looks like the action must be defined in the controller, not the route.

For example, I have a component and added the following _anAction_ param to to the way I called it:

```
{{users/settings-form user=model
                  selectedState=(user/select-state model)
                  anAction=(action 'myAction')
                  onSubmit=(action 'register')}}

```

Then I called it from my component, thusly:

```
  this.sendAction('anAction');

```

When I put the _myAction_ handler in the controller it works fine:

```
    myAction() { alert('got it'); },

```

However, when I remove that action from the controller and put it in the route, my app doesn’t even display the page due to the following error:

```
Error: Assertion Failed: An action named 'myAction' was not found in <bnc@controller:users/register::ember487>

```

I have been burned on this before, and have found it confusing as to what the rules actually are for calling actions _from components_.

For example, there was a long discussion in here ([Where should I define a `save` action? - #2 by tristanpendergr](https://discuss.emberjs.com/t/where-should-i-define-a-save-action/5062/2)) about this very issue. People went back and forth about whether or not the action(s) should be defined in the controller or the route… but that discussion struck me as moot when dealing with components, because in that case it seems that the only option is to put the action in the controller.

Also, it seems to me that _sendAction_ is kinda sorta deprecated in favor of _closure actions_. From that same book:

_From Ember 1.13 onward, there is another way to trigger actions. Instead of passing in an action name (a string) to the component, a function, returned by a call to the action helper can be passed in._

And here is the example he gives, with the old _string way_ and the new _closure action_ way:

```
{{star-rating item=song rating=song.rating onClick="updateRating"}}

{{star-rating item=song rating=song.rating on-click=(action "updateRating")}}

```

In this (closure) way, he points out that the action _must_ live in the controller:

_The action helper looks up the provided name in the actions object of the current context, in this case the controller and creates an action function from it encapsulating the current context (hence the name, “closure action”)._

I’m just starting out, so I’d love to hear what someone more knowledgeable than I has to say on this subject.

---

<div class="post-metadata">

**Author:** ![larryh](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/larryh/32/16498_2.png) [@larryh](https://discuss.emberjs.com/u/larryh)\
**Post date:** [May 3, 2018, 1:01pm UTC](https://discuss.emberjs.com/t/calling-a-route-action-from-a-component-fails/14687/3 "2018-05-03T13:01:25Z")

</div>

Ah, shoot. Looking over my post I see where I might have made an error: The param I set _anAction_ to in the call to my component was a closure action, which means it has to live in the controller.

I was thinking that using _sendAction_ would give me the _controller → current route → active routes_ lookup path, but I guess I am wrong.

The operative word being “guess” =\> I’m leaving the original post the way it was, and maybe someone can clear this up - which will hopefully answer your original question as well.

The good thing about this discussion forum is that the answers will live forever =\> I doubt we will be the only 2 people who benefit from getting this question answered.

Thanks!

---

<div class="post-metadata">

**Author:** ![belgoros](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/belgoros/32/16101_2.png) [@belgoros](https://discuss.emberjs.com/u/belgoros)\
**Post date:** [May 3, 2018, 1:26pm UTC](https://discuss.emberjs.com/t/calling-a-route-action-from-a-component-fails/14687/4 "2018-05-03T13:26:57Z")

</div>

> [@larryh](#):
>
> {{star-rating item=song rating=song.rating onClick=“updateRating”}}

Thank you for your response. It is still unclear for me. The difference with the latest [docs](https://guides.emberjs.com/v3.1.0/components/triggering-changes-with-actions/) and the latest [RARWE book](https://balinterdi.com/rock-and-roll-with-emberjs/) it that it is all about a click on a component itself or using services.

I wonder if the design I use is correct:

- display a holidays rows in `holiday-rows.hbs` template
- each row is represented by a component `holiday-row.hbs`
- each row contains a button to delete the row the button _belongs to_

I prefer to have all the application scoped actions (like create, delete, update, etc.) to be defined in a route.

---

<div class="post-metadata">

**Author:** ![belgoros](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/belgoros/32/16101_2.png) [@belgoros](https://discuss.emberjs.com/u/belgoros)\
**Post date:** [May 4, 2018, 7:35am UTC](https://discuss.emberjs.com/t/calling-a-route-action-from-a-component-fails/14687/5 "2018-05-04T07:35:37Z")

</div>

I’m trying to apply `closure actions` way to do that but still no success:

```auto
#templates/holiday-hours.hbs
...
{{#each model as |holidayHour|}}
        {{holiday-hour holiday=holidayHour shouldDisplayDeleteIcon=true deleteHoliday=(action 'deleteHoliday' holidayHour)}}
{{/each}}

```

Then in the component:

```auto
#components/holiday-hour.js

export default Component.extend({
...
  actions: {
    deleteHoliday(holiday) {
      this.get('deleteAction')(holiday);
    }
... 

```

The I defined the action in the route:

```auto
#routes/holiday-hours.js
export default Route.extend(AuthenticatedRouteMixin, {
...
    actions: {
      deleteHoliday(holiday) {
         console.log('ROUTE-> deleteHoliday called: state->' + holiday.get('state'));
....

```

Hoped that the action will be called in the corresponding route but it"s not the case, - Ember is trying to find it in the controller:

```auto
Assertion Failed: An action named 'deleteHoliday' was not found in <decastore-front@controller:holiday-hours::ember605>

```

Does it exist a way to call an upper layer action, - not from the controller but from the route ? Or to call a route action from the corresponding controller action ? Or the only way is to use [ember-route-action-helper](https://github.com/dockyard/ember-route-action-helper) ?

---

<div class="post-metadata">

**Author:** ![larryh](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/larryh/32/16498_2.png) [@larryh](https://discuss.emberjs.com/u/larryh)\
**Post date:** [May 4, 2018, 12:23pm UTC](https://discuss.emberjs.com/t/calling-a-route-action-from-a-component-fails/14687/6 "2018-05-04T12:23:52Z")

</div>

Using closure actions is the wrong way to go: doing so means that the action handler _must live in the controller_, not the route.

I think the mistake I made earlier boiled down to something like this: I assumed that the _way I called_ the method would determine the lookup path, i.e. using _sendAction_ meant the path would be _controller → current route → active routes_, but that was wrong.

What determines the lookup path is not how you call it, but _what you call it with_. Since the argument was a _closure action_, that meant the handler _must_ live in the controller.

(Don’t ask me why because I don’t know. But it is one of those annoying aspects of programming that causes all of us to waste too much time: the problems you are experiencing _have nothing to do with your domain logic_, rather they are the result of the underlying implementation details.

Kinda like how programmers long ago had to deal with segmented memory in their code - had _nothing_ to do with anyone’s problem domain, but had to be dealt with, nevertheless.) (And boy, was it a pita!)

Anyway, I think your first approach was pretty close; I think the only problem was the _way you called your component_, which you did not list (so I’m not sure).

Here is an example using different names, because I find that repeating the same name for both attribute and argument, i.e. _deleteHoliday_, only serves to confuse things. (At least it confuses me.)

In the template that calls the component, pass in the name of the route action-handler _as a string_:

```
{{myComponent myAction="myDelete"}}

```

In the component’s template do what you originally did:

```
<button type="button" ~~~{{action "deleteHoliday" holiday}}~~~ >

```

In the component’s JS file:

```
actions: {
    deleteHoliday(holiday) {
       this.sendAction("myAction", holiday);
   }
}

```

And finally, in the route:

```
actions: {
    myDelete(holiday) {
       <delete holiday>
   }
}

```

I hope that’s right and that it solves your problem. Good luck!

---

<div class="post-metadata">

**Author:** ![belgoros](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/belgoros/32/16101_2.png) [@belgoros](https://discuss.emberjs.com/u/belgoros)\
**Post date:** [May 4, 2018, 12:39pm UTC](https://discuss.emberjs.com/t/calling-a-route-action-from-a-component-fails/14687/7 "2018-05-04T12:39:36Z")

</div>

Thank you for your response. What do you think about the argument raised in this article regarding the use of `sendAction` saying that it had some drawbacks and which is rather old and acts more of an event bus that is not very efficient ?

---

<div class="post-metadata">

**Author:** ![larryh](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/larryh/32/16498_2.png) [@larryh](https://discuss.emberjs.com/u/larryh)\
**Post date:** [May 4, 2018, 12:59pm UTC](https://discuss.emberjs.com/t/calling-a-route-action-from-a-component-fails/14687/8 "2018-05-04T12:59:06Z")

</div>

I’m really just starting out, but from what I have gathered, _sendAction_ does seem to fit in “the old way of doing things”, and closure actions, i.e. “the newer way of doing things”, are considered “better” because given the fact that you actually call them means they can return a value that the callee can then use.

But just because it’s old doesn’t mean it’s necessarily bad, or even something to stay away from. I’ve heard of _ember-oute-action-helper_, but have no idea if that’s what people use these days.

Bottom line: someone who has been around ember for enough time to build up some historical context would be much better suited to answer this question.

---

<div class="post-metadata">

**Author:** ![belgoros](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/belgoros/32/16101_2.png) [@belgoros](https://discuss.emberjs.com/u/belgoros)\
**Post date:** [May 4, 2018, 1:14pm UTC](https://discuss.emberjs.com/t/calling-a-route-action-from-a-component-fails/14687/9 "2018-05-04T13:14:34Z")

</div>

> [@larryh](#):
>
> ember-oute-action-helper

I absolutely agree with you (by the way I’m on Ember way for just 2 months as well). As for [ember-route-action-helper](https://github.com/dockyard/ember-route-action-helper), the very first line in their `README` tells:

> You probably don’t need to use this addon. Most of the use cases you’d use this addon for are perfectly achievable without this addon.

So if I don’t find any other solution, I think I’ll have to install this add-on, because there is no clear and documented example in Ember guides on how to get out from this situation.

---

<div class="post-metadata">

**Author:** ![larryh](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/larryh/32/16498_2.png) [@larryh](https://discuss.emberjs.com/u/larryh)\
**Post date:** [May 4, 2018, 1:49pm UTC](https://discuss.emberjs.com/t/calling-a-route-action-from-a-component-fails/14687/10 "2018-05-04T13:49:01Z")

</div>

I certainly feel your pain.

In my first response I included this link [Where should I define a “save” action](https://discuss.emberjs.com/t/where-should-i-define-a-save-action/5062/35) where a long discussion took place on where to put certain actions: in the controller or the route.

But nowhere did they talk about the difficulty of referencing an action in the route _from a component_, which stuck me as odd, given the emphasis on using components.

It seems like there should be a simple, well-documented way to do this, but unfortunately the two of us seem to be missing it. And even though it could be (probably is) our fault, I think it should raise a concern to the ember documentation folks that something this important can’t be figured out by newbies. (And I don’t mean to disparage them; they do a tremendous job on a difficult task on their own time for no pay - something few people are willing to do.)

Maybe someone with more smarts will show us the light. 😄

---

<div class="post-metadata">

**Author:** ![belgoros](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/belgoros/32/16101_2.png) [@belgoros](https://discuss.emberjs.com/u/belgoros)\
**Post date:** [May 4, 2018, 2:02pm UTC](https://discuss.emberjs.com/t/calling-a-route-action-from-a-component-fails/14687/11 "2018-05-04T14:02:33Z")

</div>

Yeah, as a proverb says: ’

> hope springs eternal

🙂

---

<div class="post-metadata">

**Author:** ![belgoros](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/belgoros/32/16101_2.png) [@belgoros](https://discuss.emberjs.com/u/belgoros)\
**Post date:** [May 4, 2018, 2:33pm UTC](https://discuss.emberjs.com/t/calling-a-route-action-from-a-component-fails/14687/12 "2018-05-04T14:33:03Z")

</div>

> [@belgoros](#):
>
> this.get(‘deleteAction’)(holiday);

Anyway, I’ve just tried `ember-route-action-helper`, - it works fine and calls the action defined in the router:

```auto
# templates/holiday-hours.hbs

      {{#each model as |holidayHour|}}
        {{holiday-hour holiday=holidayHour shouldDisplayDeleteIcon=true deleteAction=(route-action 'deleteHoliday' holidayHour)}}
      {{/each}}

```

Then in the component:

```auto
#components/holiday-hour.js

export default Component.extend({
...
  actions: {
    ..
     deleteHoliday(holiday) {
      this.get('deleteAction')(holiday);
    },

```

And finally in the route handler:

```auto
#routes/holiday-hours.js

export default Route.extend(AuthenticatedRouteMixin, {
...
actions: {
  ....
   deleteHoliday(holiday) {
      console.log('ROUTE-> deleteHoliday called:' + holiday.get('state'));
....

```
