angular 1.x reloaded: improve your app now! and get ready for 2.0
TRANSCRIPT
#vdt15 @carlobonamico
Angular 1.x reloaded: improve your app now! and get ready for 2.0
Carlo BonamicoNIS s.r.l. / JUG Genova
#vdt15 @carlobonamico
Waiting for Angular 2.0
● As development proceeds and details emerge, growing excitement for what the new release will bring:– full support for Web Components
● which often require custom integration directives in AngularJS 1.x
– full support for ES6 ● particularly module system
– better performance– better tooling support
● smart autocompletion, development-time validation
– first-class mobile support● By the way, go watch Misko and Rado Kirov ng-conf Day 2 keynote
– videos for all other talks also available● https://www.youtube.com/watch?v=-dMBcqwvYA0&index=21&list=PLOETEcp3DkCoNnlhE-7fov
YvqwVPrRiY7
https://angular.io
#vdt15 @carlobonamico
Yes, but... The questions we are all asking
● Do I start learning/using 2.0 now? or when?
● Will I be forced to use ES6 or Typescript?
● Will I have to rewrite some/most/all of my 1.x code?
● By the way, what the *** is this new syntax?[disabled]=”comp.disabled” (click)=”comp.enable()”
● How about a migration path?
● Do I have to wait until 2016 to get 2.0 advantages in my app?
#vdt15 @carlobonamico
Some (preliminary) answers
● Do I start learning/using 2.0 now? or when?learning, now! using... not until beta/RC
● Will I be forced to use ES6 or Typescript?NO! although you will get benefits it you do
● Will I have to rewrite some/most/all of my 1.x code?definitely NOT ALL – more about this later
● By the way, what the *** is this new syntax?[disabled]=”comp.disabled” (click)=”comp.enable()”
better semantics! Web Components! ● How about a migration path?● Do I have to wait until 2016 to get 2.0 advantages?
NO! see next slides...● So... – and start getting ready!
Disclaimer:
1) Info uptodate in April 2015.
2) May change: additions possiblemajor API changes
look unlikely
3) I am not in the Angular team.All mistakes &
misinterpretations are mine :)
#vdt15 @carlobonamico
You can improve your 1.x app now, AND make adoption of 2.0 easier
● Use new (and 2.x friendly) constructs– controllerAs– new bindToController directive syntax
● Follow 2.0 Design Patterns now– components all the way down
● Use “dual mode” libraries supporting both versions– angular new router– i18n– more to follow...
● Take advantage of ES6 / TypeScript
This talk isshares our experience
in adopting these approaches in real-world projects
#vdt15 @carlobonamico
What's new in 1.3/1.4?
● Apparently, small things– but they do enable big changes in the way we develop Angular apps
● Besides, both releases achieve a significant performance increase– 1.3 improves DOM manipulation
● 4.3 times faster with 73% less garbage
– 1.3 optimizes change detection● 3.5 times faster digest with 87% less garbage
– 1.4 brings even more tuning– you do not need to change your code :-)
● So move to 1.3 NOW!– and to 1.4 in a few weeks (it's RC0 as of today)
#vdt15 @carlobonamico
Angular 1.x reloaded – 1: controllerAs
● Avoid injecting $scope in the controller● Put the controller instance IN the scope● HTML
<div ngcontroller=”ComposerController as msgComposer”>{{msgComposer.message.subject}}<button ngclick=”msgComposer.send()”>
</div>
● JSfunction ComposerController(MailService) //no $scope!{
this.message = { subject : “Hello World” };
this.send = function () { MailService.send(this.message); };}angular.module(“mailApp”).controller(“ComposerCtrl”, ComposerController)
Examples for a fictionalgmail-like webmail
#vdt15 @carlobonamico
Advantages
● More readable code– particularly in complex views
● Even easier to test● Use the $scope only if need access to its APIs
– e.g. $watch()● http://toddmotto.com/digging-into-angulars-controller-as-syntax/
– less dependencies on the framework● and consequently on the framework version
● Why is this important? – no explicit scope in 2.0 → becomes integrated with Dep. Injection– @Component syntax similar to controllerAs
#vdt15 @carlobonamico
Angular 1.x reloaded - 2: Use ES6 / TypeScript
● ES6: the future of the web– both class support and better functional programming constructs
● Standard module system– including good support for both sync and async loading
● TypeScript adds types (both explicit and inferred) – more development-time checks
● Good news is that they are optional! – so that use them only where they do provide benefits– incrementally add them
● small overhead in workflow, better tooling
#vdt15 @carlobonamico
Example of ControllerAs: ES5
● In HTML<div ngcontroller=”ComposerController as msgComposer”>
{{msgComposer.message.subject}}<button ngclick=”msgComposer.send()”>
</div>
● JSfunction ComposerController(MailService) //no $scope!{
this.message = { subject : “Hello World” };
this.send = function () { MailService.send(this.message); };}angular.module(“mailApp”).controller(“ComposerCtrl”, ComposerController)
#vdt15 @carlobonamico
Example of ControllerAs: ES6
● In HTML<div ngcontroller=”ComposerController as msgComposer”>
{{msgComposer.message.subject}}<button ngclick=”msgComposer.send()”>
</div>
● ES6class ComposerController {
constructor(MailService){this.mailService = MailService;this.message = { subject : “Hello World” };
}
send() { this.mailService.send(this.message); };}angular.module(“mailApp”).controller(“ComposerCtrl”, ComposerController)
#vdt15 @carlobonamico
Example of ControllerAs: TypeScript
● In HTML<div ngcontroller=”ComposerController as msgComposer”>
{{msgComposer.message.subject}}<button ngclick=”msgComposer.send()”>
</div>
● TSclass ComposerController { message:MailMessage;
constructor(private mailService:MailService){ //autoassign to property
this.message = { subject : “Hello World” };}
send() { this.mailService.send(this.message); };}angular.module(“mailApp”).controller(“ComposerCtrl”, ComposerController)
#vdt15 @carlobonamico
Example of Angular 2.0 Component
● In composer.html<div>
{{message.subject}}<button (click)=”send()”>
</div>
● TS@Component({ selector: "messagecomposer"}, inject: ...)@Template({url: "composer.html"})class ComposerController { message: MailMessage;
constructor(private mailService:MailService){this.message = { subject : “Hello World” };
}
send() { this.mailService.send(this.message); };}angular.module(“mailApp”).controller(“ComposerCtrl”, ComposerController)
● http://blog.ionic.io/angular-2-series-components/
@Metadata
Can also be written in (slightly more verbose)
ES5 syntax
#vdt15 @carlobonamico
What about AtScript? ES6 – TypeScript roadmap
● At ng-conf 2015, Microsoft & Angular Team announced that AtScript features (particularly annotations and runtime types) are being merged into TypeScript 1.5
● http://blogs.msdn.com/b/typescript/archive/2015/03/05/angular-2-0-built-on-typescript.aspx
Now - at TypeScript 2.0 release
– at runtime, both languages share the current ES5 object model
TSES6
ES5 TSES6 ES5
#vdt15 @carlobonamico
But tell me more about the migration path...
● There will be one! “1.x will evolve until migration is trivial” – Main theme of Angular 1.5: paving the way to the upgrade
● In the meantime: good old Software Engineering principles still apply!– Separation of Concerns (particularly UI - logic)– Clarity of intent and code readability– Favor composition over inheritance– Modularity – Test, test, test!
● unit (Jasmine) vs e2e (protractor – cucumber) - http://martinfowler.com/bliki/TestPyramid.html
● As always, apps following these principles will adapt more easily to both requirements changes and framework changes– and it will be easier to evolve them incrementally – and validating each step → see Continuous Delivery
#vdt15 @carlobonamico
Composition and Separation of Concerns: from this
Image courtesy of Todd Motto's very interesting tutorial
https://www.thinkful.com/learn/angularjs-tutorial-build-a-gmail-clone
WebMailController
#vdt15 @carlobonamico
Composition and Separation of Concerns: to this
WebMailController
MessageListController
FolderListController MsgAction
Controller
Controllers
should be as small as possible
should be “slim”, manage link to UI,
and delegate to Services
MessageListServiceMailSenderService
● Angular 2.0 will have much better and more powerful DI, ● but actual Service code will not change much
#vdt15 @carlobonamico
Angular 1.x reloaded – 3: DataBinding
● 1.3 adds support for one-time binding with {{ ::obj.field }}– better performance with immutable data– reduces the need for custom directives
<li ngrepeat=”item in hugeListOfNonChangingItems”>{{ ::item.name }}</li>
● Limitations of 1.x binding: what is name in<tag search=”name”>
– a string constant? and expression? do I need curly braces? – is it an attribute or a method?
● Implicit semantics! it depends on the DDO...– not self-describing
1.x Binding Syntax Binding Type
{{obj.field}} model-to-view
{{::obj.field }} model-to-view, one-time
ngmodel=”obj.field” bidirectional
ngclick=”add()” event method
#vdt15 @carlobonamico
Angular 2.0: New binding syntax? no, new binding semantics!
● Angular 1.x binds to HTML attributes– parsed and processed by the $compile service
● Angular 2.0 binds to DOM properties – HTML seen as serialized DOM[text]=”composer.message.subject” means bind → text property value to variable (click)=”composer.send()” means attach listener to → click event
● Advantages– no more ad-hoc directives
use standard dom properties – works with any Web Component
<tab [title]=”message.subject” (click)=”collapse()” >
– unambiguous and self-describing● expression format specified by the caller, not by the component
– more readable, clearer flow of data within the page● once your eyes get accustomed to the parentheses :-)
nghide=”” → [hidden]=”” ngclick=”” → (click)=””
or canonical syntax
nghide=”” →bindhidden=””ngclick=”” →onclick=””
#vdt15 @carlobonamico
Is this all?
● Data binding syntax is just the tip of the iceberg...
● So what's the single most important thing that you can do now to get ready for 2.0?
{{ iceberg.tip }}
Modules DI
Routing
components
#vdt15 @carlobonamico
Move to component-based development now
● From this
ngcontroller=”WebMailController”
ngcontroller=”MessageListController”MessageList.html
Ngcontroller=
”FolderListController” MsgAction
Controller
#vdt15 @carlobonamico
Move to component-based development now
● To this
ngcontroller=”WebMailController”
<messagelist><folderlist>
<messageactions>
<messagedetails>
<messagesearchbox>
#vdt15 @carlobonamico
With component-based directives
● Angular 2.0 will be both component-based and component-friendly– the default construct will be a component – controllers and directives become components with different roles
● Three different rolesRole Angular 1.x Angular 2.0
Element restrict: “E”, scope: { … }can use transclusion
@Componentcan use shadow-dom
Decorator restrict: “A”, link: function (element)
@Decoratorconstructor(element)
Template/Viewport e.g. ng-repeatng-if
e.g. *for *if
#vdt15 @carlobonamico
Angular 1.x reloaded – 4: better component support with bindToController
used in HTML
<messagecomposer message=”ctrl.newMessage”
autosave=”true” ondraftsave=”mainCtrl.save()”>
</messagecomposer>
Template
Subject: <input ngmodel=”compCtrl.message.subject”>
Content: <input ngmodel=”compCtrl.message.content”>
<button ngclick=”compCtrl.save()”>Save</button>
<button ngclick=”compCtrl.send()”> Send</button>
app.directive('messageComposer', function () { return { scope: {}, bindToController: { message: '=', autosave: '@', onDraftSave: '&' onSend: '&' } templateUrl: … , controller: 'ComposerCtrl as compCtrl', };});
class ComposerCtrl { message = {...}; constructor(){ this.autosave = true; } save (){ //do stuff this.onDraftSave(this.message); }}
#vdt15 @carlobonamico
But if everything is a component,
●How do they share state?
●Do they?
●How do they interact?
#vdt15 @carlobonamico
Example: message list with expanded current message and navigation
● Within FolderController of <messagefoldercontent>
<messagelist>
<messagedetails>
<< >><navigationcontrols>
<messagedetails>
#vdt15 @carlobonamico
Connecting components: defining an API
● A component has – inputs: bindable properties
● and component methods in 2.0
– outputs: event methods● A bit like a function with input parameters and output callbacks
● In our exampleComponent Inputs Outputs
<messagelist> list
<messagedetails> message, collapse() reply(), forward()
<navigationcontrols> next(), prev()
#vdt15 @carlobonamico
Connecting components: HTML
● HTML
<messagefoldercontent name=”inbox”>
</messagefoldercontent>
● templates/message-folder-content.html
<messagelist list=”folder.messages”>
<displaymessage message = “folder.currentMessage”>
</messagelist>
<navigationcontrols next=”folder.next()” prev=”...” >
● In <messagefoldercontent> controllerclass FolderController{
constructor(MessageLoaderService){
this.messages = MessageLoaderService.loadMessagesByFolder(this.name);
this.counter = 0;
this.currentMessage = this.messages[counter];
}
next(){
this.counter = ++;
this.currentMessage = this.messages[counter];
}
reply(message) { … }
}
#vdt15 @carlobonamico
Connecting components: binding and data flow
● Within <messagefoldercontent name=”inbox”>
<messagelist list=”folder.messages”>
<< >><navigationcontrols prev=””>
<messagedetails message=”folder.current”>
Direct Acyclic Graph!
i.e. a Good Thing
#vdt15 @carlobonamico
Connecting components: state and data flow
● In 1.x state is often hidden – many components can change shared state in any direction
● thanks to two-way DataBinding
● Two way DataBinding is extremely powerful– we got hooked into Angular because of this
● Turns out, however, that – two-way binding works best at the local level – too implicit in complex / composite views
#vdt15 @carlobonamico
What about two-way DataBinding?
● So a bit like you refactor global variables into encapsulated state with explicit parameter passing, in 2.x, component state can be shared through data binding only with child components
<messagedetails message=”currentMessage”>– binding lets a child component read its parent state, not write to it– child components need explicit event methods to communicate state change to
surrounding components● e.g. next()
● Page structure and data flow becomes easier to follow– particularly in complex apps
● But... forms likely to get ad-hoc support replicating two-way behaviourwith different implementation
– http://victorsavkin.com/post/110170125256/change-detection-in-angular-2
#vdt15 @carlobonamico
Advantages
● Dependencies become more explicit● State changes can be propagated even more efficiently
– model → view from top to bottom– view → model explicitly, and bottom-up
● This means fast fast FAST! databinding– single-pass change detection
● http://victorsavkin.com/post/114168430846/two-phases-of-angular-2-applications
– even more optimization if you give hints about when state changes● immutable vs observable vs dirty-checked objects● http://victorsavkin.com/post/110170125256/change-detection-in-angular-2
#vdt15 @carlobonamico
What else can I do?
#vdt15 @carlobonamico
Use Angular 1.4 new routerhttps://angular.github.io/router
● Component-based router● Supports
– child and nested router– lazy loading – multiple views
● JS Route configuration $router.config([ { path: '/inbox', // Map components to viewports components: { //folder component in main viewport 'main': 'folder', 'sidebar': 'folderlist' } ]);
<div ngviewport="sidebar">
<div ngviewport="main">
#vdt15 @carlobonamico
The new router – lifecycle support
● Promise-enabled callbacks before and after navigation – notify navigation requests – can accept / reject them
● Simplifies many common use cases: – asking confirmation before leaving view with unsaved data in forms– redirecting to login page if not auhtenticated– block navigation to routes not authorized for the user profile
● It will support mixed 1.x / 2.0 scenarios: – 1.x views in 2.0 route definition and vice-versa– key tool for incremental migration of large apps
● https://www.youtube.com/watch?v=vecg70fPDFw
#vdt15 @carlobonamico
Next Generation modules
● Learn about System.js– backward- and forward- compatible
implementation of ES6 module system– available now!– https://github.com/systemjs/systemjs
● Example for Angular 1.x
– http://martinmicunda.com/2015/02/09/how-to-start-writing-apps-with-es6-angular-1x-and-jspm/
● Example for Angular 2.0– https://angular.io/docs/js/latest/quickstart.html
Webmail App
Logging Auth UI Widgets
Message List Reader
Message Composer Contacts
#vdt15 @carlobonamico
Keep up-to-date
● Watch out for 1.5 release– main theme adding support for easier migration – keep an eye on http://angularjs.blogspot.it/ for roadmap updates
● Learn about Component-based approaches with 1.x– https://www.airpair.com/javascript/posts/creating-container-components
-part-1-shadow-dom (also part 2 & part 3)
● Start reading about 2.0– http://blog.ionic.io/angular-2-series-introduction/ – http://blog.thoughtram.io/ – https://github.com/timjacobi/angular2-education
● Follow 2.x development– http://victorsavkin.com/
#vdt15 @carlobonamico
More references
● StyleGuide– https://github.com/johnpapa/angularstyleguide
● SOLID Principles– http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod
● Javascript by Yakov Fain – http://enterprisewebbook.com/appendix_a_advancedjs.html
– https://www.youtube.com/watch?v=X1J0oMayvC0
● Axel Rauschmayer Speaking Javascript– http://speakingjs.com/
● TypeScript– http://www.typescriptlang.org/
● ES6– http://www.2ality.com/2014/08/es6today.html
#vdt15 @carlobonamico
Thank you!
● If you are interested,– read my other presentations
● http://www.slideshare.net/carlo.bonamico/presentations
– ask us about Angular training / consulting● http://www.nispro.it
● Follow us on Twitter– @carlobonamico @nis_srl
● updates on AngularJS!● and some Docker, Ansible, Continuous Delivery
● Contact us– [email protected] / [email protected]
Special thanks to my teammates Sonia Pini, Danilo Caruso and Roberta Ficco for all
suggestions, ideas & feedback on “reloading” Angular
and to Pascal Precht for the timely & great feedback