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/

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!

    View Slide

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

    [email protected]

    View Slide

  3. Today’s presentation:
    • AngularJS roadmap
    • 1.3.0 breaking changes
    • Performance improvements
    • New features

    View Slide

  4. Let’s not talk about
    changelog

    View Slide

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

    View Slide

  6. Breaking changes

    View Slide

  7. no IE8 support!
    • Won’t break the second you update,
    but… it might
    • Tests are not run on IE8
    • Smaller codebase, less hacks

    View Slide

  8. falsy values
    • Before, some strings were falsy: 

    'f', '0', 'false', 'no', 'n', '[]'
    • Before, empty array was falsy: []
    • Now only JS falsy values are

    View Slide

  9. falsy values
    • Before 1.3 this would display nothing:
    $scope.test = 'no';
    Nope.
    • Have we ever done it?

    View Slide

  10. View Slide

  11. falsy values
    • But we did rely on this:
    $scope.empty = [];
    Nope.
    • Removed in 1.3 as well

    View Slide

  12. replace directives
    • No longer supported
    • Difficult to implement
    • All browsers support custom elements

    View Slide

  13. stateless filters
    • Won't update if injected data changes
    • Huuuge performance gain - caching
    • filter.$stateful = true

    View Slide

  14. Done with the breaking changes!

    View Slide

  15. Performance
    improvements

    View Slide

  16. benchpress
    • Macro benchmarking tool
    • Performance of real applications
    • Measures garbage collector too
    • On GitHub by Angular team

    View Slide

  17. benchpress
    • AngularJS 1.3 compared to 1.2:
    • DOM manipulation:

    4.4x faster, 73% less garbage
    • digest:

    3.5x faster, 87% less garbage

    View Slide

  18. benchpress
    • The main point is:
    • Don't worry about Angular's overhead,
    worry about your code's performance!

    View Slide

  19. but wait… is that all?

    View Slide

  20. production mode
    • There's a lot of debug info everywhere
    • Some tools (eg. Protractor) use them
    but they're not needed in production

    View Slide

  21. production mode
    • You can turn them off:

    $compileProvider

    .debugInfoEnabled(false);

    View Slide

  22. production mode
    • Production mode:
    • DOM manipulation:

    44% faster, 73% less garbage
    • digest:

    28% faster

    View Slide

  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

    View Slide

  24. $rootScope.$applyAsync()
    • You can use this in your own modules
    • It queues up multiple apply calls

    within about 10ms

    View Slide

  25. cool but… boring

    View Slide

  26. New features
    (the real cool stuff)

    View Slide

  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

    View Slide

  28. angular-material-design
    • Accessible
    • Takes care of all ARIA attributes
    • Allows keyboard navigation

    View Slide

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

    View Slide

  30. angular-material-design
    • Turns sidebars into off-screen menus
    automatically
    • Gives really cool feedback for touch

    View Slide

  31. angular-material-design
    • Super easy to use
    • Built with flexbox
    • Integration with ionic is coming…
    • material.angularjs.org

    View Slide

  32. ngAria
    • Talking about accessibility…
    • This new module adds ARIA attributes
    • aria-*
    • checked, disabled, hidden, invalid…

    View Slide

  33. ngAria
    • So this


    • Becomes this

    aria-disabled="true">

    View Slide

  34. ngStrictDi
    • (function ($scope) {…})
    • (['$scope',

    function ($scope) {…}])

    View Slide

  35. ngStrictDi

    • Fails on functions without annotation
    • Incompatible with Batarang

    :(

    View Slide

  36. $scope.$watchGroup()
    • Takes an array and a callback
    • Watch many properties
    • Callback - when any of them changes

    View Slide

  37. time for more exciting stuff!

    View Slide

  38. Forms
    • Forms in Angular are cool, right?
    • But yet some things were missing…

    View Slide

  39. ngModelOptions
    • Usecase
    • Update model value after:
    • User focuses out of the input
    • A given time after the last keystroke

    View Slide

  40. ngModelOptions
    ng-blur=
    "value1Final = value1">
    {{value1Final}}
    • Angular 1.2: not that bad;

    additional variable has to be used

    View Slide

  41. ngModelOptions
    ng-model-options=
    "{ updateOn: 'blur' }">
    {{value1}}
    • Angular 1.3: same length;

    more clear, no additional variables

    View Slide

  42. that was too easy
    let's update after a timeout too

    View Slide

  43. ngModelOptions
    • Template:
    ng-blur="onBlur()">
    {{value2Final}}
    • Function call on blur!

    View Slide

  44. ngModelOptions
    • Controller:
    var timer;
    $scope.onBlur = function () {
    $timeout.cancel(timer);
    $scope.value2Final= $scope.value2;

    };

    View Slide

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

    });

    View Slide

  46. this is too complicated!
    what about Angular 1.3?

    View Slide

  47. ngModelOptions
    • Angular 1.3 is all declarative:
    ng-model-options="{
    updateOn: 'default blur',
    debounce: {
    default: 1000, blur: 0 }

    }">

    View Slide

  48. ngModelOptions
    • Affects $setViewValue() too!
    • Pending changes can be cancelled
    with $rollbackViewValue()

    View Slide

  49. Forms validation
    spoiler: async validators ahead!

    View Slide

  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

    View Slide

  51. form validation
    • Angular 1.2:

    ng-minlength="6"

    ng-maxlength="13"

    ng-pattern="/^\d+$/">

    View Slide

  52. form validation
    • Angular 1.3:

    minlength="6"

    maxlength="13"

    pattern="^\d+$">

    View Slide

  53. form validation
    • There are differences though:
    • 

    Some browsers disallow any text longer
    than 13 characters
    • 

    Only Angular error

    View Slide

  54. ngMessages
    • New directive for displaying validation
    errors
    • Makes HTML code cleaner

    View Slide

  55. ngMessages
    • Angular 1.2:

    ng-if="form.input.$error.required">

    Required

    ng-if="form.input.$error.minlength">

    Minlength

    ng-if="form.input.$error.pattern">

    Pattern

    View Slide

  56. ngMessages
    • Angular 1.3:


    ng-message="required">Required

    ng-message="minlength">Minlength

    ng-message="pattern">Pattern


    View Slide

  57. ngMessages
    • ngMessagesMultiple - display all
    errors at once
    • Impossible in Angular 1.2 without
    hacks

    View Slide

  58. ngMessages
    • ngMessagesInclude - include
    specified template into container
    • In 1.2 possible with use of ngInclude
    and ngIf

    View Slide

  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

    View Slide

  60. custom validators
    • How? custom directive with

    require: 'ngModel'
    • Add a function on object

    ngModel.$validators

    View Slide

  61. custom validators
    require: 'ngModel',
    link: function (_, _, _, ngModel) {
    ngModel.$validators.three =
    function (value) {
    return (value === 3);

    };

    }

    View Slide

  62. custom async validators
    • Long awaited feature!
    • As simple as the validators pipeline
    • How? Add a function returning
    a promise to the pipeline

    View Slide

  63. custom async validators
    require: 'ngModel',
    link: function (_, _, _, ngModel) {
    ngModel.$asyncValidators.async =
    function (value) {
    return promise;
    };
    }

    View Slide

  64. custom async validators
    • $pending property on the controller
    while validation is in progress
    • Async validators are called after all
    other validators pass

    View Slide

  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

    View Slide

  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! :)

    View Slide

  67. improved SVG support
    • ng-repeat inside of SVG now works
    • You can use
    templateNamespace: 'svg'

    to create SVG directives

    View Slide

  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

    View Slide

  69. improved animations
    • Added ng-animate-children
    • Added staggering animations
    • Meaningful transitions (WiP)
    • But that's a topic for another
    presentation…

    View Slide

  70. last thing
    but certainly not least!

    View Slide

  71. …drum roll…

    View Slide

  72. seriously
    it's a pretty fascinating feature!

    View Slide

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

    View Slide

  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

    View Slide

  75. one-time binding
    • It's good for performance - less
    watches
    • Can be used everywhere:

    {{::val}}

    View Slide

  76. one-time binding
    • It should be possible to define own
    syntax for expressions, right?
    • Well… it is!

    View Slide

  77. one-time binding
    • Angular 1.3 introduces

    $$watchDelegate
    • Very simple:

    $provide.decorator('$parse',
    …)

    View Slide

  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);

    View Slide

  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!

    View Slide

  80. one-time binding
    • angular-watch-when

    "bind sometimes"
    • ::myModel::myModel.id

    update myModel.id binding whenever
    myModel is changed

    View Slide

  81. one-time binding
    • angular-watch-require

    reuse $watch from identical
    expression
    • ?model, ^model, ?^model

    View Slide

  82. View Slide

  83. lots of possibilities
    angular is more flexible than ever

    View Slide

  84. the outro

    View Slide

  85. AngularJS 1.3
    • No IE8 support
    • Huge performance improvements
    • Better accessibility (ngAria)
    • Material Design

    View Slide

  86. AngularJS 1.3
    • ngModelOptions
    • Boosted forms and validators (async!)
    • Improved SVG
    • Animations on steroids (WiP)
    • Added one-time binding

    View Slide

  87. one more thing
    “I heard about AngularJS 2.0…”

    View Slide

  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…”

    View Slide

  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…”

    View Slide

  90. AngularJS 1.3
    is awesome

    View Slide

  91. Michał Miszczyszyn
    Code available at:

    mmiszy.github.io/angular-comparison/
    @mmiszy

    [email protected]

    View Slide

  92. AngularJS 1.3

    View Slide

  93. Thank you!

    View Slide