AngularJS
class: center, middle .title[  ] --- class: center, middle  --- class: center middle .title[ # Simple App - [Demo](examples/simple-app.html) ] .demo[
] --- class: center, middle .left[ ## Angular module ```js angular.module('simpleApp',[]) .controller('Ctrl', function ( $scope ) { $scope.students = [ ... ]; }); ``` ] .left[ ## HTML markup ```html
Found: {{ query.length ? filtered.length : 0 }}
{{ name }}
``` ] --- class: center middle # How it works...? ## !@#$%^%$&  --- # Entrance points: - ###Custom HTML nodes - ###Custom HTML attributes - ###Special instructions in HTML template - ###AngularJS to process it all
.left[ ## HTML markup ```html
``` ] --- # How Angular processes HTML: - ###Read node/attribute name - ###Search internal registry for attribute logic - ###Runs that logic ## HTML markup ```html
{{$ctrl.valueFromController}}
{{valueFromControllerScope}}
``` ```javascript const module = angular.module('simpleApp',[]); module.controller('MyCoolController', ['$scope', function($scope) { this.valueFromController = "This will be displayed in div"; $scope.valueFromControllerScope = "Another way to display something" }); ``` --- #Learning curve
--- ## AngularJS and MVC - ###Controller + Scope + HTML template = MVC - ###HTML template - for a View. No business logic. - ###Scope - Simple object to link JS values with HTML nodes - ###Controller - JS function to change values in Scope. - ###Component: Controller + Scope + Template. And public API: Bindings ## HTML markup ```html
``` --- .left[ ```javascript const studentsListComponentDefinition = { bindings: { listSource: '<' }, template: `
Student initials: {{$ctrl.getInitials(item)}}
`, controller: function() { this.getInitials = function (student) { return `${student.name[0]}. ${student.surname[0]}.` } }, controllerAs: '$ctrl' } const module = angular.module('simpleApp',[]); module.component('StudentsList', studentsListComponentDefinition); ``` ] --- class: center middle .title[ #Concepts ] .left[ - ##Dependency Injection - ##Scope - ##Data Binding - ##Directive/Component - ##Controller - ##Service ] --- class: center middle .title[ #Dependency Injection ] ##There are only three ways a component (object or function) can get a hold of its dependencies: .left[ - ###The component can create the dependency, typically using the ***new*** operator. - ###The component can look up the dependency, by referring to a global variable. - ###The component can have the dependency passed to it where it is needed. ] --- class: center middle .title[ #Dependency Annotation ] .left[ - ###Using the inline array annotation ```js someModule.controller('MyController', ['$scope', '$http', function($scope, $http) { // ... }]); ``` - ###Using the $inject property annotation ```js var MyController = function($scope, $http) { // ... } MyController.$inject = ['$scope', '$http']; someModule.controller('MyController', MyController); ``` - ###Implicitly from the function parameter names (has caveats) ```js someModule.controller('MyController', function($scope, $http) { // ... }); ``` ] --- #Scope .left[ - ###Scope is an object that refers to the application model. - ###It is an execution context for expressions. - ###Scopes are arranged in hierarchical structure which mimic the DOM structure of the application. - ###Scopes can watch expressions and propagate events. ] ```html
{{someValue}} {{$ctrl.anotherValue}}
``` ```javascript const module = angular.module('simpleApp',[]); module.controller('MyCoolController', ['$scope', function($scope) { console.log($scope.$ctrl === this); // <-- true; $scope.someValue = "some string value"; this.anotherValue = "another value"; }); ``` --- class: center middle .title[ #Scope Characteristics ] .left[ - ###Scopes provide APIs (***$watch***) to observe model mutations. - ###Scopes provide APIs (***$apply***) to propagate any model changes through the system into the view from outside of the "Angular realm" (controllers, services, Angular event handlers). - ###Scopes provide APIs (***$on***, ***$emit***, ***$broadcast***) for dispatching/subscribing custom events - ###Scopes can be nested to limit access to the properties of application components while providing access to shared model properties. - ###Scopes provide context against which ***expressions*** are evaluated. ] --- class: center middle # Event Loop
--- #Data Binding .left[ - ###Any changes to the view are immediately (after digest loop) reflected in the model, and any changes in the model are propagated to the view. - ###The model is the single-source-of-truth for the application state, greatly simplifying the programming model for the developer. - ###You can think of the view as simply an instant projection of your model. ] --- #Data Binding. How it works? ```html
{{scopeProperty}}
``` ```javascript class SomeController { constructor($scope) { $scope.scopeProperty = 123; this.controllerValue = 456; } } SomeController.$inject = ['$scope']; angular.module('es2015App', []).controller('someController', SomeController); ``` ###It creates 2 watches: ```javascript $scope.$watch('scopeProperty', ...); $scope.$watch('$ctrl.controllerValue', ...); ``` --- class: center middle  --- #Dependency Annotation - ###Using the $inject property annotation for class ```js class MyController { constructor($scope, $http) { //... } } MyController.$inject = ['$scope', '$http']; someModule.controller('MyController', MyController); ``` --- class: center middle .title[ # Modules ] .left[ ##Creation ```js /*var myMod = */angular.module('myModule', [ 'dep1', 'dep2',/* ... */ 'depN']); ``` ] .left[ ##Retrieval ```js /*var myMod = */angular.module('myModule'); ``` ] .left[ ##Configuration ```js angular.module('myModule', []) .config(function(injectables){ /* provider-injector */}) .run(function(injectables){ /* instance-injector */}) .value('a', 123) .factory('a', function() { return 123; }) .directive('directiveName', ...) .filter('filterName', ...) /*...*/; ``` ] --- class: center, middle .title[ # Injector ] .left[ ##In Angular apps most of the objects are instantiated and wired together automatically by the ***injector service***. ```js var $injector = angular.injector(); // inferred (only works if code not minified/obfuscated) $injector.invoke(function(serviceA){}); // annotated function explicit(serviceA) {}; explicit.$inject = ['serviceA']; $injector.invoke(explicit); // inline $injector.invoke(['serviceA', function(serviceA){}]); ``` ] .left[ ##The injector creates two types of objects, ***services*** and ***specialized objects***. ] --- class: center middle .title[ # Services ## The injector needs to know how to create these objects. ##You tell it by registering a "recipe" for creating your object with the injector. ] .left[ - ###Value - ###Factory - ###Service - ###Provider - ###Constant ] --- class: center, middle .title[ # Service "Value" ] .left[ ```js myModule.value('labId', 'FL5'); ``` ```js myModule.controller('MyCtrl', function ( $scope, labId ) { $scope.lab_id = labId; }) ``` ```html
Lab ID:
{{ lab_id }}
``` ] --- class: center, middle .title[ # Service "Factory" ] .left[ ```js myModule.factory('labInfo', function ( /* injectables */ ) { return { labId : 'FL5' } }); ``` ```js myModule.controller('MyCtrl', function ( $scope, labInfo ) { $scope.labInfo = labInfo; }) ``` ```html
Lab ID:
{{ labInfo.labId }}
``` ] --- class: center middle .title[ # Service "Service" ] .left[ ```js myModule.service('labInfo', function ( /* injectables */ ) { this.labId : 'FL5' }); ``` ```js myModule.controller('MyCtrl', function ( $scope, labInfo ) { $scope.labInfo = labInfo; }) ``` ```html
Lab ID:
{{ labInfo.labId }}
``` ] --- class: center, middle .title[ # Service "Provider" ] .left[ ```js myModule.provider('labInfo', function () { var _prefix = ''; this.setPrefix = function ( pref ) { _prefix = pref; }; this.$get = function ( /* injectables */ ) { return { labId : _prefix + 'FL5' } } }); ``` ```js myModule.controller('MyCtrl', function ( $scope, labInfo ) { $scope.labInfo = labInfo; }) ``` ```html
Lab ID:
{{ labInfo.labId }}
``` ] --- class: center, middle .title[ # Module Config ] .left[ ```js angular.module('myModule', []). .value('a', 123) .factory('a', function() { return 123; }) .directive('directiveName', ...) .filter('filterName', ...); // is same as angular.module('myModule', []). config(function($provide, $compileProvider, $filterProvider) { $provide.value('a', 123); $provide.factory('a', function() { return 123; }); $compileProvider.directive('directiveName', ...); $filterProvider.register('filterName', ...); }); }); ``` ] --- class: center, middle .title[ # Module Config ] .left[ ```js myModule.provider('labInfo', function () { var _prefix = ''; this.setPrefix = function ( pref ) { _prefix = pref; }; this.$get = function ( /* injectables */ ) { return { labId : _prefix + 'FL5' } } }); ``` ] .left[ ```js myModule.config(function (labInfoProvider) { labInfoProvider.setPrefix('epam_'); }); ``` ] --- class: center, middle .title[ # Built-in Providers ] .left.img-wrap-50[ ```js $anchorScrollProvider $animateProvider $compileProvider $controllerProvider $filterProvider *$httpProvider $interpolateProvider $locationProvider $logProvider $parseProvider $qProvider $rootScopeProvider $sceDelegateProvider $sceProvider $templateRequestProvider ``` ] --- class: center, middle .title[ # $http service ] .left[ ## Basic Usage ] .left[ ```js $http({ method: 'GET', url: '/someUrl' }).then(function successCallback(response) { // this callback will be called asynchronously // when the response is available }, function errorCallback(response) { // called asynchronously if an error occurs // or server returns response with an error status. }); ``` ] .left[ ### Shortcut methods ] .left[ ```js $http.get('/someUrl', config).then(successCallback, errorCallback); $http.post('/someUrl', data, config).then(successCallback, errorCallback); ``` ] --- class: center, middle .title[ # $http service ] .left[ ## Response object ] .left[ ```js { data, // – {string|Object} – The response body transformed with the transform functions. status, // – {number} – HTTP status code of the response. headers, // – {function([headerName])} – Header getter function. config, // – {Object} – The configuration object that was used to generate the request. statusText, // – {string} – HTTP status text of the response. } ``` ] --- class: center, middle .title[ # UI Router ] .left[ ### Angular UI-Router is a client-side Single Page Application routing framework for AngularJS. ### Routing frameworks for SPAs update the browser's URL as the user navigates through the app. Conversely, this allows changes to the browser's URL to drive navigation through the app, thus allowing the user to create a bookmark to a location deep within the SPA. ### UI-Router applications are modeled as a hierarchical tree of states. ] --- class: center, middle .title[ # UI Router ] # Setup .left[ ```html
``` ] .left[ ```js myModule.config(function($stateProvider) { $stateProvider .state('state1', { url: "/state1", templateUrl: "partials/state1.html" }) .state('state1.list', { url: "/list", templateUrl: "partials/state1.list.html", controller: function($scope) { $scope.items = ["A", "List", "Of", "Items"]; } }); }); ``` ] --- class: center, middle .title[ # UI Router ] # Activating a state .left[ - Call ``` $state.go() ```. High-level convenience method. - Click a link containing the ``` ui-sref ``` directive. - Navigate to the url associated with the state. ] --- class: center, middle .title[ # UI Router ] # State Change Events ### All these events are fired at the $rootScope level. .left[ ```js $rootScope.$on( 'eventName', function(event, toState, toParams, fromState, fromParams, options){ ///... } ); ``` - ```$stateChangeStart``` - fired when the transition begins. - ```$stateChangeSuccess``` - fired once the state transition is complete. - ```$stateChangeError``` - fired when an error occurs during transition. ] --- class: center middle .title[ #Practice ] .middle[ .img-wrap-70[] ] .center[ ##Create angular directive to display/edit student info in card view. ([ref1](practice/index.html), [ref2](https://plnkr.co/edit/ZejRPicd7UjDD3UIso9Y?p=preview)) ] .left[ - create js file called studentname-studentsurname.js (e.g. john-doe.js) - create angular module called 'studentname.studentsurname' (e.g. 'john.doe') - create angular directive that can be used as element ```
``` (e.g. ```
```) ] --- # Related resources - [AngularJS API Reference](https://docs.angularjs.org/api) - [Creating AngularJS Custom Directives](http://weblogs.asp.net/dwahlin/creating-custom-angularjs-directives-part-i-the-fundamentals) - [Angular 1 Style Guide](https://github.com/johnpapa/angular-styleguide/blob/master/a1/README.md)