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';
}),
});
