AngularJS.part1
-
Upload
andrey-kolodnitsky -
Category
Technology
-
view
117 -
download
0
Transcript of AngularJS.part1
AngularJS overview
• 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
AngularJS core features
• Modules• Controllers• Directives • Scope• Templates• Filters• Services• Dependency injection and container• Testability
AngularJS modules• 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
AngularJS modules//declare module and its dependenciesangular.module('myApp', ['ngAnimate','ngCookies']) //declaring controller in a module .controller("MainController",mainController) //running module configuration if needed .config(moduleConfiguration);
AngularJS controllers• 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
AngularJS controllers
angular.module('app') .controller('Customers', [function() { var vm = this; vm.title = 'Customers'; vm.customers = [ {name: 'Customer 1'}, {name: 'Customer 2'}, {name: 'Customer 3'}, {name: 'Customer 4'} ];}]);
//VSangular.module('app') .controller('Customers', ['$scope', function($scope) { $scope.title = 'Customers'; $scope.customers = [ {name: 'Customer 1'}, {name: 'Customer 2'}, {name: 'Customer 3'}, {name: 'Customer 4'} ];}]);
AngularJS Directives• 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
AngularJS Directives
• 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
AngularJS Directivesangular.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 };});
AngularJS Scope
• 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
AngularJS Scopeangular.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); }]);
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
AngularJS Working with 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
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>
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
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>
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
AngularJS Servicesangular.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();}]);
AngularJS Dependency injection
• 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
Dependency injection
var MyController = function($scope, greeter) {};//$inject annotationMyController.$inject = ['$scope'];myModule.controller('MyController', MyController);
//array annotationmyModule.controller('MyController',[ '$scope', MyController]);
//naming annotationmyModule.controller('MyController',MyController);
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
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'); });});
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(); });});
Sum Up
• Provides big amount of features• Has everything for SPA development• Limits usage of other frameworks• Learning curve is being quite high
Useful components and links
• https://angularjs.org/• http://angular-ui.github.io/ - bootstrap
components for angular