Recently, while working on an Ember.js app, I found that I wanted to create a reusable component that manages the editable state of content within it. That is, it would start out by displaying information (initializing its isEditing binding to false), and provide an “Edit” button that would set isEditing to true, so the content wrapped in the component could display its editing interface.
Naturally, I then wanted a way to “subclass” my EditableComponent so that I could create (for example) an AddressComponent that would display a mailing address read-only but allow you to edit it. What I struggled with was finding the best way to pull this off.
I had a few different ideas, two of which didn’t work.
Subclassing the Component
Given my background is stronger with frameworks like UIKit on iOS, subclassing the component initially seemed like a reasonable way to mentally model things. Unfortunately, this is not how Ember is designed.
Although it would be a good approach to influence the behavior of the component, such as described in this Ember.js guide, it does not appear to be a valid approach for my goal. Rather than tweak the base component, I’m interested in using it to build an entirely new one.
Using the Editable Component’s Template as a Layout
It would have been possible to use the template for the editable component as a layout for the address component. This would have saved me from duplicating the editable template code, but it would not have saved me from duplicating the logic contained in the editable component.
One work around would have been to move the logic into a mixin that the address component could include, but that precludes being able to use the editable component in a one-off setting, something that I found desirable.
Using the Component within the New Component’s Template
This was how I actually wrote the Address component. It turns out to be the simplest way to achieve this, too.
Unfortunately, there were two problems:
- I needed to explicitly bind all properties on the editable component that I wanted to expose to users of the address component. Depending on your perspective, this may not be a problem at all. In this case, I hardly minded it.
- This will affect the resulting markup used in your app. There will be an extra container (for the address component) that only includes the editable component inside it, which in turn contains the content. With some experimentation, I found that you can set `tagName: “”`, which will cause the component to render without being wrapped in an HTML element. I certainly wouldn’t recommend this, however, as reading the source for Ember seems to indicate that this behavior is not explicitly intended.
I’m not certain that I found the absolute best way to achieve my goal, but it certainly got the job done relatively cleanly. If you have a better solution, I’d love to hear about it.