Adding key-up action handlers in routes

I’m trying to add key-up validation to an {{input}} object like so:

{{input placeholder="Email Address" value=model.email type="email" key-up=(action 'fieldUpdated') class="form-control"}}

but when I load the page I get the error:

Error: Assertion Failed: An action named 'fieldUpdated' was not found in (generated contact controller)

I don’t get the error with my button:

<button {{action "fieldUpdated"}} disabled={{sendMessageDisable}} class="btn btn-block btn-primary">What's happening?</button>

I figure this is because it’s a <button> HTML element whereas I’m using an input component. I wish to use a component so I can double bind my data.

Here is my route:

import Route from '@ember/routing/route';

export default Route.extend({
  model(){
    return this.store.createRecord('contact');
  },

  actions: {
    fieldUpdated(model) {
      debugger; //Triggers on button, but not input
    }
  }
});

How can I have the input component trigger the logic in my route?

This sort of logic belongs on the component. Should ‘just work’, too :slight_smile: Lemme know if it doesn’t though :wink:

Ah, ok. I’ll put it in the component. Thanks. :slight_smile:

To add a little more context about the error specifically:

Error: Assertion Failed: An action named 'fieldUpdated' was not found in (generated contact controller)

This suggests that you haven’t defined a controller for this route, so the autogenerated controller is there and it can’t find the action on the controller because you haven’t defined it. Typically a route template only has access to properties and actions defined on the controller, not the route (there’s an addon for route actions). So the error is generated because you’re defining a closure action which does not bubble and it’s not where it needs to be (the controller).

As for why it works on the <button> and not on the {{input}}… on the input it’s trying to create a closure action, which again doesn’t bubble. But on the button it’s using (and I may be confusing terminology here) but the action modifier which works differently by creating a traditional bubbling action. This article has a really great exploration of the differences in action types for further reading. I think you’d also get an error if you did this with the button:

<button {{action "fieldUpdated" bubbles=false}} disabled={{sendMessageDisable}} class="btn btn-block btn-primary">What's happening?</button>

or if you used a closure action:

<button onclick={{action "fieldUpdated"}} disabled={{sendMessageDisable}} class="btn btn-block btn-primary">What's happening?</button>

Anyway, the solution is obviously to put the action on the controller or in a component as @NullVoxPopuli stated. Just thought I’d point out what was happening; it can be worth digging into the reasons behind these (admittedly confusing) behaviors when you run into them.

EDIT: probably also worth noting that closure actions are always the preferred method for creating actions, the old behavior still exists for legacy reasons but should be avoided. IIRC actions as we know they may eventually go away completely in favor of a more flexible and intuitive method binding syntax.