Templates in AngularJS are quite powerful, but just because something can be done in the template doesn’t mean you should do it there. The separation between controller and template can be vague in Angular, which is why I have a couple of guidelines which I consider to be best practices in any Angular project.
One of those rules of thumb is: Don’t do in the template what can be done elsewhere.
In this post, I will go over the different symptoms of template overuse and why it can be problematic.
Template Overuse Symptoms
Template Overuse (noun): Performing work in the template that will be better placed somewhere else.
A popular example is
1 2 3
As you can see, the
ng-click handler is first making sure that the form is valid before actually calling the submit operation.
This extra logic is misplaced.
A similar, yet different, example is:
As a guideline, template event handlers should trigger functions on the controller, and not any other expression/statement (e.g. the above would be
This goes the same for similar directives, such as
This, for some reason beyond me, is not an uncommon sight:
In case you’re not aware of it,
ng-init simply runs the code given to it when the template initializes.
Its valid use cases are so rare, even the documentation warns against using it.
And yet, a GitHub search comes up with 785K+ hits at the time of this writing.
There’s a good place to initialize stuff: the controller’s
All the power we get from templates might make it easy to forget that not all visual logic has to be done inside them.
A good example is using
ng-class for targeting special cases that can be handled in CSS, like special casing the first element in a list, or coloring every other row, like I’ve shown here.
Forgetting the Basics
I see too many developers reinventing the wheel instead of making use of the power of the web.
Consider the first example here, which showed
ng-click="$ctrl.validate() && $ctrl.submit()".
There’s a known mechanism for preventing actions on buttons in case the form state is invalid, which is setting those buttons to be
This can be done by using Angular’s validators, or even simply by using
1 2 3
Why is Overuse Bad?
Further, it’s very easy for templates to contain a bunch of dense expressions and overly long
These in turn make code maintenance a PITA.
Templates should be easy to change when view requirements change, and are best when they make it easy to understand and visualize what is happening on screen.
The more code in your templates, the harder they become to follow.
Also, logic in template also makes it harder to properly unit test controllers.
For example, if the template contains an
ng-init hook, then usually the test would also have to invoke whatever expression the
ng-init is calling.
Essentially, all these reasons boil down to complicated templates making code maintenance harder in the long term. Making a point of keeping templates succinct will make for a codebase that everyone will be happier working on.
To repeat, the basic guidelines you should strive to follow are:
- Don’t do in the template what can be done elsewere.
- Template event handlers should trigger functions.
- Remember the basics, like CSS and HTML form validation.
- Don’t use
ng-init. Just don’t.
“Maintaining AngularJS feels like Cobol 🤷…”
You want to do AngularJS the right way.
Yet every blog post you see makes it look like your codebase is obsolete. Components? Lifecycle hooks? Controllers are dead?
It would be great to work on a modern codebase again, but who has weeks for a rewrite?
Well, you can get your app back in shape, without pushing back all your deadlines! Imagine, upgrading smoothly along your regular tasks, no longer deep in legacy.
Subscribe and get my free email course with steps for upgrading your AngularJS app to the latest 1.6 safely and without a rewrite.