I have been developping with Ember for a couple of months now, embracing the component approach as much as possible and looking forward to the landing of routeable components. Throughout our projects we have seen some common problems arise and slowly came to the conclusion that not all components are born equal. Here are the different patterns I use and what I struggle with. Your opinions are most welcome.
Data down, Actions up (DDAU)
The most idiomatic use. Perfect for small components, the building blocks of any application, and the way they are advertised in Ember.
- They enclose a generic, highly encapsulated, re-usable set of layouts or user interactions.
- They get their data through readonly attributes.
- They send back actions.
Using DDAU components, it is easy to encapsulate generic behaviors. The next step is to use those to build interface blocks. For instance, a post editor. A product review editor. An uploading interface.
When those interface blocks are used in several places, it comes naturally to make them components as well. However, the DDAU model starts to break apart, as upwards actions in the form “change data” explode either in size (if you send the whole dataset in each change action like
sendAction('change', value)) or in number (if you send targeted change actions like
sendAction('change', 'product.translations.en.name', 'Foobar'))
At this point, directly updating the data becomes an almost required step.
So this is how I would define an editor-type component: a component that has exactly one argument it updates automatically (still sending a ‘change’ action up though). Sort of a glorified
When dealing with related data, I often reach a point where I must let the user choose an association. For instance, select the owner of an object from a list. This can be neatly encapsulated in a DDAU component: pass it the current value, the list of options, get a
select action back. Neat.
This model seems to fall short for more complex relations. Current example: I must let the user attach pictures from the picture database. It is huge, so a simple select won’t do.
Now, this picture database is organized: each user can have his personal, private Collections, and may build Galleries for publishing purposes. They provide natural organisation, so for this task of selecting pictures, I want the full deal: a modal split view with Collection and Gallery browser on the left, matching pictures on the right, upload tool on the bottom.
I am still trying to find a proper abstraction for this. Using the DDAU model would mean every-time I have a
picture-select component, the parent component or the controller must pass it the gallery records, the collection records, and the
picture records. And must know how to change the latter everytime the user chooses a gallery or collection in the browser. And must know how to handle uploads and react to dragndrop.
In the end, this is a lot of duplicated code.
How would you handle this? Would it be acceptable to make the
picture-select component directly fetch and save stuff from/to the store?
What if I wanted to add the ability to open the picture editor from the picture selection modal, change a few fields, and come back to the picture selection?
I often find myself wondering where knowledge belongs. For instance, permissions? Suppose an editor should lock some fields depending on what the user can do. Maybe some choices are not available as well.
Should the component itself know this? Should it take
bar-field-readonly arguments? What about a component that shows an array of models?
Structure, structure, structure. Care to share whether you encountered similar problems (or other edge cases for the DDAU pattern) and how you solved them?