Future versions of Ember will be released as ES2015 modules, so we'll be
able to import Ember.computed
directly as computed
. This includes
computed.alias
or computed.bool
, should be set to alias
and
bool
, respectively. Do not use extend prototype syntax
// Good
var computed = Ember.computed;
var alias = computed.alias;
var attr = DS.attr;
var Model = DS.Model;
export default Model.extend({
firstName: attr('string'),
lastName: attr('string'),
surname: alias('lastName'),
fullName: computed('firstName', 'lastName', function() {
// Code
})
});
// Bad
export default DS.Model.extend({
firstName: DS.attr('string'),
lastName: DS.attr('string'),
fullName: Ember.computed('firstName', 'lastName', function() {
// Code
}),
fullNameBad: function() {
// Code
}.property('firstName', 'lastName')
});
export default Component.extend({
// Defaults
tagName: 'span',
// Single line CP
post: alias('myPost'),
// Multiline CP
authorName: computed('author.firstName', 'author.lastName', function() {
// Code
})
actions: {
someAction: function() {
// Code
}
}
});
Define your object's default values first.
Define single line computed properties (thing: alias('myThing')
)
after default values
Multi-line computed properties should follow your single line CPs.
Define your route/component/controller's action last, to provide a common place that actions can be found.
Unless you want to change an object's init
function, perform actions
by hooking into the object's init
hook via on
. This prevents you
from forgetting to call _super
. Here is why you shouldn't override
init.
Store local components within their pod, global components in the
components
structure
app
application/
template.hbs
route.js
blog/
index/
blog-listing/ - component only used on the index template
template.hbs
route.js
template.hbs
route.js
comment-details/ - used within blog templats
component.js
template.hbs
components/
tag-listing/ - used throughout the app
template.hbs
post/
adapter.js
model.js
serializer.js
For consistancy and ease of discover, list your query params first in your contoller. These should be listed above default values.
ObjectController is presently deprecated, and ArrayController will be as
well. Controllers are not going to be used in Ember 2.0, so by using
Controller
, you will make it easier to migrate to 2.0.
It provides a cleaner code to name your model user
if it is a user. It
is more maintainable, and will fall in line with future routable
components
export default Controller.extend({
user: alias('model')
});
Always use components. Parials share scope with the parent view, use components will provide a consistent scope.
Use block syntax instead of in
syntax with block helpers
Contents of your each blocks should be a single line, use components when more than one line is needed. This will allow you to test the contents in isolation via unit tests, as your loop will likely contain more complex logic in this case.
The model hooks are async hooks, and will wait for any promises returned to resolve. An example of this would be models needed to fill a drop down in a form, you don't want to render this page without the options in the dropdown. A counter example would be comments on a page. The comments should be fetched along side the model, but should not block your page from loading if the required model is there.
Even though Ember Data can be used without using explicit types in
attr
, always supply an attribute type to ensure the right data
transform is used.
// Good
export default Model.extend({
firstName: attr('string'),
jerseyNumber: attr('number')
});
// Bad
export default Model.extend({
firstName: attr(),
jerseyNumber: attr()
});
Group attributes, relations, then computed properties. Organize each subgroup alphabetically.