If you're in the midst of transitioning your classic classes (those that call .extend()
) to native classes, it may be helpful to know that you can still use the @action
and @tracked
decorators in classic classes.
Using @action
in Classic Classes
We can refactor our classic classes to use the @action
decorator so that we can stop using the actions
hash and the action
helper and remove the quotes from our action names in our templates.
Before
import Controller from '@ember/controller';
export default Controller.extend({
actions: {
handleClick() {
console.log('clicked');
},
},
});
<button type="button" onclick=>
Click me
</button>
After
import Controller from '@ember/controller';
import { action } from '@ember/object';
export default Controller.extend({
handleClick: action(function () {
console.log('clicked');
}),
});
<button type="button" >
Click me
</button>
If you need to curry arguments, you can use the fn
helper:
import Controller from '@ember/controller';
import { action } from '@ember/object';
export default Controller.extend({
handleClick: action(function (foo, bar) {
console.log('clicked', foo, bar);
}),
});
<button type="button" >
Click me
</button>
Using @tracked
in Classic Classes
We can refactor our classic classes to use the @tracked
decorator so that we don't need to call this.set()
.
Before
import Controller from '@ember/controller';
export default Controller.extend({
appName: 'Foo',
actions: {
handleClick() {
this.set('appName', 'Bar');
},
},
});
<h1>Welcome to </h1>
<button type="button" onclick=>
Click me
</button>
After
import Controller from '@ember/controller';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
export default Controller.extend({
appName: tracked({ value: 'Foo' }),
handleClick: action(function () {
this.appName = 'Bar';
}),
});
<h1>Welcome to </h1>
<button type="button" >
Click me
</button>
If the initialization of your tracked property involves some logic like using a service as opposed to a static value, you can pass in an initializer
function instead of value
:
import Controller from '@ember/controller';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
import { inject as service } from '@ember/service';
export default Controller.extend({
appName: tracked({
initializer() {
return this.store.peekRecord('setting', 1).siteName;
},
}),
handleClick: action(function (foo, bar) {
this.appName = 'Bar';
}),
});