Common Pitfalls using AngularJS

AngularJS is a super awesome SPA JavaScript framework which we have embraced wholeheartedly and it has become our number one choice for all greenfield engagements. This obviously means I get to spend a considerable amount of time working on this framework. I also help fellow devs on StackOverflow AngularJS thread answering their queries.

Time and again while answering questions on SO and working with my team I see some areas in Angular where developers have difficulties and they keep hitting roadblock. In this post I want to highlight such issues and their resolutions. So in no particular order let me get started

1. Scope Prototypal inheritance

This is the most common stumbling block for a newcomer or a seasoned developer and nothing I say can match up to this wiki article which explains the concept beautifully. This article may be a long read but this would save you countless hours of debugging andor StackOverflowing :). You would hit this issue if

  • You create nested controller
  • If you use directives that create scope (ng-repeat, ng-if, ng-include, ng-controller and more ..)
  • If you create directives

As you can see you would hit this issue, I guarantee 🙂 So do yourself a favor read the wiki article

2. JavaScript async nature

Time and again I get see code like this [gist]https://gist.github.com/chandermani/8755571[/gist]

The standard behavior of all AJAX libraries is to implement a callback pattern, to keep the UI responsive. This holds true for AngularJS as well (its $http and $resource services). So it is important to understand that for any asyc call response would not be available immediately. Developers used to synchronous model of coding (which is the case with most programming languages like C#, Java) face this issue once too often. This manifests itself in queries like this and this.

2.1 Promise Unwrapping

AngularJS had (In 1.x version) a feature called promise unwrapping, which meant this worked

[gist]https://gist.github.com/chandermani/8749891[/gist]

This code makes one feel that the data is being retrieved synchronously and bound to HTML, but that is not the case. It is the template engine that hides the async nature of the call and hence adds to more confusion.

In fact in Angular 1.2.x the above does not work and you need to change it to

[gist]https://gist.github.com/chandermani/8750158[/gist]

You can play around with this plunkr to understand the nuances of $http and $resource

3. External callbacks and $scope.$apply()

Not always we function inside the Angular context. There are times when we have to integrate with jQuery or need to handle events out of AngularJS scope using callbacks. Understanding $scope.$apply become essential as model changes outside of AngularJS context are not tracked by the AngularJS model binding infrastructure. The correct to handle such scenario is

[gist]https://gist.github.com/chandermani/8765431[/gist]

But remember scope.$apply() causes a digest cycle to be executed and hence call to it should be minimized. Number of JavaScript constructs such as setTimeout, setInterval are available as AngularJS services $timeout and $interval further reducing the need to use scope.$apply()

3.1 Accessing scope outside Angular context

In extreme case we want want to access AngularJS scope outside of AngularJS, lets say in a third party library written in jQuery. AngularJS provides some constructs for this too. Using code like this to retrieve scope for a non AngularJS code

[gist]https://gist.github.com/chandermani/8765797[/gist]

More details are available on this SO thread.

4. Model driven UI

AngularJS has a steep learning curve and more so for people coming from jQuery background. One has to unlearn the jQuery way and embrace the Angular way. In AngularJS model drives the UI (View). One never manipulates DOM elements, we manipulate the model and the binding feature of AngularJS makes the UI react to model changes. Any DOM changes need to be done using directives. And for people starting with Angular most the inbuilt directive like ng-click,ng-dblclick, ng-class, ng-style, ng-mouse should suffice and would never require you to do direct DOM manipulation.

One way to learn about Angular way of doing thing would be to look at some sample code. TodoMVC is a great example which compares creating a trivial TODO list app using different JavaScript frameworks.

For jQuery developer this is a great SO thread for helping you think the Angular way.

5. Using Directives

Directives are the most powerful feature of Angular and the most difficult understand and master too. For any decent size application one eventually would have to write directive and getting it correct is always a challenge. Describing directive and how it works is a complex topic and deserves a post of its own. Here I would provide some pointers to relevant material for directive that I found useful.

Once you start getting the hang of directives, an important to realize is when not to create own directive. You don’t need new directives

  • For standard mouse and keyboard events. There are already directives for ng-click, ng-dblclick, ng-mouseover,ng-keydown and many more.
  • You just need to add classstyle to a DOM element on some condition. Use ng-style, ng-class.
  • Show hide element. Use ng-show, ng-hide.
  • And any combination of above :). Remember in Angular model drives the view, so direct DOM manipulation may not be required.

6. Recreating module

Quite a common issue faced by newbies, see here, here and here. All these questions have different context but same error. The problem lies in the fact that [gist]https://gist.github.com/chandermani/8778893[/gist] If you use the first syntax more than once, you are re-declaring the module. So any associations done before re-declaration get lost and one see such errors. Remember this re-declaration can affect across js files. If you see such errors just verify module declaration is not done multiple times.

7. ng-repeat Object vs Arrays

ng-repeat is a flexible directive and allows one to repeat over an array and object. But this is a source of confusion too. Developers try to bind an object using array construct (album in artist.albums) and it does not work. Infact the expression for binding an object to ng-repeat is ((name, age) is {‘adam’:10, ‘amalie’:12}).

Binding an object to ng-repeat also has some other nuances, such as filter cannot be applied to object type as it can be done for array.

8. Not seeing the browser console log for errors

This is a personal rant and is not limited to Angular. Many a times I see questions on SO where developer did not bother to look at console error logged in their respective browser. Number of queries on SO can be resolved just by looking at the error details in browser console log and and taking corrective actions.

Conclusion

I highlighted some common issues while developing with AngularJS and how this post is useful for people who are using this super awesome framework and make them more productive. In future if I see some more patterns like these I would do a followup post.

Related posts