DEPENDENCY INJECTION
SCOPES
That was EASY PEASY...
...NOW 4 THE REAL STUFF
BASE RULEs
- no other global var than angular
- one file per definition
- dependency injection is brilliant: use it
- testing IS AS EASY AS IT CAN GET: DO IT
- DEDICATED MODULES FOR REUSABLE COMPONENTS
DEFINING A MODULE
angular.module('moduleName', [/* deps */]);
RETRIEVING A MODULE
angular.module('moduleName');
ADDING FUNCTIONALITY
angular.module('moduleName')
.animation()
.config()
.constant()
.controller()
.directive()
.factory()
.filter()
.provider()
.requires()
.run()
.service()
.value()
see: https://docs.angularjs.org/api/ng/type/angular.Module
BOOTSTRAPPING
<body ng-app="my-module">
<div ng-view></div>
</body>
WE NEED A ROUTE!
DEFINING ROUTES
angular.module('myModule', ['ngRoute']);
ngRoute provides
$routeProvider, $route and $routeParams
$routeProvider, $route and $routeParams
angular.module('myModule').config(['$routeProvider', function($routeProvider) { $routeProvider .when('/detail/:id', { controller: 'DetailCtrl', template: 'detail.html' }); }]);
WE NEED A CONTROLLER!
DEFINING CONTROLLERS
angular.module('myModule.controllers').controller('DetailCtrl', ['$scope', function($scope) { // gluecode }]);
WE NEED A (VIEW) TEMPLATE!
DEFINING A TEMPLATE
<div> <span ng-repeat="greetings as greeting">{{greeting|lowercase}}</span> <button ng-click="doSomething()">{{buttonText}}</button> </div>
DONE!
RELAX BEFORE WE GO AHEAD
BUILTIN FILTERS
- filter
- currency
- number
- date
- json
- lowercase
- uppercase
- limitTo
- orderBy
USING FILTERS
in template
<span>{{value|filter-name:arg1:arg2:...}}</span>
in javascript
$filter('filter-name')(value, arg1, arg2, ...)
see: https://docs.angularjs.org/api/ng/filter/filter & https://docs.angularjs.org/guide/filter
BUILDING CUSTOM FILTERS
angular.module('myModule.filters').filter('filterName', [ function() { return function(input, arg1, arg2, arg3) { return input + arg1 + arg2 + arg3; } }]);
see: https://docs.angularjs.org/guide/filter
DEFINITELY GOT THAT FILTER
THING NOW
BUILTIN DIRECTIVES
- as elements (E)
- a, form, input, script, select, textarea
- as attributes (A)
- ngApp
- ngBlur
- ngClick
- ngDblClick
- ngHref
- ngIf
- among 52 others
see: https://docs.angularjs.org/api/ng/directive
USING DIRECTIVES
<div ng-repeat="thing in things"> <span ng-dblclick="toggle(thing.id)">{{thing.description}}</span> <span ng-if="thing.additionalInfo">{{thing.additionalInfo}}</span> <a ng-href="thing.link.href">{{thing.link.text}}</a> <button ng-click="showDetailView(thing.id)"></button> </div>
CUSTOM DIRECTIVES
angular.module('myModule.directives').directive('directiveName', [ function() { return { restrict: 'AEC', template: '<span>{{value}}</span>' } }]);
in template
<div> <directive-name></directive-name> </div>
compiled
<div> <span>some text</span> </div>
see: https://docs.angularjs.org/guide/directive
THAT'S ALL?
ISOLATING DIRECTIVE'S SCOPE
angular.module('myModule.directives').directive('directiveName', [ function() { return { scope: {} } }]);
- overriding does the job
- now the directive has its own scope
and we can pass in arguments
PASSING ARGUMENTS TO DIRECTIVES
<div> <directive-name an-argument="{{someValue}}"></directive-name> </div>
angular.module('myModule.directives').directive('directiveName', [ function() { return { scope: { anArgument: '=' // also: @ / & }, template: '<span>{{anArgument}}</span>' } }]);
@&=???
@
attribute
=
binding
&
expression
see: http://onehungrymind.com/angularjs-sticky-notes-pt-2-isolated-scope/
DOM MANIPULATING DIRECTIVES
<div> <span directive-name></span> </div>
angular.module('myModule.directives').directive('directiveName', [ function() { // this is javascript here so feel free to do whatever you want return function(scope, element, attrs) { element.text('hi'); } }]);
compiled
<div> <span>hi</span> </div>
TRANSCLUSION
TRANSCLUSION!!! !
TRANSCLUSION
<div> <directive-name><span>Some text</span></directive-name> </div>
angular.module('myModule.directives').directive('directiveName', [ function() { return { transclude: true, template: '<div ng-transclude></div>' } }]);
compiled
<div> <div><span>Some text</span></div> </div>
DIRECTIVES WITH EVENT HANDLERS
angular.module('myModule.directives').directive('directiveName', [ function() { return function(scope, element, attr) { element.on('mouseenter', function(event) { event.preventDefault(); // it's javascript, feel fre-- ahh you know... }); } }]);
DIRECTIVES THAT REQUIRE DIRECTIVES
angular.module('myModule.directives').directive('directiveOne', [ function() { return { scope: {}, controller: function($scope) { $scope.method = function() {}; } } }])
angular.module('myModule').directive('directiveNameTwo', [function() { return { require: '^directiveOne', link: function(scope, elements, attrs, directiveOneController) { directiveOneController.method(); } } }])
STILL WITH ME?
BUILTIN SERVICES
- $animate
- $compile
- $filter
- $http
- $location
- $q
- $timeout
- among 17 others
USING A SERVICE
angular.module('myModule.controllers').controller('DetailCtrl', ['$scope', '$http', function($scope, $http) { $scope.data; $http.get('yourapi/yourresponse.json') .success(function(data, status, headers, config) { $scope.data = data; }) .error(function(data, status, headers, config) { // ... }); }]);
CUSTOM PROVIDERS: RECIPE TYPES
VALUE
CONSTANT
FACTORY
SERVICE
PROVIDER
see: https://docs.angularjs.org/guide/providers
RECIPE TYPE: VALUE
definition
angular.module('myModule').value('foo', 'value value');
usage
angular.module('myModule.controllers').controller('CtrlName', ['$scope', 'foo', function($scope, foo) { $scope.name = foo; }]);
<div> <span>{{name}}</span> </div>
RECIPE TYPE: CONSTANT
definition
angular.module('myModule').constant('BAR', 'value value');
usage
angular.module('myModule.controllers').controller('CtrlName', ['$scope', 'BAR', function($scope, BAR) { $scope.name = BAR; }]);
<div> <span>{{name}}</span> </div>
RECIPE TYPE: FACTORY
definition
angular.module('myModule.s').factory('myFactory', [function() { var self = {}; self.returnName = function() { return 'a name'; } return self; }]);
usage
angular.module('myModule').controller('CtrlName', ['$scope', 'myFactory',
function($scope, myFactory) { $scope.name = myFactory.returnName(); }]);
RECIPE TYPE: SERVICE
definition
function ConstFct() { this.someValue = 0; this.someMethod = function() {}; } angular.module('myModule').service('myService', [ConstFct]);
usage
angular.module('myModule').controller('CtrlName', ['$scope', 'myService',
function($scope, myService) { $scope.name = myService.someMethod(); }]);
RECIPE TYPES: OVERVIEW
DONT'S
USING
THE
ROOTSCOPE
USE
JQUERY
AND
APPLY()
EVERYWHERE
MANIPULATE
THE
DOM
WITH
THE
CONTROLLER
SELECTOR
INSIDE
LINK()
BUSINESS
LOGIC
IN
THE
CONTROLLER
DO'S
STORE
DATA
IN
YOUR
SERVICE
ONE
FILE
PER
DEFINITION
TOOLS?
BATARANG
(CHROME)
ANGULAR
(*STORM)
ANGULAR
(*STORM)
PLNKR.CO
FIN
Angular JS Introduction
By Marc Dix
Angular JS Introduction
Some images
- 1,558