Data binding in AngularJS – From model to view – Types of data binding



Data binding in AngularJS – From model to view – Types of data binding

0 0


angular-data-binding

A presentation about data binding in AngularJ, from model to view.

On Github troch / angular-data-binding

Data binding in AngularJS

From model to view

Thomas Roch, Formedix Ltd Hello, my name is, I work for We develop Applications using AngularJS for the front-end part. We are trying to make them solid, fast and scalable. That leads us to make the most of what Angular can offer, and today I'd like to talk about one of the most important feature in Angular: data binding.

Types of data binding

  • One way (model to view)
  • Two-way data binding

From view to model

  • Javascript DOM Event model: Event, KeyboardEvent, MouseEvent...
  • Easy to bind model to view in Angular directives
app.directive('input', function () {
    return {
        restrict: 'E',
        scope: false,
        link: function (scope, element, attrs) {
            element.bind('input', function (event) {
                scope.$apply(function () {
                    scope.model = element.val();
                });
            });
        }
    };
});

From model to view

  • No events or notifications fired when a value changes in EcmaScript 5
  • Observers are for the future (EcmaScript 6)
Object.observe(myObj, function observer(changes) {
    /* Do something */
    changes.forEach(function (change) {
        console.log(change.name, change.type, change.oldValue);
    });
});

A way to overcome this: dirty checking

Observers can listen to: change of property value, addition or deletion of property value... Notifiers can also be used to emit custom event typesWhat is dirty checking? A digest process needs to run everytime something has changed or could have changed: - goes through the existing bindings - checks if the current model value and the last model value in the binding are still the same - Update if not

Watchers

// Object.observe(myObj, function observer(changes) {
//     changes.forEach(function (change) {
//         console.log(change.name, change.type, change.oldValue);
//     });
// });

$scope.$watch(watchExpression, function listener(newValue, oldValue) {
    // Do something
    console.log(newValue, oldValue);
});
  • watchExpression can be an expression (string)It is evaluated in the context of the $scope using $parse
  • Or it can be a function returning a value
  • Watched values can be primitives, array or objects
  • The listener function is executed if the watchExpression result has changed since the last check.
  • $scope.$watch() returns a deregistration function
- It is evaluated with $parse => convert to a function This is some difference between proper observers and dirty checking: - With observers, every single value change will trigger the observer function - Dirty checking is a discrete process where values are sampled and check at each dirty check. If the value changes more than once between two dirty checks, it is simply missed.

Watching depths

  • $scope.$watch(watchExpr, listener) for watching primitives or object references 
  • $scope.$watchCollection(watchExpr, listener) for watching additions and deletions in Arrays 
  • $scope.$watch(watchExpr, listener, true) for objects and arrays equality (using angular.equals) 
- A normal watch compares variables using === (which is by reference for variables of type "object") - Demo in console - Watching for objects and arrays equality is more resource demanding
Credits: Tero Parviainen, http://teropa.info/blog/2014/01/26/the-three-watch-depths-of-angularjs.html

Which directives add watchers?

  • $watch: {{ }}, ngBind, ngBindTemplate, ngModel ngShow, ngHide, ngIf, ngSwitch ngSelected, ngChecked, ngDisabled, ngRequired, etc...
  • $watchCollection: ngRepeat
  • $watch with object equality: ngClass, ngStyle

The digest process

  • $scope.$digest() digests a scope and its children
  • Cannot run concurently
  • Evaluates all watch expressions and functions
  • If at least one listener is fired, it will re-evaluate all watch expressions
  • The digest process stops when no more listeners have been fired
  • Stops at 10 times and throws an infinite digest loop
- A watch expression can be fired multiple times per digest - A digest is about propagating changes, you can compoare it to a brick in a pond - That error you probably saw more than once

What triggers a digest?

  • $digest usually not called directly
    // Apply changes: execute function and call $digest
    $scope.$apply(function () {
        $scope.myModel = 'Hello';
    });
    
  • Services: $http, $timeout, $interval
  • Directives: ngClick, ngChange, ngFocus, ngPaste, etc...
  • When inside a watch listener, no need to trigger a digest!

Issue #1: performance

To measure performance improvements we have created a crude benchmark of a table of 20 columns (a repeater) and 100 rows (another repeater) and placed a binding in each cell for a total of 2000 cells. We then proceeded to change a small portion of the model to see the performance characteristics of the update. The result is summarized below.
  • Dirty checking: 40ms
  • Observers: 1-2ms

Issue #2: Sustainability

  • The more the watchers, the more processing required
  • The more processing, the more time it takes

Solution

  • Limiting the number of watchers!

Scopes and data

  • A variable can be available when the scope is instanciated: use of resolve, or synchronous initialisation
  • A variable can be available after the scope is instanciated: fetching data asynchronously
  • A variable can be changing multiple times during a scope's life
- We have talked about watchers - We have talked about the digest process - Let's now talk about the context where all of this happens: scopes

The three cases of watching data

  • A watcher is watching...
  • data available at scope creation which will never change
  • data available after scope creation which will never change thereafter
  • data available immediately or not, which will change once or more
- Angular directives with watchers make no assumption about your data: they work for the worst case: your data can change at any time

Demo

Questions