January 16, 2016

The advice to avoid attrs is still relevant as of Ember 2.12, and until angle bracket components are released in Ember.

In this post I will attempt to explain why you should avoid using attrs in your Ember.js application code.

tl;dr attrs is a Glimmer Component thing, and Glimmer Components haven’t landed on stable Ember.js yet.

First, a bit of background on why attrs appeared. Currently we have a kind of component that is invoked with handlebars (curly braces), like this:

{{my-component}}

These have been around for a while, so for the sake of distinction we’ll call them Classic Components. Then, in the much mentioned Road to Ember 2.0 RFC and related blog post, a new kind of component was introduced that uses HTML-like invocation, like so:

<my-component>

Previously slated to land on the 1.x series, it has been postponed until some serious flaws are addressed. While they were first referenced as angle bracket components, we will be calling them Glimmer Components.

This distinction is relevant for our subject because Glimmer Components have slightly different semantics. The two most relevant are that bindings are one-way by default, and that they don’t proxy attribute lookups. What does this mean?

Attributes versus properties #

A component property is something defined internally. In the following code snippet, foo is a property:

export default Ember.Component.extend({ foo: "bar" }};

A component attribute is something passed into the component when invoked. In the following snippet, baz is an attribute:

{{my-component baz="qux"}}

In Classic Components there is no difference between the two, that is what I mean by it proxies lookups. If you do this.get('foo') or this.get('baz') in a Classic Component‘s JavaScript, you will get the proper values.

In Glimmer Components this doesn’t happen. If you have the equivalent:

<my-component baz="qux">

Then in the JavaScript file you would access it with this.attrs.baz .

Back to attrs #

So, why shouldn’t you use attrs in Classic Components? Because in Classic Components attrs already existed, and is used internally to manage component bindings and might not be exactly what you need. While you should be mostly fine using it for actions, you’ll have problems if you use it for attributes, so it’s easier to use the current APIs than to keep this in mind.

I have put together an Ember Twiddle to showcase how to do action-related logic without the use of attrs .

I hope this has been useful. You can reach me on the Slack channel for further discussion.

368 Kudos