In AngularJS, your app’s HTML can be added via the templates of ng-view
, ng-include
and directives. But what HTML should go in each template? How does ng-view
differ from ng-include
, and should you use many ng-includes
and few directives, or vice-versa? This article will show you the best practice for constructing your HTML in a production-ready AngularJS app.
The big picture (or Tl;dr)
- Put the main HTML content of your page in the
ng-view
‘s partial. Use only oneng-view
for your whole app, and bind it to a controller, a partial and a specific url via the$routeProvider
service. - Use zero-to-a-few
ng-includes
, one for each large layout component that’s common across pages (e.g. sidebar, header, footer) - Use many small directives, each encapsulating a small feature with its own discrete set of functionality, such as a carousel, menu, or part of a form’s interface.
Three different ways of constructing the HTML in your AngularJS app
An AngularJS app starts with a static HTML skeleton file containing the usual boilerplate stuff (head
, body
, script
tags, etc.). Within this HTML skeleton will be a number of AngularJS core directives (ng-view
and ng-include
), plus your own custom directives, all of which will dynamically import their own HTML fragments from different HTML templates (called partials) and inject them into the skeleton.
There are therefore three different ways of composing your app’s HTML:
ng-view
,ng-include
,- your own custom directives.
ng-view
The HTML that you put in the ng-view
partial represents the main content of your page. It is bound to the page’s url (that is, its route) via the $routeProvider
service, together with a partial and a controller. Whenever the user navigates to the page, the bound partial will be rendered in place of the ng-view
.
Because ng-view
is bound to the page’s route, you can only use one per page. This bears repeating, as there are times when you think you’ll need more than one ng-view
(e.g. one for the main content and one for the sidebar). You cannot.
You can only have one
ng-view
per page
If you think you need another ng-view
, you’re doing it wrong! Use an ng-include
instead.
What to put inside an ng-view's
partial
The HTML content within an ng-view's
partial usually comprises the main content of the page itself (excluding what I call here layout components such as headers, footers, etc.).
Examples include:
- for a blog app, it’s the part where the blog posts go;
- if it’s dashboard app, it’s the main section showing the different charts and gauges;
- if it’s a CRM app, it’s the tables showing the customer’s details.
Why this is best practice
Because ng-view
is bound to the url, its content will tend to be specific to the url it’s bound to. For example, the view for a customer’s details will change according to the customer (and hence the page’s url) you’re viewing; equally, a blog’s posts will change according to the category or page number you’re viewing (each of which is referenced via its own unique url).
In contrast, layout components, such as headers, footers, etc., tend not to change across the pages of your app, and so should not be bound to a specific url. So, keep ng-view
for the main content of your app – the stuff that is unique to the url it’s bound to.
ng-include
ng-include
is more granular than ng-view
, and so rather than being used to declare the main content of a page, it should be used for what I call here layout components, such as a header, footer, or sidebar.
You can have many ng-includes
on a page, as it’s not bound to a url, and can even switch between different partials dynamically, as the src
attribute that references the ng-include's
partial is simply a property that can be changed at will.
What to put inside an ng-include's
partial
The HTML content within an ng-include's
partial is generally (but not always) used to render layout components, such as headers, footers, sidebars, etc.
Note that it should not be used to render smaller components, such as menus, lists, or forms, etc. For that, you need directives.
Why this is best practice
As a general rule, ng-include
is used for components with little functionality, but which are used commonly across more than page. It is a way of keeping your page modular and enabling reuse, effectively componentising distinct areas of your page.
Headers, sidebars and footers all tend to stay the same across pages. Any differences within them can be encoded using a custom directive. By using an ng-include
for your layout components, you can split the page up into discrete components that are easier to debug, and can be ported easily to other HTML pages, or even different apps.
For example, a CRM app might have a set of highly functional pages that provide the core features of the app, letting you view, edit and add customers and your interactions with them. But it might also have a blog area as well. For consistency, you might have the same header and footer across the app and the blog, but a different sidebar.
Using ng-includes
let you do just that.
Directives
Directives tend to be used for smaller components that contain a higher degree of functionality. Whereas ng-include
should be should be used for larger layout components, a directive should be much smaller, and only encapsulate the functionality of an individual feature.
You will generally have many directives in your page, certainly more directives than ng-includes
.
What to put inside a directive’s partial
User interface components, such as a carousel, accordion or calendar, are all good candidates for a directive. So too are form elements such as a submit button, or a group of inputs dedicated to a specific feature (such as login/logout, for example).
(Note that you do not necessarily need a partial for a directive, though. Some directives do things such as modify existing text, and so do not need their own HTML, as they merely alter the HTML of another directive.)
Putting it all together with a Page Template
Enough of the theory – what does an example page template look like? Well, this:
...
Your sidebar could look like this:
And your footer like this:
Evgeny
Thanks. great article! made things much clearer for me.