Best practices when creating a complex page (render vs component vs view)


#1

We have developed a fairly complex page that uses a model with lots of properties and relations. Unable to find a complex example online about exactly how to go about designing the page in ember, we selected to use {{render}} to break up the various sub sections to contain the sub model and logic. From the guide and examples, the controller felt like the right solution at the time.

The problem we are seeing now is, anytime you navigate between routes, all the sub rendered controllers are generated and sit in memory, but also since they are still present, interact with validations we have in place since we are tracking child controllers. The controllers aren’t destroyed, and so we can’t use the willDestroy callback to remove the extra child controllers.

Getting to the questions, I have a few that if anyone has design feedback on, it would be appreciated.

  1. When should you use render? A the moment it feels like you should only use it on top level items, like in the application template. Using it in a place that gets re-rendered frequently just seems to create tons of controllers.

  2. Should components replace our existing render statements? We want the separation, but a view doesn’t feel like the right solution as we need actions, and specific models as the context.

  3. Does anyone have a solid guideline of when to use a view vs a component vs render. Even after using ember for a month an a half constantly, I still don’t feel like there is a good distinction what makes the call on which to use.


#2

I don’t really have a solid guideline; but I’ll tell you that recently I’ve been trying to avoid {{render}} because it’s creating the singleton instance of the named controller which will continue to exist while the app exists. This is typically not the behavior I want.

It seems like it’s best used for long-living parts of your application…say, for example, you had a Facebook-like chat feature at the bottom of your page or some sort of notification center: {{render}} might be appropriate for that. This is rarely the case for my applications.

Depending on what these subdivisions of a route are supposed to do, components may be a decent solution, but it’s important to keep in mind that they are not aware of their context except what you explicitly pass to it. I’d say that if you’re putting any business logic inside a component, then you might be a little bit beyond what a component is intended for.

There’s a soon-to-be feature coming that I think may serve your needs a little better. This would create a temporary ObjectController that wraps your model only while it’s be actively used in your route. It behaves similarly to the {{#each}} itemController property which is super handy. Additionally, this controller will have direct access to its parentController is also super handy.

Hope this helps!


#3

@Spencer_Price Maybe it’s off topic, but can you elaborate? (I’m not sure what is best for what scenario). " … I’d say that if you’re putting any business logic inside a component, then you might be a little bit beyond what a component is intended for. … " My understanding is that a component is more like autonomous. It interacts with others in a whole. It can have its own logic and views. Let’s take Facebook-like chat feature (assuming it has complex logic) as an example. If I make it a component, I can use it like an HTML element in a couple places as needed. And I don’t need to worry about how it works most time.

It seems like render or view can do the trick too. So is a component designed for a simple view. Then which is designed for a re-usable complex one?


#4

Again, I don’t think there’s any hard and fast rules for what to use when. You’re right that you could certainly create a Facebook Chat component…but that depends on your intended use.

There’s a good tutorial on components here. The key takeaway is that a component defines an interface and expects its context to fill that interface, but nothing else.

Perhaps a question to guide when to use a component: If the complexity of your application increases, does your component also have to change? (I suppose this is what I meant by “business logic”) If so, a component might not be the correct solution. That does not mean, however, that a component by itself can’t be complex.


#5

@Spencer_Price I’m starting to agree. I feel like the use of {{render}} should be pretty rare (global notifications are a good example of when to use it). In most circumstances, I feel now that a component is the best way of isolating a context/model instead of using a {{render}} to generate a new controller to pass in the context.

The new feature could be useful, as long as it doesn’t create lots of instances that are never removed.

@kceiw The problem I’ve seen so far, is that a controller/component/view is so interchangeable its hard to define when to use which type. My gut feeling of how to use them now is this:

Render/Controller - Only used when coming directly off of a route, or you have a need to have a top level controller (header, navigation, etc). You shouldn’t create controllers with {{render}} to isolate models/context. Properties on the controller should be related to the displaying of content or tracking view states.

View - It feels like views should only be used when you either need to directly work with the DOM, or you need to have some sort of state tracking (related to the DOM). State tracking is a little harder to explain, but I’ve used a view in a checkbox situation where I had two separate models that when checked or unchecked I needed to associate or remove the association, and it couldn’t be done easily at the controller level. It feels like views should have a minimal number of computed properties.

Component - Anything that is a little more than a view, and lives temporarily on the page. This allows you to isolate a context, create scoped properties, and reuse the component many times.

Model Properties - Anything that is shared by multiple components or controllers. This doesn’t related to displaying data as in the controller, but information or meta information thats used for in multiple places.

Anyway, thats the conclusion I’m starting to derive, anyone else having a similar conclusion or differences?


#6

I would love some clarification around this too. Using {{render}} is nice to get a new controller for a specific context object but the lack of cleanup for those controllers is causing us issues on a long running app (transitioning between multiple routes is calling render many times and leaving behind controllers, or at least not ever calling willDestroy)

According to the docs it should work both ways: http://emberjs.com/guides/templates/rendering-with-helpers/.

When no model is provided it gets the singleton instance of the corresponding controller

This is what you guys have been discussing. That’s fine and that makes sense. However I’ve used it a lot in the other scenario which is also clearly documented as

When a model is provided it gets a unique instance of the corresponding controller

If these “unique” controllers could get destroyed when a route changes I feel like it would solve these problems. Otherwise all I’m hearing is that we shouldn’t use it in that second documented way… in which case removing it from the documentation would be useful.