2. AngularJSoverview
• AngularJS is a JavaScript MVW
framework made by Google for
building complex client-side
applications.
• It provides everything for development
of SPA out of the box
4. AngularJSmodules
• Allows to separate application in logical domains
• Allows to minify dependencies and knowledge
sharing between modules
• Allows to introduce architecture limitations aka :
– main module knows about controllers
– main module knows about routing
– controllers know about repositories (services)
– main module knows nothing about repositories
– controllers know nothing about routing
5. AngularJSmodules
//declare module and its dependencies
angular.module('myApp', ['ngAnimate','ngCookies'])
//declaring controller in a module
.controller("MainController",mainController)
//running module configuration if needed
.config(moduleConfiguration);
6. AngularJScontrollers
• Attached to a DOM via ng-controller directive
• Use them to:
– Initiate and add behavior to the $scope
– Retrieve data from services
• Do not use for:
– DOM manipulation
– Data filtering
– Share state with other parts of the application
8. AngularJSDirectives
• Markers for the DOM element
• Use them to:
– Attach behavior to the DOM element
– Transform DOM
• At the high level those can be treated as
components which extend or change behavior of
the DOM elements
9. AngularJSDirectives
• Directives are declared as
module.directive
• Directives are invoked once so
definition object instead of function is
preferred
• In order to avoid naming collisions
prefix your directives and do not use
standard ng as a prefix
10. AngularJSDirectives
angular.module('app')
//in html can be used as lo-directive
//name expected to be in camel case in html each uppercase letter is prefixed with -
.directive('loDirective', function() {
return {
//identifies matching rule
// A-attribute, E – element, C - class name
restrict: 'AEC',
//isolating scope
scope: {
//equal for JS object
info: '=info',
// & for callback
callback: '&',
// @ for a value
value: '@value'
},
//replacing DOM element with own content
replace:true,
//if we need to wrap DOM element with some markup.
//Original DOM is placed using ng-transclud
transclude: false,
//here is the template that is used for rendering
templateUrl: 'my-customer-iso.html',
//and that function would be called each time I am attached to the DOM element
link:function(scope, element, attrs) {
}
//And by the way I can have my own controller, restrict access to specific
controllers and other cool stuff
};});
11. AngularJSScope
• object that refers to the application
model
• arranged in hierarchical structure
which mimic the DOM structure
(scopes inheritance is done though
prototype)
• Provides API to:
– Watch model mutations
– Propagate model changes
12. AngularJSScope
angular.module('app')
.controller("TestController", ['$scope', function($scope){
//I can set values and use them in the view
$scope.name = "Test";
$scope.count = 0;
//I can subscribe to events which can be $emit(notify parents)
//and $broadcast(notify children)
$scope.$on('CustomEvent', function(name) {
$scope.name = name;
});
//I can $watch the changes
//even in the collection through $watchCollection
$scope.$watch('name',function(newValue, oldValue){
$scope.count++;
});
//or I can apply changes if async operation is performed
setTimeout(function(){
$scope.$apply(function(){
$scope.name = "Hey ya!!!";
})},200);
}]);
13. AngularJS Templates
• Written in HTML
– Can contain directives
– Can contain filters
– Can contain form
– Can contain specific markup {{expression}}
• Can be loaded dynamically
• Can be injected into other templates
• Are loaded once per app
• Are compiled on 1st load
14. AngularJS Workingwith forms
• ng-model – bind element value to form
control (ng-model=“user.name”)
• Give form a name and mark it as
novalidate
• standard validation with
formName.fieldname.$error
• or use 3rd party libraries
15. AngularJS Templates
<!-- ngController directive -->
<body ng-controller="MyController as vm">
<!-- ngModel directive allows to bind to element values -->
<input ng-model="foo" ng-model="vm.name" type="email">
<!-- This is going to be replaced with datepicker directive -->
<datepicker ng-model="vm.date"></datepicker>
<!-- this will call $scope.change once clicked
and will have controller buttontext displayed inside -->
<button ng-click="change()">{{vm.buttonText}}</button>
<!-- or you can bind content with ngBind directive -->
<span ng-bind="vm.buttonText"></span>
<ul>
<!-- here is the way I can iterate through collection with ngRepeat -->
<!-- and change class depending on model value -->
<li ng-repeat="item in vm.items track by id" ng-class="{active: item.active}">
<!-- and I can have expressions in the layout as well -->
<button ng-click="item.active = !item.active">change state</button>
<!-- and have custom templates if needed -->
<div ng-include="item.templateUrl"></div>
</li>
</ul>
16. AngularJS Filters
• Used to filter output
• Used to format output
• Filter is applied by using | in markup
• Or can be injected in other object
• Should return a function that will be
evaluated
17. AngularJS Filters
<script type="text/javascript">
//here is the way we register filder
angular.module('myFilters', []).filter('checkmark', function() {
//in the return function let's change the output
return function(input) {
return input ? 'True' : 'False';
};
});
</script>
Search: <input ng-model="searchText">
<table>
<tr><th>Name</th><th>Visited date</th><th>Active</th></tr>
<!-- I can filter elements in array -->
<tr ng-repeat="customer in customers | filter:searchText">
<td>{{customer.name}}</td>
<!-- I can format output with standard filter -->
<td>{{customer.lastVisitedDate | date:'yyyy-MM-dd'}}</td>
<!-- or with custom -->
<td>{{customer.active | checkmark }}</td>
</tr>
</table>
18. AngularJS Services
• Used to share across application:
– Data
– Behavior
• Services are lazy instantiated
• Services are singletons
• Remove code duplication
• Can work with DOM if needed
19. AngularJS Services
angular.module('app').factory('SampleRESTService', function ($resource) {
//there we go let's use another service which provides full REST support
return $resource('/api/sample/:id', { id: '@id' });
})
//let's inject the service
.controller("TestController", ['$scope', 'SampleRESTService',
function($scope, SampleRESTService){
$scope.tasks = SampleRESTService.query();
}]);
20. AngularJSDependencyinjection
• Using the inline array annotation
(prefered) is doing the constructor
injection
• Using $inject
• Using naming convention (is not min
safe)
• Add ng-strict-di directive to avoid
usage of naming convention
22. AngularJS Testability
• Unit testing
• End 2 end testing == Automated
testing
• Middleware testing == white box
testing provides access to internal
angular objects (directives)
• Useful library angular-mocks
23. AngularJS Unit testing (controller)
describe('Home controller test', function () {
//loading module where controller is defined
beforeEach(module('app.home'));
//declaring variables that will be used in the tests
var controller, scope, deferred;
//creating items
beforeEach(inject(function ($rootScope, $controller, $q) {
deferred = $q.defer();
scope = $rootScope.$new();
//create the controller injecting the scope and the mocked service
controller = $controller('Home', {
$scope: scope,
DashboardService: {
getDashboard: function () {
return deferred.promise;
}
}
});
}));
//once result is not returned let's check that initial data state is correct
it('verifies NewMessagesCount is undefined', function () {
expect(controller.NewMessagesCount === undefined);
});
//Let's resolve value and see if it is correct
it('verifies NewMessagesCount is correct', function () {
deferred.resolve({ NewMessagesCount: 5 });
expect(controller.NewMessagesCount === 5);
});
it('verifies that scope contains go and it is a function', function () {
expect(scope.go === 'function');
});
});
24. AngularJS Unit testing (controller)
describe('Dashboard factory tests', function () {
//injecting module
beforeEach(module('app.services'));
//mocking dependcies
beforeEach(function () {
var Utility = {};
module(function ($provide) {
$provide.value('Utility', Utility);
});
});
var httpBackend, Factory;
//injecting httpBackend for testing of http
//injecting factory itself
beforeEach(inject(function ($httpBackend, Factory) {
httpBackend = $httpBackend;
Factory = Factory;
}));
it('checks that object is not modified by service and proper API method is called',
function () {
//setting method we expect to be called and method response
httpBackend.expectGET('api/Dashboard/').respond("Test");
var result = Factory.getDashboard();
//Verifying that all expected methods were called
httpBackend.flush();
//verifying that result is returned as expected
expect(result == "Test");
});
afterEach(function () {
httpBackend.verifyNoOutstandingExpectation();
httpBackend.verifyNoOutstandingRequest();
});
});
27. Sum Up
• Provides big amount of features
• Has everything for SPA development
• Limits usage of other frameworks
• Learning curve is being quite high