2. Brief overview
Quick intro (~2 min)
Core concepts:
- Modules
- DI
- Controllers
- Scopes
- Views
- Directives
- Templates
- Filters
- Providers
Change detection
Note: (lns are based on Angular 1.4.0-rc.0)
3. quick intro
(in case living under a rock)
- “JAVA script” client side framework
(they call it like that when they contact you from an HR agency)
- Imposes MVW architecture
- Component based
- DI
4. module
- Logical containers
- Module -> [controllers, filters, directives, services, factories, animations, configs]
Example:
angular.module('yourApp', ['yourDependency']);
its phases - or blocks:
- config
(define your app configuration, e.g. routes, only providers & constants)
- run
(similar to a main method, not needed but sometimes useful, only instances & constants)
5. DI
- each app has one $injector
- $injector can instantiate types, invoke
methods, load modules
- instance cache + instance factory
- credited with making all providers singletons
- $injector.get()
-> if inCache() return from cache
-> else instantiate
a small DI usage example :
yourApp.controller('yourCtrl', function($scope) {});
6. controller
- more like view models, less like controllers
- controller ~ view relation: 1-1
- can be used in relation 1-m (not the usual practice)
- each controller has its own scope and view which
contains what is shown
- created by ~ $controllerProvider
(lns 8645 - 8791)
7. scopes
- objects containing view related functions and properties
- each controller has one
- app has one “parent” scope ~ $rootScope
- children can have their own children
8. views
At the beginning (0.x ~ 1.x) there were only classic,
because the ng team thought directives could be used as
composite views with state
- classic views: ng-route
- kinda composite: ng-include
- composite views: ui-router
10. expressions
- code placed in “{{ }}” handlebars represent expressions
example:
<div>{{ 3+5 }}</div>
- before rendering the actual template, its expressions
are compiled by $interpolate service
- detrimental to performance
- always check their performance with batarang
- one time binding “::” (!= one-way data binding)
(lns 10485 - 10584)
11. directives
- composable components
- can have their own scope
- they are not providers, as they are more of an extension
to the DOM elements, but they do have their
$compileProvider (lns 5924 - 8518)
- can have its own controller
(one of the reasons why in the first Angular versions there was no need for composite view)
12. DDO
yourModule.directive('directiveName', function factory(injectables) {
var directiveDefinitionObject = {
priority: 0,
template: '<div></div>', // or // function(tElement, tAttrs) { ... },
// or
// templateUrl: 'directive.html', // or // function(tElement, tAttrs) { ... },
transclude: false,
restrict: 'A',
replace: true,
templateNamespace: 'html',
scope: false,
controller: function($scope, $element, $attrs, $transclude, otherInjectables) { /**...*/ },
controllerAs: 'stringIdentifier',
bindToController: false,
require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?
^optionalParent'],
compile: function compile(tElement, tAttrs, transclude) {
return {
pre: function preLink(scope, iElement, iAttrs, controller) { /**...*/ },
post: function postLink(scope, iElement, iAttrs, controller) { /**...*/ }
};
// or
// return function postLink( ... ) { ... }
}
// or
// link: {
// pre: function preLink(scope, iElement, iAttrs, controller) { ... },
// post: function postLink(scope, iElement, iAttrs, controller) { ... }
// }
// or
// link: function postLink( ... ) { ... }
};
return directiveDefinitionObject;
});
14. directive source example
/**
* @question
* Guess which element does this native directive extend?
*/
var htmlAnchorDirective = valueFn({
restrict: 'E',
compile: function(element, attr) {
if (!attr.href && !attr.xlinkHref) {
return function(scope, element) {
// If the linked element is not an anchor tag anymore, do nothing
if (element[0].nodeName.toLowerCase() !== 'a') return;
// SVGAElement does not use the href attribute, but rather the 'xlinkHref' attribute.
var href = toString.call(element.prop('href')) === '[object SVGAnimatedString]' ?
'xlink:href' : 'href';
element.on('click', function(event) {
// if we have no href url, then don't navigate anywhere.
if (!element.attr(href)) {
event.preventDefault();
}
});
};
}
}
});
15. directives
most usable ones:
- model
- event (ng-click, ng-mouseover...)
- value
- bind
- class
- include
- repeat
- show
- switch
the main list is within lns 18928 - 27672
16. filters
- think of it as a formatter
- an ng service used for formatting data to the user
- example
{{ expression | filter_name[:parameter_value] ... ] }}
- when registering them, Angular automatically adds
“Filter” postfix to them, in order not to mix them with
other services
- all filters are handled by their own provider ~
$FilterProvider
(lns 17663 - 18926)
18. providers
- referred to as “services” (op term)
- Represent the state of your app
- List of providers:
provider
constant
factory
service
decorator
value
(lns 4170 - 4402)
19. provider
- Configurable factory
- Meaning it has configuration options and a creation
function ($get)
- Can be used during the config phase
- // angular.provider('providerName');
20. provider source
function provider(name, provider_) {
assertNotHasOwnProperty(name, 'service');
if (isFunction(provider_) || isArray(provider_)) {
provider_ = providerInjector.instantiate(provider_);
}
if (!provider_.$get) {
throw $injectorMinErr('pget', "Provider '{0}' must define $get factory method.",
name);
}
return providerCache[name + providerSuffix] = provider_;
}
21. provider examples
someModule.provider('providerName', function (){
var trackingUrl = '/track';
// A provider method for configuring where the tracked events should been saved
this.setTrackingUrl = function(url) {
trackingUrl = url;
};
// The service factory function
this.$get = ['$http', function($http) {
var trackedEvents = {};
return {
// Call this to track an event
event: function(event) {
var count = trackedEvents[event] || 0;
count += 1;
trackedEvents[event] = count;
return count;
},
// Call this to save the tracked events to the trackingUrl
save: function() {
$http.post(trackingUrl, trackedEvents);
}
};
}];
});
22. factory
- well known
- most widely used
- private functions
- provider with a $get function
- // angular.factory('someFactory', factoryObject)
23. factory source
function factory(name, factoryFn, enforce) {
return provider(name, {
$get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn
});
}
function enforceReturnValue(name, factory) {
return function enforcedReturnValue() {
var result = instanceInjector.invoke(factory, this);
if (isUndefined(result)) {
throw $injectorMinErr('undef', "Provider '{0}' must return a value from $get
factory method.", name);
}
return result;
};
}
25. constant
- we all know what constant means
- can’t be decorated (not shit, Sherlock)
- injectable during config phase
- Example:
angular.constant('someConstantName',
constantValue)
28. value
- can not be injected in the config phase
- represents an angular variable that can be injected and used
throughout your providers, directives, controllers
example:
angular.value('someValue', actualValue)
33. decorator
- Service instantiation interceptor
- Behavior override
- Modify / encapsulate other providers
- Can decorate every provider, except constant
- Less known, barely used
- why?
- angular-mocks uses it to add flush() to $timeout
angular.decorator('someDecorator', decoratorObj);
35. decorator example
/**
* @description
*
* Here we decorate the ns.$log service to convert warnings to errors
*/
angular.decorator('$log', ['$delegate', function ($delegate) {
delegate.warn = delegate.error;
return delegate;
}]);
36. Change detection
- dirty checking
- consists of running equality checks over all
of the data that the view depends on