In previous posts we have seen various aspects of AngularJS. We have seen model binding with ng-model, various angular directives like ng-app, ng-controller, ng-click, ng-repeat etc. Using these we can build highly interactive and dynamic website.
1. ng-app with application name.
angular.module('MODULE_NAME',ARRAY OF DEPENDENT MODULES)
With ng-app we can inject external modules( like angular-ui) or any custom modules. In this example i have declared an external module app.Module1
. The value method defines a service with in module scope. In app.Module1, i have defined sayHello object with welcome function. TestApp is another module which is used as my application module. You can find ng-app='TestApp' in HTML code. app.Module1 is added as an dependency to TestApp module. sayHello service is injected to testController. If we will replace ng-app='TestApp' with ng-app, the service will not be loaded.
2. ng-controller in application scope.
s
with $scope and f
with $filter respectively. In real world scenarios a controller always belongs to an application. So it is always advisable to define controller in application scope. In above example myController can be used with any ng-app modules. To define a controller in application scope, we can use controller() method of module.myApp
module. So myController
can only be used with in myApp
module. If we remove the myApp
module from HTML, we will not get expected result.3. ng-bind/ng-cloak instead on inline expression ({{..}})
{{..}}
(angular expression) in many of my examples. It seems quite easy to bind an expression with in {{}} braces. But it has got one annoying disadvantage. Until angular is loaded and bootstrapped your HTML, you will see the angular expression, but it will go away once angular is loaded. In below image, i have put an break point to show above effect called Flash Of Unstyled Content (FOUC)
ng-bind
and ng-cloak
. ng-bind='expression'
is used as an attribute and it tells compiler to replace the innerHTML with result of the expression
. In following example, the expression name||'Guest'
tells angular to display Guest until name is defined and the innerHTML Guest, will be shown when angular is not bootstrapped.ng-cloak
is similar to ng-bind, but it hides the innerHTML till application is bootstrapped. In angular.js following css rule is applied which will hide the ng-cloak DOM element.[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {display: none !important;}
But, these effect will be applied
only after angular.js is loaded.
So we can add above css rule to site.css for better effect. Moreover attribute based styling in not supported in IE8 and earlier. To be in safer side we can add
ng-cloak with class='ng-cloak'.
4. Don't do DOM manipulation, use angular directives effectively.
Angular provides a rich framework which supports two-way-binding of the model and views. With effective use of various angular directives we can eliminate the DOM manipulations. We can use ng-model
,ng-view
,ng-show
,ng-click
etc to access required behaviors. We will see a DOM manipulation examples using jQuery and Angular.
In above example we have done few simple DOM manipulation. As you can see javascript code is filled with HTML selectors. Now we will try to do same with angular.
As you see, my javascript code is much more neat and simple. Angular framework takes care of these DOM manipulation. This is a simple example, when we will learn about much more angular directives, we can avoid a lot of code. (like ajax request and update DOM etc)
5. $scope is not the model but a reference to model.
We have used $scope many times, declared variables in $scope and used in views. But $scope is not meant for this. Ideally we need to define models with required properties and refer model in $scope. As per best practice, ng-model should have '.' in its name This is done to avoid prototypical inheritance problem. In angular we will face similar problem, if a property is defined in $scope and it is updated in child scope. Lets spend some time understanding this,
Consider above two scenarios, assume Parent is $scope
object. Until we have overridden the myVar in child scope, any change to Parent.myVar
will be reflected when we will call Child.myVar
(as it accesses same object). If we will override myVar in child scope then Parent.myVar
and Child.myVar
will point to two different values.
In above example if we change value in Parent scope, it will be reflected in Child scope. But if we change value in child scope, it will create a new variable in child scope. After this, if we will modify Parent , the changes will not be reflected in Child scope. Lets wrap fName in a model person. Now when we will modify person.fName, it will refer to person in parent scope, so it will behave as expected.
We should always create a model which contains required variables and refer the model in $scope. So,
$scope should be read-only in view. Write to a model in $scope , not in scope directly.