Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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/

8f7e1a0e97a69d5f7be4885c867b74ba?s=128

Michał Miszczyszyn

November 20, 2014
Tweet

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!