- Start Date: 2020-05-23
- Relevant Team(s): Ember.js
- RFC PR: #632
- Tracking: (leave this empty)
In Ember 1.13 we introduced closure actions, which have been recommended over string based actions. This officially deprecates string based actions in favor of closure actions, which provide many benefits such as
- simpler passing through components
- less need for an actions hash
- ability to return a value
- typing in TypeScript
- more in line with the Octane programming model
We will deprecate the following:
- The
send
api. - The use of a string parameter to the
action
helper. - The use of a string parameter to the
action
modifier.
The send
api may currently be used in components, controllers, and routes.
It is used to target the actions
hash. In calling the actions
hash of the
same object, send
can be replaced by a function call once the method is
moved outside the actions
hash.
For cases where send
is used to go from a controller to a route or from
a route to a parent route, no direct replacement for this "action bubbling"
behavior will be provided.
Instead, users are recommended to inject the router service.
Users will transition to closure actions.
While the action helper and modifiers are still supported with non-string arguments, the refactoring recommendation is to switch to the on modifier and @action decorator directly. It is possible that the action helpers and modifiers will be deprecated in future RFCs.
For example, take this button that sends the foo action with the default click event:
export default Component.extend({
someMethod() {
this.send('actionName');
},
actions: {
actionName() {
// do something
}
}
});
Although this could be refactored to:
export default Component.extend({
someMethod() {
this.actionName();
},
actionName() {
// do something
}
});
Because the action modifier might be deprecated in the future, it is recommended that the code is refactored instead to:
export default Component.extend({
someMethod() {
this.actionName();
},
actionName: action(function() {
// do something
})
});
so that it can eventually become, once refactored to native classes:
export default class extends Component {
someMethod() {
this.actionName();
}
@action
actionName() {
// do something
}
}
For the send api, it is now generally possible to avoid string based actions in the actions hash of any route, because the router service has all the methods that were once only available in routes. If there are any route actions, it is recommended to move them to a component, service, or a controller.
For example, if you currently have a route action accessed by the send
api like this:
// app/routes/some-route.js
actions: {
myAction() {
this.transitionTo('some.other.route');
}
}
and are calling it from using send
in your controller like this:
// app/controllers/some-route.js
someMethod() {
this.send('myAction');
}
You can move the action from the route to the controller:
// app/controllers/some-route.js
export default Controller.extend({
router: service(),
someMethod() {
this.myAction();
}
myAction: action(function() {
this.router.transitionTo('some.other.route');
})
});
In native class syntax, this looks like:
// app/controllers/some-route.js
export default class SomeRouteController extends Controller {
@service router;
someMethod() {
this.myAction();
}
@action
myAction() {
this.router.transitionTo('some.other.route');
}
}
If you are using ember-route-action-helper
, you can instead
move your action from the route to the controller.
From:
// app/routes/some-route.js
export default Route.extend({
actions: {
someRouteAction() {
// do something
}
}
}
To:
// app/routes/some-controller.js
export default class SomeController extends Controller {
@action
someAction() {
// so something
}
}
We already teach closure actions exclusively in the guides. Other than a new deprecation guide, no additional material should be necessary.
Some older applications have thousands of string based actions throughout their codebases. We should consider writing a codemod to ease the transition.
Closure actions are now the standard in Ember, so other alternatives have not been seriously considered.
Can we also deprecate the use of the actions
hash? Can we also deprecate using this.actions
?
Can the target
property of @ember/controller
and @ember/component
be deprecated?