Note: This post was updated for the official release of 1.5
In my Angular 1.5 sneak peek I mentioned the new .component()
method.
A lot of people are quite excited about this method.
But, as with anything new, there are open questions:
When should you use it?
Why should you use it?
What’s the difference between it and .directive()
?
Today we’ll understand what exactly it does and whether it’s good for you.
Syntax sugar
First things first: this method is truly just syntax sugar for the good old .directive()
method you know (and hate?).
There’s nothing you can do with .component()
that you can’t do with .directive()
.
So what is it good for?
It aims to simplify the way we create “components” – which roughly means UI directives. It also pushes the community to use the defaults that have become best practices:
- Components have isolated scopes by default
- They automatically use controllerAs syntax
- They use controllers instead of
link
functions - The
bindToController
option is on by default
If this sounds familiar, you might remember this is basically how I’ve recommended we write directive controllers in this post.
Show me the code: before and after
Here’s an example component directive:
1 2 3 4 5 6 7 8 9 10 11 |
|
It’s a simple component directive, with an isolated scope, binding, and a controller.
Here’s how you’ll write it with .component
:
1 2 3 4 5 6 7 |
|
As you can see, not much has changed.
But, things are simpler and more straightforward.
Also, we get to enjoy some default and save on boilerplate: bindToController
is the default, controllerAs
is on and defaults to $ctrl
(I would have prefered a nicer looking default, but it’ll do).
Another nice point is that we don’t need to write a stupid function that always returns the same object.
We just define that object right here.
When can/should you use it?
Clearly there are a few cases where you can’t/shouldn’t use it:
- If you need the
link
function (though you rarely should) - If you want a template-less directive, e.g.
ng-click
that doesn’t have a template or separate scope
For all your other directives, this should work. And because it saves on boilerplate and less error-prone it’s nicer to use.
I usually prefer to go with whatever would work everywhere.
And here it goes against .component()
that it can’t fully replace .directive()
.
But, using it saves so much boilerplate.
And, non-component directives should be rare, which means they’ll stand out even more.
That’s why, in my opinion, using this new syntax is worthwhile. You can read the full docs about it here.
Lots of new goodies
$onInit
It has been pretty common to group initialization code of your controllers inside some function.
For example, John Papa’s style guide recommends an activate()
function to fire promises.
With 1.5 there’s official support for this much-needed concept.
If the controller has a $onInit
function, it will be called once all bindings are initialized:
1 2 3 4 5 6 7 8 |
|
This will also make transitioning components to ng2 easier (since it has the equivalent ngOnInit
function).
You can require other components/directives
In the first RC releases of 1.5, there was no (nice) way for using the awesome require
property directives have.
It meant that making a structure of components that communicate using nice APIs on their controllers wasn’t really possible.
But, with the final release we got it all sorted out:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
This greatly helps in writing maintainble Angular, as I’ve recommended (2 years ago!) here.
One way bindings
First, make sure you don’t confuse this with 1.3’s one-time bindings (or “bind once”).
One-way binding does half of what two-way binding does (surprisingly).
Previously, we could pass objects to child directives/components with the =
binding:
1 2 3 4 5 6 7 |
|
This would have created a two-way binding with the component’s parent. Whenever the parent would assign a new value, it would be propagated to the child. And vice-versa, if the component assigns a new value it will be copied to the parent.
This, while helpful, isn’t a very common scenario in my experience. That’s why Angular has finally introduced one-way bindings.
These create just a single watch, that watches for changes in the parent and syncs them to the child. We gain performance (by cutting in half the amount of watches created) and things become less error prone. This also is a step towards the way things will usually behave in ng2.
The syntax is similar:
1 2 3 4 5 6 7 |
|
Yeah, we just change =
to <
.
All in all, .component()
is a great addition to Angular.
It’s a real upgrade for code quality and helps you preper for ng2.
So, upgrade to 1.5 and start using .component()
: you have unlocked a new skill!
“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.