How to do nested views in AngularJS (Hint: Don’t)
Starting to use AngularJS in November was an eye-opening experience. Angular does application architecture like would have done but with a level of polish and refinement that I could never have achieved.
That said there was an issue I encountered early that also comes up from time to time on the AngularJS mailing list, namely that of nested views.
Angular has facilities to watch the location/history and control an
ngView directive in response, but it only supports one
ngView per app. How could you build a nicely structured application with that when you have nested levels of hierarchy?
It took my a while to realize that I was think in the wrong direction, coming from a Backbone project and doing years of Rails development.
Views are not what you use to structure your application!
In fact, views are more of a crutch, a shortcut, to create structures similar to traditional websites, only with angular as a driver. When developing a web application, the way to deal with complex interfaces is to use, in combination:
- Scope objects/variables that store your desired view state explicitly
- ngSwitch directives on this view state
- Directives to include custom templates/perform complex DOM manipulation behavior
Stop thinking of your application in terms of views that need to be loaded. That kind of thinking aligns better with imperative frameworks but doesn't work well in angular.
Think instead of components that fulfill a particular purpose. Define the components as directives, passing objects into your components, manage view state explicitly using simple objects or single variables in your scope. Angular is declarative and data-driven at its heart. Therefore decisions over what to display belong in the directives really, either as part of your linking functions or as ng-switch directives in the templates. They should never be managed in a controller although that seems to be what many people instinctively try to do when getting started with angular.
Defining multiple views that are manipulated imperatively goes against the core concept of angular.
Those approaching angular with concepts from other JS frameworks will have a hard time realizing the full power of Angulars clean separation of concerns.
UPDATE: I've written a follow up to this Article here