I like many of the changes that are coming in the next major version of ember, and I feel it will remove a lot of the blurry lines that exist today between controllers, views, and components, but it still feels like Ember is missing a solution / pattern for complex interactions when a page doesn’t follow the traditional ember routing model.
To explain what I mean, let me give an example of what we have today on one of our pages. On the page itself, we have four areas. They consist of:
- A pending items area
- Created items filtered by type one
- Created items filtered by type two
- Created items filtered by type three
The pending items eventually will become one of the created items. All four of the areas load data independently of each other, and allow independent paging. A screenshot of the actual site, to visualize the groups can be seen here: https://www.dropbox.com/s/v1n6orrcbju6q3r/Screenshot%202015-01-06%2010.44.34.png?dl=0. As you scroll within each of the groups, more items are ajax loaded and that is where the trouble begins, because it pulls us out of the traditional ember routing model. Data needs to be loaded and changed without a specific route assigned to it.
Separating the page into different nested routes and resources
We can’t do this with 4 distinct areas on the page. It doesn’t fit within a traditional master/detail view and therefore there isn’t a single path to go down. That keeps us all at the same routing level. Even if we tried to somehow put this page into routes, it would make the routes very unclear as to what you are actually viewing and the state of each area on the page.
Retrieve subsequent data through the router
There isn’t a way to easily notify the router to retrieve data and then get that data back to the component. Especially when our “view” isn’t the entire store for a single model. Let me give an example.
- The “created items type one” is scrolled and it triggers an action to load more items
- The component receives this action, sets a loading flag to true, and sends an action outside the component to load more data
- The route receives this action and sends off a store request to load the next page and waits for the promise to fulfill
At this point we have two scenarios that could happen
- The promise fulfills, we had more items to load. The component observers the collection was modified, and sets loading to false. The extra items are displayed. When the component is scrolled again in the future, the events above are triggered and repeated.
- Or, the promise fulfills, we have no extra items to load. At this point, how would we then notify the component that there is nothing left to load, and to set loading to false? We have a disconnected state, since the data has finished loading, but the component is still showing loading.
How we handle it currently
For this reason, we are currently loading and tracking data through the components. Based on components design, I feel like this is the wrong approach, but can’t think of better solution. Previously to ember 2.0, this could have been avoided by using a controller and using render to display each one of the groups. I’m not advocating to keep controllers, I like the idea of removing them in ember 2.0, but this problem above is just one example of where more complex components are needed that don’t fit into the traditional ember design.
There have also been other times, we have needed to notify a component that something changed at the route or controller level, and have had to find a hack to notify the component through binding an arbitrary property, or through other means.
Now getting to my point of this post. I feel like ember works for most situations, or we have found a work around to make it work, but the hack didn’t really follow the ember design pattern. I feel like components should be:
- Isolated to allow them to be re-used
- Unaware of their surroundings or context
But it feels like there are almost two types of components that are going to need to be made.
- A generic component that can be reused anywhere without care of its context or usage
- A specific component that will need to be aware of its context, possibly load data, and very specific to the apps design.
I feel like if we had the ability to communicate down to components and their children, we could avoid some of these design decisions, but how things are setup today, we have a very disconnected communication pattern for complex design.
Any suggestions / ideas to make this work within the current Ember design patterns, or is Ember going to need to change to keep components isolated and more control given at the route?