Adopting Ember Octane's Native Class Syntax for Cleaner Components
Learn how Ember Octane's native class syntax cuts boilerplate in components, with a worked toggle‑button example, version requirements, and migration tips.
13 Feb 2026, 22:37 UTC

Problem: Boilerplate in Classic Ember Components
Before Ember Octane, components were defined with Ember.extend. This required repetitive boilerplate for declaring properties, actions, and lifecycle hooks, making the code harder to scan and maintain.
Thesis: Native Class Syntax Reduces Boilerplate
Ember Octane introduces ES6 class syntax, decorators, and tracked properties. By using @argument, @tracked, and plain class methods, you can write components that are shorter, clearer, and aligned with modern JavaScript.
Defining a Component with Native Classes
To create a component that uses the new syntax, run the Ember CLI generator with the --native-class flag. This scaffolds a file that already contains the class decorators you need.
# Run from your Ember project root
ember generate component my-toggle --native-class
The generated app/components/my-toggle.js will look like this:
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
export default class MyToggleComponent extends Component {
@tracked isOn = false;
@action
toggle() {
this.isOn = !this.isOn;
}
}
The template (app/components/my-toggle.hbs) can then use the class fields directly:
<button {{on "click" this.toggle}}>
{{#if this.isOn}}ON{{else}}OFF{{/if}}
</button>
{{yield this.isOn}}
Worked Example: Toggle Button Component
Imagine a toolbar where you need a button that toggles a feature on and off and also yields its state to a parent component for further logic.
- Generate the component as shown above.
- Verify the file contents – open
app/components/my-toggle.jsand confirm the class definition,@trackedproperty, and@actiondecorator. - Run the unit test (the generator also creates a test file):
The test should pass, confirming that clicking the button togglesember test --filter 'my-toggle component'isOnand the action fires. - Manual check – start the dev server (
ember serve), navigate to a route that uses{{my-toggle}}, and observe the button label change between ON and OFF.
Trade‑off and Limitations
While native‑class components simplify new code, they are not a drop‑in replacement for every legacy component:
- Ember version requirement – you need Ember 3.13 or later (the Octane edition). Earlier releases lack decorator support and the
@glimmer/trackingpackage. - Addon compatibility – some older addons still rely on
Ember.extendhooks or expect a classic component instance. If you encounter runtime errors after converting a component, check the addon’s documentation for Octane support or consider keeping that component classic until the addon is updated. - Gradual migration – you can mix classic and native components in the same application. Start new features with the native syntax and refactor existing components only when you have sufficient test coverage.
Actionable Closing
To begin using Ember Octane’s native class syntax today:
- Confirm your environment:
ember -vshould output 3.13 or higher. - Generate new components with
--native-class. - For existing components, apply the same pattern: replace
Ember.extendwith a class, add@trackedfor reactive state, and use@actionfor methods. - Run your test suite frequently to catch any incompatibilities early.
By adopting the native class syntax, you reduce boilerplate, improve readability, and align your Ember codebase with modern JavaScript practices—while still being able to ship incremental changes safely.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.