Deprecations Added in Ember 5.x
What follows is a list of deprecations introduced to Ember during the 5.x cycle.
For more information on deprecations in Ember, see the main deprecations page.
Deprecations Added in 5.3.0
§ Implicit Route Model
Previously, if no Route#model
hook was specified and a _id
parameter was present, Ember would attempt to figure out how to load that model for you. Specify your own model hook to load from the store, if desired.
An optional feature, called no-implicit-route-model
, can be turned on to clear this deprecation and opt in to the new behaviour. This optional feature is enabled in blueprints as of v5.7.0
and will be removed in v6.0.0
. For more information, see the optional features guides.
For example:
import { Route } from '@ember/routing/route';
import { service } from '@ember/service';
export default class MyModelRoute extends Route {
@service store;
model({ my_model_id }) {
return this.store.findRecord('my-model', my_model_id);
}
}
For more background, read the RFC.
Deprecations Added in 5.9.0
§ Action helper and modifier
Scenario: action
is passed a string
Before:
<button type="button" {{action "plusOne"}}>
Click Me
</button>
After:
<button type="button" {{on 'click' this.plusOne}}>
Click Me
</button>
or, if plusOne
is passed in as an argument:
<button type="button" {{on 'click' @plusOne}}>
Click Me
</button>
If the plusOne
action is in an actions object, it needs to move out:
For Glimmer components
Before:
import Component from '@glimmer/component';
export default class Demo extends Component {
actions = {
plusOne() {
/* ... */
}
}
}
After:
import Component from '@glimmer/component';
import { action } from '@ember/object';
export default class Demo extends Component {
@action
plusOne() {
/* ... */
}
}
or
For Classic Components with native classes
Before:
import Component from '@ember/component';
export default class Demo extends Component {
doMath() {
this.send('plusOne');
}
actions = {
plusOne() {
/* ... */
}
}
}
After:
import Component from '@ember/component';
import { action } from '@ember/object';
export default class Demo extends Component {
doMath() {
this.plusOne();
}
@action
plusOne() {
/* ... */
}
}
or
For Classic Components with EmberObject.extend
Before:
import Component from '@ember/component';
export default Component.extend({
actions: {
plusOne() {
/* ... */
}
}
})
After:
import Component from '@ember/component';
import { action } from '@ember/object';
export default Component.extend({
plusOne: action(function() {
/* ... */
}),
})
If (action)
or {{action}}
is passed a string, it's possible that the referenced method is declared on the caller, and not the immediate component -- that is, (action)
and {{action}}
bubble up the render tree from route templates -> controllers -> routes.
Note that @action
is completely different from (action)
or {{action}}
(and is partly a motivator for deprecating (action)
and {{action}}
, to reduce ambiguity).
@action
binds the this
on the method to the instance of the class.
Scenario: action
is passed a function reference
Before:
<SomeComponent @update={{action this.plusOne}} />
After
<SomeComponent @update={{this.plusOne}} />
Scenario: action
is passed parameters
Before:
<SomeComponent @update={{action this.plus 1}} />
After:
<SomeComponent @update={{fn this.plus 1}} />
Scenario: action
is used with mut
Before:
<SomeComponent @update={{action (mut @value.property}} />
After:
// parent.js
import Component from '@glimmer/component';
import { action } from '@ember/object';
export default class SomeComponent extends Component {
@action
handleUpdate(value) {
this.args.property = value;
}
}
{{! parent.hbs }}
<SomeComponent @update={{this.handleUpdate}} />
Related, Combining function arguments with action functions
For more background, read the RFC
Deprecations Added in 5.10.0
§ Component Template Resolving
There are two types of paths to migrate off the old layouts
- use a currently supported multi-file layout (keeping separate
js
,ts
, andhbs
files) - migrate the component entirely to the latest component format,
gjs
,gts
, (aka<template>
)
There are some tools to help with this:
Specifically, these layouts are no longer supported:
Classic | Pods |
---|---|
|
|
The above example(s) can be migrated to:
{app,addon}/
components/
foo.js
foo.hbs
namespace/
bar.js
bar.hbs
Or using --component-structure=nested
{app,addon}/
components/
foo/
index.js
index.hbs
namespace/
bar/
index.js
index.hbs
Note, however, that classic components importing the layout
and setting it on an @ember/component
will still work.
The key thing being deprecated is the runtime resolution of templates, so if there is an import involved, there is no runtime resolution.