Angular.js - create reusable HTML widgets with directives
August 13th, 2013
The Angular.js JavaScript MVC framework has a powerful directive mechanism that can be used to create reusable HTML widgets.
AngularJS is a powerful if stubborn Javascript framework. What follows is simply a list of things that I wish were clearer to me when I started working with AngularJS. Hopefully, someone just starting with AngularJS will find this list helpful.
Data Binded Directives
Manipulate the data, not the DOM. In a “normal” Javascript application, the developer is used to writing lots of event listeners to respond to users. You end up writing a lot of onChanges, for example. This gets in your way in AngularJS. AngularJS binds to your data and watches it. For example, instead of an onChange attribute on a select input, you can register a $watch() method on your controller to watch a collection. Or maybe you want to hide/show a div (using the ng-show directive) based on what value is chosen in the select.
Additionally, you can write your own custom directives to manipulate a particular DOM element and add functionality to it. Combined with services and messaging, this can be extremely powerful.
In short, when you start with AngularJS, you need to make a conscious effort to forget what you thought you knew about manipulating the DOM with Javascript.
Services are just global objects
AngularJS wires in services to your controllers for you, in an attempt at implementing dependency injection in Javascript. Many useful services are provided for you, such as $http, $scope, $location, and $routeParams. However, in any reasonably complex application you will write your own services. In reality, services are just Javascript objects, nothing more. They are a very useful place to hold data that may need to be accessed in multiple parts of the application. Hence why I call them global (although, in reality, singletons may be the better term).
Embrace broadcast messaging
Any reasonably complex view will end up containing multiple controllers. We struggled for a while to handle communicating between those controllers. For example, take a view that has a left navigation bar and corresponding controller, as well as a main content window that also has its own controller. The behavior of the main content window depends upon selections in the left navigation bar. How do you communicate between those two controllers? When we started, in many cases broadcast messaging just felt like overkill. Once we learned to love the bomb, life got easier.
Which all leads us to…
Combine broadcast messaging with services
The pattern that we eventually fell into was to combine broadcast messaging with services. Given data that affects multiple controllers, that data is stored in a service. If a controller needs to manipulate that data, it does so via a setter exposed by the service. When this data is updated, the service broadcasts a message alerting the application that the data is changed. Any other controller that may care about that data can register a listener (a $on() method) for that message on instantiation. When it receives the message, it can get the data from the service and react accordingly.
Like many things in AngularJS, this too felt like overkill at first. But it is extremely flexible and expandable. I have never really seen this pattern described anywhere, but it seemed to come naturally to us as we grew more comfortable with AngularJS. It works very well for us.
Know when to use a ng-view
A page gets one ng-view. Assuming you have a single page application, this means you get one view. Use it wisely. Give some thought to what should be in the view. Is this your main content window or is this more of a navigation? Is the actual content (HTML) of this section highly dynamic? These are important decisions to make early in the development of your application if you have more than one distinct content area on your page.
Beware of external data manipulation
I had an application written in AngularJS with several $watch() methods watching various pieces of data. In one instance, some of the data was being manipulated by an onClick call added after the DOM was parsed by AngularJS. Since the DOM had already been parsed before the onClick was added, the $watch() method did not fire. (Note: this violated my first point in this article!). I am not sure of the best way to handle this. I ran into this issue building an application for a demonstration and just left it. I added it here as something to be aware of. If you find yourself wondering why AngularJS doesn’t always react to changes in your data, look for places that data is being manipulated that AngularJS may not be aware of.
I hope this helps out others getting started with AngularJS.
The Angular.js JavaScript MVC framework has a powerful directive mechanism that can be used to create reusable HTML widgets.
Information technology is moving faster all the time. But, if information technology is progressing rapidly, Why does it takes so long to do web development? How do intelligent technologists solve these problems? Share this infographic: http://www…
Sauce, which provides Remove WebDriver Browsers as a Service, or RWDBaaS. I may have just made up that acronym, but I am not making up this service. Its a great way to run automated Selenium-based tests against a large number of browsers. But automated cross-browser unit tests? Well, thats just one step removed and I would like to show you that.
Insert bio here