IPT – Intellectual Products & Technologies Trayan Iliev, http://www.iproduct.org/
AngularJS and TypeScript
SPA Development
Slide 1Sources: AngularJS [ https://docs.angularjs.org ], AngularJS Hub [ http://www.angularjshub.com/ ]
Licensed under the Creative Commons Attribution-ShareAlike 3.0 License
AngularJS Projects, Forms and Services
Trayan Iliev
IPT – Intellectual Products & Technologiese-mail: [email protected]
web: http://www.iproduct.org
Oracle®, Java™ and JavaScript™ are trademarks or registered trademarks of Oracle and/or its affiliates.Microsoft .NET, Visual Studio and Visual Studio Code are trademarks of Microsoft Corporation.
Other names may be trademarks of their respective owners.
IPT – Intellectual Products & Technologies Trayan Iliev, http://www.iproduct.org/
AngularJS and TypeScript
SPA Development
Slide 2Sources: AngularJS [ https://docs.angularjs.org ], AngularJS Hub [ http://www.angularjshub.com/ ]
Licensed under the Creative Commons Attribution-ShareAlike 3.0 License
Agenda
1. Seed project2. Proposed project structure3. Proposed module structure4. AngularJS form support5. Form directives and styles6. Form validation and building custom validators7. AngularJS built-in services – $log, $q, $http, $resource8. Custom services – using factory and service methods9. Using promises10.Filters11.Creating custom filters
IPT – Intellectual Products & Technologies Trayan Iliev, http://www.iproduct.org/
AngularJS and TypeScript
SPA Development
Slide 3Sources: AngularJS [ https://docs.angularjs.org ], AngularJS Hub [ http://www.angularjshub.com/ ]
Licensed under the Creative Commons Attribution-ShareAlike 3.0 License
Sinagle Page Apps (SPA) in 3 steps
1) Setting up a build system – npm, webpack, gulp are common choices, babel, typescript, JSX, CSS preprocessors (SASS, SCSS, LESS), jasmine, karma, protractor, Yeoman/ Slush, live servers
2) Designing front-end architecture components – views & layouts + view models (presentation data models) + presentation logic (event handling, messaging) + routing paths (essential for SPA)
Better to use component model to boost productivity and maintainability.
3) End-to-end application design – front-end: wireframes → views,data entities & data streams → service API and models design,sitemap → router config
IPT – Intellectual Products & Technologies Trayan Iliev, http://www.iproduct.org/
BG OUG Meeting – Pravetz November 20, 2015
Slide 4Licensed under the Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License
Simple Project Structure
typescript-projectsrc
app.ts / main.tstodo.controller.ts
distnode_modules ...typings ...index.htmlpackage.jsonstyles.csstsconfig.jsontypings.json
IPT – Intellectual Products & Technologies Trayan Iliev, http://www.iproduct.org/
AngularJS and TypeScript
SPA Development
Slide 5Sources: AngularJS [ https://docs.angularjs.org ], AngularJS Hub [ http://www.angularjshub.com/ ]
Licensed under the Creative Commons Attribution-ShareAlike 3.0 License
Seed Project: Proposed Project Structure
We will be using a seed project in order to speed up the first step (project setup) and guide the design and development:
https://github.com/dsebastien/angularjs-webpack-starter
AngularJS + Webpack + TypeScript – not so many choices:)
Mature and promotes best practices (backported from ng2)
Redux (one-way data flow for shared state management), Immutable.js, RxJS, Lodash, PostCSS, Autoprefixer, Karma (unit test runner), Protractor (end-to-end test framework), Jasmine (bdd unit testing library), Istanbul (generate code coverage reports), TSLint, TypingsTSDoc, moment, Sinon.JS, SASS, JSData
IPT – Intellectual Products & Technologies Trayan Iliev, http://www.iproduct.org/
AngularJS and TypeScript
SPA Development
Slide 6Sources: AngularJS [ https://docs.angularjs.org ], AngularJS Hub [ http://www.angularjshub.com/ ]
Licensed under the Creative Commons Attribution-ShareAlike 3.0 License
Seed Project Advantges (1)
Hot module replacement (HMR) –http://andrewhfarmer.com/understanding-hmr/ http://andrewhfarmer.com/webpack-hmr-tutorial/
Unit tests (Karma & Jasmine)
End to end tests (Protractor)
Test coverage reports (Istanbul) – html, lcov, junit
TS to ES5 transpilation (TypeScript) -
SASS to CSS transpilation (SASS)
TS quality/style checks (TSLint)
IPT – Intellectual Products & Technologies Trayan Iliev, http://www.iproduct.org/
AngularJS and TypeScript
SPA Development
Slide 7Sources: AngularJS [ https://docs.angularjs.org ], AngularJS Hub [ http://www.angularjshub.com/ ]
Licensed under the Creative Commons Attribution-ShareAlike 3.0 License
Seed Project Advantges (2)
TS code documentation generation (TSDoc)
Development and production configurations
Optimizations for production (minification, compression, ...)
Security best practices applied to dev server configuration
Content Security Policy (CSP)
Other security headers
...
IPT – Intellectual Products & Technologies Trayan Iliev, http://www.iproduct.org/
AngularJS and TypeScript
SPA Development
Slide 8Sources: AngularJS [ https://docs.angularjs.org ], AngularJS Hub [ http://www.angularjshub.com/ ]
Licensed under the Creative Commons Attribution-ShareAlike 3.0 License
Seed Project: Recommended Structure
project-rootsrc
appmodules – your code here (AngularJS modules)
typings – only custom TypeScript type definitions (.d.ts) index.htmlmain.ts – bootstrapping the AngularJS applicationmain-styles.ts – imports application specific styles vendor.ts – imports all used JS dependency librariesvendor-styles.ts – imports vendor styles(MD, bootstrap)
...
IPT – Intellectual Products & Technologies Trayan Iliev, http://www.iproduct.org/
AngularJS and TypeScript
SPA Development
Slide 9Sources: AngularJS [ https://docs.angularjs.org ], AngularJS Hub [ http://www.angularjshub.com/ ]
Licensed under the Creative Commons Attribution-ShareAlike 3.0 License
Recommended Module Structure (1)
<module_name> - folder for the module<module_name>.ts - AngularJS module definitioncomponents - containins all the components of that module
<component_name> - component folder in the module
<component_name>.controller.ts - controller (*)<component_name>.controller.spec.ts - unit tests (*)<component_name>.template.html - template/partial view of the component (*) _<component_name>.scss - styles (starts with `_` )<component_name>.model.ts - model
IPT – Intellectual Products & Technologies Trayan Iliev, http://www.iproduct.org/
AngularJS and TypeScript
SPA Development
Slide 10Sources: AngularJS [ https://docs.angularjs.org ], AngularJS Hub [ http://www.angularjshub.com/ ]
Licensed under the Creative Commons Attribution-ShareAlike 3.0 License
Recommended Module Structure (2)
<module_name> - folder for the module … ( - continues - ) …
services - folder containing all the services of that module <service_name>.service.ts - a service
<service_name>.service.spec.ts - unit tests for a service
filters - folder containing all the filters of that module <filter_name>.filter.ts – filter factory
<filter_name>.filter.spec.ts - unit tests for a filter
IPT – Intellectual Products & Technologies Trayan Iliev, http://www.iproduct.org/
AngularJS and TypeScript
SPA Development
Slide 11Sources: AngularJS [ https://docs.angularjs.org ], AngularJS Hub [ http://www.angularjshub.com/ ]
Licensed under the Creative Commons Attribution-ShareAlike 3.0 License
AngularJS Forms (1)<form novalidate class="simple-form" role="form"><div class="form-group"><label for="name">Product Name: </label> <input type="text"class="form-control" ng-model="$ctrl.product.name"></div><div class="form-group"><label for="vendor">Vendor: </label> <input type="text"class="form-control" ng-model="$ctrl.product.vendor"></div>
<input type="submit" ng-click="$ctrl.update()" value="Save"class="btn btn-default" /> <input type="button"ng-click="$ctrl.reset()" value="Reset" class="btn btn-default" /></form><pre>user = {{$ctrl.product | json}}</pre><pre>master = {{$ctrl.productMaster | json}}</pre>
IPT – Intellectual Products & Technologies Trayan Iliev, http://www.iproduct.org/
AngularJS and TypeScript
SPA Development
Slide 12Sources: AngularJS [ https://docs.angularjs.org ], AngularJS Hub [ http://www.angularjshub.com/ ]
Licensed under the Creative Commons Attribution-ShareAlike 3.0 License
AngularJS Forms (2)export class AddProductController extends AbstractController { modalShown: boolean = false; productMaster: Product = { 'id': 0, 'name': '', 'permalink': '', 'snippet': '', 'currency': 'USD' }; product: Product; static $inject: Array<string> = ['$log', '$state']; public constructor(logger: ILogService, $state:IStateService){ super(logger, $state); this.reset(); logger.debug('AddProductController loaded...'); }
IPT – Intellectual Products & Technologies Trayan Iliev, http://www.iproduct.org/
AngularJS and TypeScript
SPA Development
Slide 13Sources: AngularJS [ https://docs.angularjs.org ], AngularJS Hub [ http://www.angularjshub.com/ ]
Licensed under the Creative Commons Attribution-ShareAlike 3.0 License
AngularJS Forms (3) ...
toggleModal(): void { this.modalShown = !this.modalShown; };
update(): void { this.productMaster = angular.copy(this.product); };
reset(): void { this.product = angular.copy(this.productMaster); };
}
IPT – Intellectual Products & Technologies Trayan Iliev, http://www.iproduct.org/
AngularJS and TypeScript
SPA Development
Slide 14Sources: AngularJS [ https://docs.angularjs.org ], AngularJS Hub [ http://www.angularjshub.com/ ]
Licensed under the Creative Commons Attribution-ShareAlike 3.0 License
Form State CSS Classes
CSS classes dynamically added to components and the form to reflect their state (added by ngModel.NgModelController and form.FormController):
ng-valid - the model is validng-invalid - the model is invalidng-valid-[key] - for each valid key added by $setValidityng-invalid-[key] - for each invalid key added by $setValidityng-pristine - the control hasn't been interacted with yetng-dirty - the control has been interacted withng-touched - the control has been blurredng-untouched - the control hasn't been blurredng-pending - any $asyncValidators are unfulfilled
IPT – Intellectual Products & Technologies Trayan Iliev, http://www.iproduct.org/
AngularJS and TypeScript
SPA Development
Slide 15Sources: AngularJS [ https://docs.angularjs.org ], AngularJS Hub [ http://www.angularjshub.com/ ]
Licensed under the Creative Commons Attribution-ShareAlike 3.0 License
Accessing Form State Programmatically<form name='productsForm' novalidate class="simple-form" role="form"> <input type="text" class="form-control" ng-model= "$ctrl.product.name" name="name" required ng-model-options="{ updateOn: 'default blur', debounce: { default: 1000, blur: 0 } }"> {{$ctrl.getItemState(productsForm.name)}}</form>
getItemState(item: ng.INgModelController): string { let state = ''; if (item.$pristine) state += 'pristine, '; if (item.$touched) state += 'touched, '; if (item.$dirty) state += 'dirty, '; if (item.$valid) state += 'valid'; if (item.$invalid) state += 'invalid'; return state;}
IPT – Intellectual Products & Technologies Trayan Iliev, http://www.iproduct.org/
AngularJS and TypeScript
SPA Development
Slide 16Sources: AngularJS [ https://docs.angularjs.org ], AngularJS Hub [ http://www.angularjshub.com/ ]
Licensed under the Creative Commons Attribution-ShareAlike 3.0 License
Binding to Form and Control State
Form (form, ngForm) is instance of FormController - can be published into the scope using the name form attribute
Input control that has the ngModel directive holds an instance of NgModelController - can be published as a property of the form instance using the name attribute on the input control
Binding to FormController and NgModelController allows to show custom error message after user interacted with control and upon submitting the form ($submitted is set):
<div ng-show="productsForm.$submitted || productsForm.name.$touched"><span ng-show="productsForm.name.$error.required">Product nameis required.</span></div>
IPT – Intellectual Products & Technologies Trayan Iliev, http://www.iproduct.org/
AngularJS and TypeScript
SPA Development
Slide 17Sources: AngularJS [ https://docs.angularjs.org ], AngularJS Hub [ http://www.angularjshub.com/ ]
Licensed under the Creative Commons Attribution-ShareAlike 3.0 License
Custom Model Update Triggers
ngModelOptions - tuning model updates, specifies custom events list triggering model updates and/or a debouncing:
ng-model-options= "{ updateOn: 'default blur', debounce: { default: 1000, blur: 0 } }
allowInvalid - if model can be set with values that did not validate correctly instead of the default behavior of setting the model to undefined
getterSetter - treat functions bound to ngModel as getters/setters
timezone - defines the timezone to be used to read/write the Date instance for <input type="date">, <input type="time">
IPT – Intellectual Products & Technologies Trayan Iliev, http://www.iproduct.org/
AngularJS and TypeScript
SPA Development
Slide 18Sources: AngularJS [ https://docs.angularjs.org ], AngularJS Hub [ http://www.angularjshub.com/ ]
Licensed under the Creative Commons Attribution-ShareAlike 3.0 License
Form Validation
Built-in validation directives: required, pattern, minlength, maxlength, min, max
Custom validators – functions receiving modelValue and viewValue as parameters. Return boolean or Promise (in case of $asyncValidators).
Synchronous validators – added to array of validators ngModelController.$validators Asynchronous validators – added to array of validators ngModelController.$asyncValidators, ngModelController.$pending object hash contains in-progresss asynchronous validators by key.
IPT – Intellectual Products & Technologies Trayan Iliev, http://www.iproduct.org/
AngularJS and TypeScript
SPA Development
Slide 19Sources: AngularJS [ https://docs.angularjs.org ], AngularJS Hub [ http://www.angularjshub.com/ ]
Licensed under the Creative Commons Attribution-ShareAlike 3.0 License
Synchronous Form Validator Exampleconst INTEGER_REGEXP = /^\w+(\-\w+)*$/;commonsModule.directive('permalink', function ($log: ng.ILogService): IDirective { return { require: 'ngModel', link: function (scope: ng.IScope, elm: HTMLElement, attrs: Attr, ctrl: ng.INgModelController): void { ctrl.$validators['permalink'] = function (modelValue: string, viewValue: string): boolean { if (ctrl.$isEmpty(modelValue)) return true; if (INTEGER_REGEXP.test(viewValue)) return true; return false; }; } };});
IPT – Intellectual Products & Technologies Trayan Iliev, http://www.iproduct.org/
AngularJS and TypeScript
SPA Development
Slide 20Sources: AngularJS [ https://docs.angularjs.org ], AngularJS Hub [ http://www.angularjshub.com/ ]
Licensed under the Creative Commons Attribution-ShareAlike 3.0 License
Asynchronous Form Validator ExamplecommonsModule.directive('permalinkUnique', ['$q', '$timeout', function($q: ng.IQService, $timeout: ng.ITimeoutService): IDirective{ return { require: 'ngModel', link: function (scope: ng.IScope, elm: HTMLElement, attrs: Attr, ctrl: ng.INgModelController): void { let permalinks = ['motorola-xoom', 'samsung-gem','lg-axis']; ctrl.$asyncValidators['permalinkUnique'] = function (mValue: string, vValue: string): ng.IPromise<boolean>{ if (ctrl.$isEmpty(modelValue)) return $q.when(true); let def = $q.defer(); $timeout(function (): void { if (permalinks.indexOf(modelValue) === -1) def.resolve(); else def.reject(); }, 2000); return def.promise; }; } };}]);
IPT – Intellectual Products & Technologies Trayan Iliev, http://www.iproduct.org/
AngularJS and TypeScript
SPA Development
Slide 21Sources: AngularJS [ https://docs.angularjs.org ], AngularJS Hub [ http://www.angularjshub.com/ ]
Licensed under the Creative Commons Attribution-ShareAlike 3.0 License
AngularJS Services
Angular services are substitutable objects that are wired together using dependency injection (DI). You can use services to organize and share code across your app.
Angular services are:Lazily instantiated – Angular only instantiates a service when an application component depends on itSingletons – Each component dependent on service gets reference to the single instance generated by the factory
They can be provided using:module.factory(name, providerFunction) ORmodule.service(name, constructor) - (ES6 & TS classes)
IPT – Intellectual Products & Technologies Trayan Iliev, http://www.iproduct.org/
AngularJS and TypeScript
SPA Development
Slide 22Sources: AngularJS [ https://docs.angularjs.org ], AngularJS Hub [ http://www.angularjshub.com/ ]
Licensed under the Creative Commons Attribution-ShareAlike 3.0 License
Service Registration using $provide
angular.module('myModule', []).config(['$provide', function($provide) {
$provide.factory('serviceId', function() {
var shinyNewServiceInstance;
// factory function body that constructs shinyNewServiceInstance
return shinyNewServiceInstance;
});
}]);
IPT – Intellectual Products & Technologies Trayan Iliev, http://www.iproduct.org/
AngularJS and TypeScript
SPA Development
Slide 23Sources: AngularJS [ https://docs.angularjs.org ], AngularJS Hub [ http://www.angularjshub.com/ ]
Licensed under the Creative Commons Attribution-ShareAlike 3.0 License
Using $provide Serviceangular.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', ...); });
IPT – Intellectual Products & Technologies Trayan Iliev, http://www.iproduct.org/
AngularJS and TypeScript
SPA Development
Slide 24Sources: AngularJS [ https://docs.angularjs.org ], AngularJS Hub [ http://www.angularjshub.com/ ]
Licensed under the Creative Commons Attribution-ShareAlike 3.0 License
AngularJS AJAX Services
$http – provides communication with the remote HTTP servers via the browser's XMLHttpRequest object or via JSONP.
$httpBackend – mock service used mainly for unit testing applications that use $http service
$resource – REST API client that provides higher level of abstraction
$q - deferred/promise API (basis for $http API) - two fashions: ES6 (ES2015) promises using $q constructorKris Kowal's Q or jQuery's Deferred implementations
$q is integrated with $rootScope.Scope model observation mechanism => faster propagation of resolution or rejection
IPT – Intellectual Products & Technologies Trayan Iliev, http://www.iproduct.org/
AngularJS and TypeScript
SPA Development
Slide 25Sources: AngularJS [ https://docs.angularjs.org ], AngularJS Hub [ http://www.angularjshub.com/ ]
Licensed under the Creative Commons Attribution-ShareAlike 3.0 License
Service vs Factoryclass CapitalizerService implements ICapitalizerService {static $inject=['$log']; constructor(private $log: ng.ILogService) {} capitalize(str: string): string { this.$log.info('\'' + str + '\' capitalized to \'' + str.toUpperCase() + '\''); return str.toUpperCase(); };}
function capitalizerService($log: ng.ILogService): CapitalizerService { let capitalize = (str: string): string => { $log.info('\'' + str + '\' capitalized to \'' + str.toUpperCase() + '\''); return str.toUpperCase(); }; return { capitalize: capitalize }; }
IPT – Intellectual Products & Technologies Trayan Iliev, http://www.iproduct.org/
AngularJS and TypeScript
SPA Development
Slide 26Sources: AngularJS [ https://docs.angularjs.org ], AngularJS Hub [ http://www.angularjshub.com/ ]
Licensed under the Creative Commons Attribution-ShareAlike 3.0 License
More AngularJS Services
$exceptionHandler – any uncaught exception in angular expressions is delegated to this service.
$httpParamSerializer – default $http params serializer that converts objects to strings
$cacheFactory – actory that constructs Cache objects and gives access to them
$window, $interval, $timeout – wrappers around standard global object window and its methods – return Promise
$sce – provides Strict Contextual Escaping services
$location – parses the URL in the browser address bar (window.location) and makes the URL available to application
IPT – Intellectual Products & Technologies Trayan Iliev, http://www.iproduct.org/
AngularJS and TypeScript
SPA Development
Slide 27Sources: AngularJS [ https://docs.angularjs.org ], AngularJS Hub [ http://www.angularjshub.com/ ]
Licensed under the Creative Commons Attribution-ShareAlike 3.0 License
Thanks for Your Attention!
Questions?