$30 off During Our Annual Pro Sale. View Details »

AngularJS 1.3.0 - let's talk about changes! ngPoznan

AngularJS 1.3.0 - let's talk about changes! ngPoznan

This presentation covers:
* AngularJS roadmap
* 1.3.0 breaking changes
* Performance improvements
* New features

This talk was given during ngPoznan meeting in Poznań, Poland, on November the 20th, 2014. *Video will be uploaded soon*

Some code examples: http://mmiszy.github.io/angular-comparison/

Michał Miszczyszyn

November 20, 2014
Tweet

More Decks by Michał Miszczyszyn

Other Decks in Programming

Transcript

  1. AngularJS 1.3 let’s talk about changes!

  2. Michał Miszczyszyn JavaScript developer at The Comet Cult (mostly AngularJS)

    @mmiszy
 michal@miszczyszyn.com
  3. Today’s presentation: • AngularJS roadmap • 1.3.0 breaking changes •

    Performance improvements • New features
  4. Let’s not talk about changelog

  5. Let’s talk about changes code before and after Angular 1.3

  6. Breaking changes

  7. no IE8 support! • Won’t break the second you update,

    but… it might • Tests are not run on IE8 • Smaller codebase, less hacks
  8. falsy values • Before, some strings were falsy: 
 'f',

    '0', 'false', 'no', 'n', '[]' • Before, empty array was falsy: [] • Now only JS falsy values are
  9. falsy values • Before 1.3 this would display nothing: $scope.test

    = 'no'; <div ng-if="test">Nope.</div> • Have we ever done it?
  10. None
  11. falsy values • But we did rely on this: $scope.empty

    = []; <div ng-if="empty">Nope.</div> • Removed in 1.3 as well
  12. replace directives • No longer supported • Difficult to implement

    • All browsers support custom elements
  13. stateless filters • Won't update if injected data changes •

    Huuuge performance gain - caching • filter.$stateful = true
  14. Done with the breaking changes!

  15. Performance improvements

  16. benchpress • Macro benchmarking tool • Performance of real applications

    • Measures garbage collector too • On GitHub by Angular team
  17. benchpress • AngularJS 1.3 compared to 1.2: • DOM manipulation:


    4.4x faster, 73% less garbage • digest:
 3.5x faster, 87% less garbage
  18. benchpress • The main point is: • Don't worry about

    Angular's overhead, worry about your code's performance!
  19. but wait… is that all?

  20. production mode • There's a lot of debug info everywhere

    • Some tools (eg. Protractor) use them but they're not needed in production
  21. production mode • You can turn them off:
 $compileProvider
 .debugInfoEnabled(false);

  22. production mode • Production mode: • DOM manipulation:
 44% faster,

    73% less garbage • digest:
 28% faster
  23. $httpProvider.useApplyAsync(true); • 1.2: every resolved request = digest • You

    can now configure it • If many responses come in a short time, only one digest will be called
  24. $rootScope.$applyAsync() • You can use this in your own modules

    • It queues up multiple apply calls
 within about 10ms
  25. cool but… boring

  26. New features (the real cool stuff)

  27. Material Design • It's a styleguide from Google • Angular-material-design

    is a set of lightweight UI elements based on it • Requires angular 1.3
  28. angular-material-design • Accessible • Takes care of all ARIA attributes

    • Allows keyboard navigation
  29. angular-material-design • Responsive • No, really. • It's very responsive.

  30. angular-material-design • Turns sidebars into off-screen menus automatically • Gives

    really cool feedback for touch
  31. angular-material-design • Super easy to use • Built with flexbox

    • Integration with ionic is coming… • material.angularjs.org
  32. ngAria • Talking about accessibility… • This new module adds

    ARIA attributes • aria-* • checked, disabled, hidden, invalid…
  33. ngAria • So this
 <x ng-disabled="disabled"> • Becomes this
 <x

    ng-disabled="disabled" aria-disabled="true">
  34. ngStrictDi • (function ($scope) {…}) • (['$scope',
 function ($scope) {…}])

  35. ngStrictDi • <x ng-app="…" ng-strict-di> • Fails on functions without

    annotation • Incompatible with Batarang
 :(
  36. $scope.$watchGroup() • Takes an array and a callback • Watch

    many properties • Callback - when any of them changes
  37. time for more exciting stuff!

  38. Forms • Forms in Angular are cool, right? • But

    yet some things were missing…
  39. ngModelOptions • Usecase • Update model value after: • User

    focuses out of the input • A given time after the last keystroke
  40. ngModelOptions <input ng-model="value1" ng-blur= "value1Final = value1"> {{value1Final}} • Angular

    1.2: not that bad;
 additional variable has to be used
  41. ngModelOptions <input ng-model="value1" ng-model-options= "{ updateOn: 'blur' }"> {{value1}} •

    Angular 1.3: same length;
 more clear, no additional variables
  42. that was too easy let's update after a timeout too

  43. ngModelOptions • Template: <input ng-model="value2" ng-blur="onBlur()"> {{value2Final}} • Function call

    on blur!
  44. ngModelOptions • Controller: var timer; $scope.onBlur = function () {

    $timeout.cancel(timer); $scope.value2Final= $scope.value2;
 };
  45. ngModelOptions • Controller: $scope.$watch('value2', function () { $timeout.cancel(timer); timer =

    $timeout(function () { $scope.value2Final = $scope.value2; }, 1000);
 });
  46. this is too complicated! what about Angular 1.3?

  47. ngModelOptions • Angular 1.3 is all declarative: <input ng-model="value2" ng-model-options="{

    updateOn: 'default blur', debounce: { default: 1000, blur: 0 }
 }">
  48. ngModelOptions • Affects $setViewValue() too! • Pending changes can be

    cancelled with $rollbackViewValue()
  49. Forms validation spoiler: async validators ahead!

  50. form validation • All HTML5 validation attributes are now properly

    bound to ngModel • No need for ng-pattern, ng-minlength, ng-maxlength, although they are still available
  51. form validation • Angular 1.2:
 <input ng-model="test3"
 ng-minlength="6"
 ng-maxlength="13"
 ng-pattern="/^\d+$/">

  52. form validation • Angular 1.3:
 <input ng-model="test3" minlength="6"
 maxlength="13"
 pattern="^\d+$">

  53. form validation • There are differences though: • <input maxlength="13">


    Some browsers disallow any text longer than 13 characters • <input ng-maxlength="13">
 Only Angular error
  54. ngMessages • New directive for displaying validation errors • Makes

    HTML code cleaner
  55. ngMessages • Angular 1.2:
 <div
 ng-if="form.input.$error.required">
 Required</div>
 <div
 ng-if="form.input.$error.minlength">
 Minlength</div>


    <div
 ng-if="form.input.$error.pattern">
 Pattern</div>
  56. ngMessages • Angular 1.3:
 <div ng-messages="form.input.$error">
 <div
 ng-message="required">Required</div>
 <div
 ng-message="minlength">Minlength</div>


    <div
 ng-message="pattern">Pattern</div>
 </div>
  57. ngMessages • ngMessagesMultiple - display all errors at once •

    Impossible in Angular 1.2 without hacks
  58. ngMessages • ngMessagesInclude - include specified template into container •

    In 1.2 possible with use of ngInclude and ngIf
  59. custom validators • In Angular 1.2 - $parsers and $formatters

    pipelines • Had to call $setValidity manually • In Angular 1.3 there's a separate pipeline for that
  60. custom validators • How? custom directive with
 require: 'ngModel' •

    Add a function on object
 ngModel.$validators
  61. custom validators require: 'ngModel', link: function (_, _, _, ngModel)

    { ngModel.$validators.three = function (value) { return (value === 3);
 };
 }
  62. custom async validators • Long awaited feature! • As simple

    as the validators pipeline • How? Add a function returning a promise to the pipeline
  63. custom async validators require: 'ngModel', link: function (_, _, _,

    ngModel) { ngModel.$asyncValidators.async = function (value) { return promise; }; }
  64. custom async validators • $pending property on the controller while

    validation is in progress • Async validators are called after all other validators pass
  65. $touched • One more small thing • $touched property added

    next to $dirty, $pristine etc… • It's set to true after user focuses out of an input
  66. $touched • We had to simulate that in Angular 1.1

    and 1.2 way too many times • This tiny little property makes me personally very happy! :)
  67. improved SVG support • ng-repeat inside of SVG now works

    • You can use templateNamespace: 'svg'
 to create SVG directives
  68. improved ng-src support • "/ngPoznan/{{id}}/a.jpg" • Invalid request if id

    is empty • Won't happen anymore. • Fixed in ng-src, ng-href, ng-srcset
  69. improved animations • Added ng-animate-children • Added staggering animations •

    Meaningful transitions (WiP) • But that's a topic for another presentation…
  70. last thing but certainly not least!

  71. …drum roll…

  72. seriously it's a pretty fascinating feature!

  73. one-time bindings you probably all heard about that already

  74. one-time binding • New syntax introduced • Expressions that start

    with :: are one‑time expressions • One-time expressions will not be updated after they are non-undefined
  75. one-time binding • It's good for performance - less watches

    • Can be used everywhere:
 {{::val}} <x dir="::val">
  76. one-time binding • It should be possible to define own

    syntax for expressions, right? • Well… it is!
  77. one-time binding • Angular 1.3 introduces
 $$watchDelegate • Very simple:


    $provide.decorator('$parse', …)
  78. (function() {
 var wrap,
 __slice = [].slice;
 
 wrap =

    function(listener, toDo, invokeAlways, isDefined) {
 return _.wrap(toDo, function() {
 var args, originalFn, value, valueIsDefined;
 originalFn = arguments[0], value = arguments[1], args = 3 <= arguments.length ? __slice.call(arguments, 2) : [];
 valueIsDefined = isDefined(value);
 if (!invokeAlways && !valueIsDefined) {
 return;
 }
 originalFn.call.apply(originalFn, [this, value].concat(__slice.call(args)));
 if (valueIsDefined) {
 return listener.cleanup();
 }
 });
 };
 
 angular.module('ngWatchWhen', []).constant('ngWatchWhenRegEx', /^\:\:([^\:]+)(\:\:[^\:]+)$/).value('ngWatchWhenCloneExpression', function(getter) {
 var clone;
 clone = function() {
 return getter.apply(this, arguments);
 };
 return _.merge(clone, getter);
 }).config(function($provide) {
 return $provide.decorator('$parse', function($delegate, ngWatchWhenRegEx, ngWatchWhenDelegateFactory, ngWatchWhenCloneExpression) {
 return _.wrap($delegate, function($parse, exp, interceptor) {
 var args, match, onceExp, onceStr, whenExp, whenStr;
 if (angular.isString(exp) && (match = exp.match(ngWatchWhenRegEx))) {
 exp = match[0], whenStr = match[1], onceStr = match[2];
 whenExp = $parse.apply(this, [whenStr]);
 onceExp = ngWatchWhenCloneExpression($parse.apply(this, [onceStr, interceptor]));
 onceExp.$$watchDelegate = ngWatchWhenDelegateFactory(whenExp, onceExp);
 return onceExp;
 } else {
 args = [exp];
 if (interceptor != null) {
 args.push(interceptor);
 }
 return $parse.apply(this, args);
 }
 });
 });
 }).value('ngWatchWhenDelegateFactory', function(whenExp, onceExp) {
 return _.wrap(onceExp.$$watchDelegate, function(originalWatchDelegate, scope, listener, objectEquality, parsedExpression) {
 var onceWatch, registerOnceWatch, whenWatch;
 onceWatch = null;
 registerOnceWatch = function() {
 onceWatch = {};
 onceWatch.deregister = originalWatchDelegate.call(this, scope, listener, objectEquality, parsedExpression);
 return onceWatch.watcher = _.first(scope.$$watchers);
 };
 registerOnceWatch();
 whenWatch = scope.$watch(whenExp, function() {
 if (!_.contains(scope.$$watchers, onceWatch.watcher)) {
 return registerOnceWatch();
 }
 });
 return function() {
 whenWatch();
 if (_.contains(scope.$$watchers, onceWatch.watcher)) {
 return onceWatch.deregister();
 }
 };
 });
 });
 
 }).call(this);
  79. one-time binding • But seriously, it's quite complicated. • This

    simple function was 69 LoC • There are already two (or more?) modules on GitHub doing that!
  80. one-time binding • angular-watch-when
 "bind sometimes" • ::myModel::myModel.id
 update myModel.id

    binding whenever myModel is changed
  81. one-time binding • angular-watch-require
 reuse $watch from identical expression •

    ?model, ^model, ?^model
  82. None
  83. lots of possibilities angular is more flexible than ever

  84. the outro

  85. AngularJS 1.3 • No IE8 support • Huge performance improvements

    • Better accessibility (ngAria) • Material Design
  86. AngularJS 1.3 • ngModelOptions • Boosted forms and validators (async!)

    • Improved SVG • Animations on steroids (WiP) • Added one-time binding
  87. one more thing “I heard about AngularJS 2.0…”

  88. • Don't worry! • Angular 1.3 will be supported for

    two more years after the release of 2.0! “I heard about AngularJS 2.0…”
  89. • 1.3 branch has the new maintainer already: Pete Bacon

    Darwin took over • Angular creators promised to release a migration guide from 1.x to 2.0 “I heard about AngularJS 2.0…”
  90. AngularJS 1.3 is awesome

  91. Michał Miszczyszyn Code available at:
 mmiszy.github.io/angular-comparison/ @mmiszy
 michal@miszczyszyn.com

  92. AngularJS 1.3

  93. Thank you!