
5 ways how NOT to use Angular JS
Modern web development is aimed at achieving faster functionality of applications and the ability to cater to an ever-growing audience. This becomes a demanding constraint for all web developers and pushes them towards coming up with an architecture that can support a gamut of desktop and mobile browsers at the same time, decrease the initial load time, increase performance and introduce better animations and styles.To add to it , better User Experience (UX) continues to hold priority.
As a movement towards a solution to the problems faced, Single page applications (SPA) is the direction most websites have taken to. Single page applications hold the capability of decreasing the load time of pages and the amount of data transferred from server to client. Some of the impacting features of this method include storing any global functionality once it is loaded the first time, allowing easier data transfer between pages and a more complex user interface, and removing the cost of loading the complete page after a post back.
There are a couple of frameworks and libraries available today which assist in structuring a faster and better SPA, some of these include AngularJS, BackboneJS, ReactJS, Ember.The most popular among-st all, ranked as the third most starred project on Github is AngularJS. AngularJS solves most of the complications faced while developing a fast and robust web application. AngularJS aims to simplify both the development and the testing of SPAs by providing a framework for client-side model–view–controller (MVC) and model–view–view model (MVVM) architectures.
As developers familiarize themselves with AngularJS, there are some potential mistakes that could be made by even the most ace developers. These mistakes are avoidable, here are a few enlisted ones to give you more clarity.
1. Too many watchers:
Watchers look for any change in the binding and reflects it in the UI if a change is found. Consider this as the polling mechanism to check for changes. For every binding {{ model }} AngularJS creates a watcher. Through Dirty Checking mechanism, on each digest phase, all such bindings are checked against their previous value. If there appears to be a changed value since the last check, the watcher callback is fired. Browsers don’t have problems even with thousands of bindings, unless the expressions are complex. Usually an upper limit of 2000 watchers is what is suggested as the maximum to have .
So, how can we limit the number of watchers?
By not watching scope models when we don’t expect them to change. With the coming of AngularJS 1.3 this has become easier and better with one-time binding being a part of the core structure now.Below is an example to elucidate it further.
<li ng-repeat=“item in ::vastArray”>{{ ::item.velocity }}</li>After ‘vastArray’ and ‘item.velocity’ are evaluated once, they will never change again. You can still apply filters to the array, they will work just fine. It is just that the array itself will not be evaluated. In many cases, that is a win.
2. Minifying your angular code:
One of the best selling point of AngularJs is Dependency Injection. It makes testing much simpler and clearer , upon which any particular object depends. AngularJS is very flexible on how things can be injected. The simplest version requires just passing the name of the dependency into the function for the module.
var app = angular.module(‘bigApp’, []);
app.controller(‘mainController’, function($scope) {
$scope.message = ‘OH NO!’;
});
In this example, Angular knows that it needs to use the $scope dependency in the app. Let’s look at the same example minified.
var app=angular.module(“bigApp”,[]);app.controller(“mainController”,function(e){e.message=”OH NO!”})Now we see that the $scope variable that was so crucial to our application has been turned into a tiny little ‘e’. Angular thus will no longer know how to use the message that we declared. To solve this one can,
a. Explicitly inject dependencies using $inject property on controllers:
var app = angular.module(‘bigApp’, []);
app.controller(‘mainController’, function($scope) {
$scope.message = ‘OH NO!’;
});
mainController.$inject = [‘$scope’];
b. inline notation:
var app = angular.module(‘bigApp’, []);
app.controller(‘mainController’, [‘$scope’, ‘$http’, function($scope){
$scope.message = ‘HOORAY!’;
}]);
We’ve added $http into this example just to show how you can manage multiple injections.
3. DOM manipulations in controller — stop using jQuery
jQuery is well known as a library for making DOM manipulations simple for handling events and for AJAX operations. AngularJS on the other hand is a framework that is used in the creation of scalable applications. The crux however is all about development and testing of applications, therefore it cannot be used in augmentation of HTML pages, if that is the case then there is no need of using jQuery. What you should do is to just let your code go beyond HTML syntax just as it has been declared.
AngularJS has an appropriate variety of features and so as a developer you should find out what features they have at their disposal before you opt to use jQuery. If you must have DOM manipulation, let it be done only in directives but this does not necessarily mean that jQuery has to be involved.
4. Not using dot in your model — prototype scoping
This is a classic mistake which most of the naive developers make who fail to understand $scope well.
Javascript’s prototype-based inheritance differs from class-based inheritance in nuanced ways. This normally isn’t a problem, but the nuances often arise when working with $scope. In AngularJS every $scope inherits from its parent $scope with the highest level being $rootScope.Sharing data from a parent to a child is trivial because of the prototype inheritance. It is easy however to shadow a property of the parent $scope if caution is not taken.
Let’s say we want to have a username displayed in a navbar, and it is fed in a login form. This could be a good first attempt at how this might work:
<div ng-controller=”navCtrl”>
<span>{{user}}</span>
<div ng-controller=”loginCtrl”>
<span>{{user}}</span>
<input ng-model=”user”></input>
</div>
</div>
When a user types in the text input with the user ng-model set on it, which template do you think would be updated? The navCtrl, loginCtrl, or both?
If you first guess was loginCtrl then you probably by now understand how prototypical inheritance works.
When looking up literal values, the prototype chain is not consulted. If navCtrl is to be updated simultaneously then a prototype chain lookup is required; this will happen when the value is an object. (Remember, in Javascript, functions, arrays, and objects are objects)So to get the desired behavior it is necessary to create an object on the navCtrl that can be referenced from loginCtrl.
<div ng-controller=”navCtrl”>
<span>{{user.name}}</span>
<div ng-controller=”loginCtrl”>
<span>{{user.name}}</span>
<input ng-model=”user.name”></input>
</div>
</div>
Now since user is an object, the prototype chain will be consulted and the navCtrl’s template and $scope will be updated along with loginCtrl. This may seem like a contrived example, but when working with directives that create child $scope’s like ngRepeat this issue can arise easily.
5. Not cleaning up timeouts, intervals afterwards
AngularJS does some work on your behalf, but not all. The following need to be manually cleaned up:
• Any watchers that are not bound to the current scope (e.g. bound to $rootScope)
• Intervals
• Timeouts
• Variables referencing DOM in directives
• Dodgy jQuery plugins, e.g. those that don’t have handlers reacting to the JavaScript $destroy event
If you don’t do that manually, you will encounter unexpected behaviour and memory leaks. Even worse — these will not be instantly visible, but they will crop up eventually-Murphy’s law.Amazingly, AngularJS provides handy ways to deal with all of those through $destroy.
Conclusion
AngularJS is a great framework that continues to evolve with the community. AngularJS is among-st the trending technologies right now, and it has been holding a stable position among the most popular development tools for a few years. With AngularJS 2.0 on the way, it will probably dominate for years to come. Hopefully you will be able to avoid some major pitfalls in scaling an AngularJS app by following these conventions.
In case you wish to drop your comments or ask us a question or (the one we love the most ;) ) engage with us on a project feel free to drop us a mail at hello@pnplabs.in