Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the Angular equivalent to an AngularJS $watch?

People also ask

What is watch function AngularJS?

What is the angular JS watch function? The angular JS $watch function is used to watch the scope object. The $watch keep an eye on the variable and as the value of the variable changes the angular JS $what runs a function. This function takes two arguments one is the new value and another parameter is the old value.

What is :: In AngularJS?

:: is used for one-time binding. The expression will stop recalculating once they are stable, i.e. after the first digest.

What is component in Angular stack overflow?

A component is one of the basic building blocks of an Angular app. An app can have more than one component. In a normal app, a component contains an HTML view page class file, a class file that controls the behaviour of the HTML page and the CSS/scss file to style your HTML view.

What is in Angular HTML?

An Angular HTML template renders a view, or user interface, in the browser, just like regular HTML, but with a lot more functionality. When you generate an Angular application with the Angular CLI, the app. component. html file is the default template containing placeholder HTML.


In Angular 2, change detection is automatic... $scope.$watch() and $scope.$digest() R.I.P.

Unfortunately, the Change Detection section of the dev guide is not written yet (there is a placeholder near the bottom of the Architecture Overview page, in section "The Other Stuff").

Here's my understanding of how change detection works:

  • Zone.js "monkey patches the world" -- it intercepts all of the asynchronous APIs in the browser (when Angular runs). This is why we can use setTimeout() inside our components rather than something like $timeout... because setTimeout() is monkey patched.
  • Angular builds and maintains a tree of "change detectors". There is one such change detector (class) per component/directive. (You can get access to this object by injecting ChangeDetectorRef.) These change detectors are created when Angular creates components. They keep track of the state of all of your bindings, for dirty checking. These are, in a sense, similar to the automatic $watches() that Angular 1 would set up for {{}} template bindings.
    Unlike Angular 1, the change detection graph is a directed tree and cannot have cycles (this makes Angular 2 much more performant, as we'll see below).
  • When an event fires (inside the Angular zone), the code we wrote (the event handler callback) runs. It can update whatever data it wants to -- the shared application model/state and/or the component's view state.
  • After that, because of the hooks Zone.js added, it then runs Angular's change detection algorithm. By default (i.e., if you are not using the onPush change detection strategy on any of your components), every component in the tree is examined once (TTL=1)... from the top, in depth-first order. (Well, if you're in dev mode, change detection runs twice (TTL=2). See ApplicationRef.tick() for more about this.) It performs dirty checking on all of your bindings, using those change detector objects.
    • Lifecycle hooks are called as part of change detection.
      If the component data you want to watch is a primitive input property (String, boolean, number), you can implement ngOnChanges() to be notified of changes.
      If the input property is a reference type (object, array, etc.), but the reference didn't change (e.g., you added an item to an existing array), you'll need to implement ngDoCheck() (see this SO answer for more on this).
      You should only change the component's properties and/or properties of descendant components (because of the single tree walk implementation -- i.e., unidirectional data flow). Here's a plunker that violates that. Stateful pipes can also trip you up here.
  • For any binding changes that are found, the Components are updated, and then the DOM is updated. Change detection is now finished.
  • The browser notices the DOM changes and updates the screen.

Other references to learn more:

  • Angular’s $digest is reborn in the newer version of Angular - explains how the ideas from AngularJS are mapped to Angular
  • Everything you need to know about change detection in Angular - explains in great detail how change detection works under the hood
  • Change Detection Explained - Thoughtram blog Feb 22, 2016 - probably the best reference out there
  • Savkin's Change Detection Reinvented video - definitely watch this one
  • How does Angular 2 Change Detection Really Work?- jhade's blog Feb 24, 2016
  • Brian's video and Miško's video about Zone.js. Brian's is about Zone.js. Miško's is about how Angular 2 uses Zone.js to implement change detection. He also talks about change detection in general, and a little bit about onPush.
  • Victor Savkins blog posts: Change Detection in Angular 2, Two phases of Angular 2 applications, Angular, Immutability and Encapsulation. He covers a lot of ground quickly, but he can be terse at times, and you're left scratching your head, wondering about the missing pieces.
  • Ultra Fast Change Detection (Google doc) - very technical, very terse, but it describes/sketches the ChangeDetection classes that get built as part of the tree

This behaviour is now part of the component lifecycle.

A component can implement the ngOnChanges method in the OnChanges interface to get access to input changes.

Example:

import {Component, Input, OnChanges} from 'angular2/core';


@Component({
  selector: 'hero-comp',
  templateUrl: 'app/components/hero-comp/hero-comp.html',
  styleUrls: ['app/components/hero-comp/hero-comp.css'],
  providers: [],
  directives: [],

  pipes: [],
  inputs:['hero', 'real']
})
export class HeroComp implements OnChanges{
  @Input() hero:Hero;
  @Input() real:string;
  constructor() {
  }
  ngOnChanges(changes) {
      console.log(changes);
  }
}

If, in addition to automatic two-way binding, you want to call a function when a value changes, you can break the two-way binding shortcut syntax to the more verbose version.

<input [(ngModel)]="yourVar"></input>

is shorthand for

<input [ngModel]="yourVar" (ngModelChange)="yourVar=$event"></input>

(see e.g. http://victorsavkin.com/post/119943127151/angular-2-template-syntax)

You could do something like this:

<input [(ngModel)]="yourVar" (ngModelChange)="changedExtraHandler($event)"></input>


You can use getter function or get accessor to act as watch on angular 2.

See demo here.

import {Component} from 'angular2/core';

@Component({
  // Declare the tag name in index.html to where the component attaches
  selector: 'hello-world',

  // Location of the template for this component
  template: `
  <button (click)="OnPushArray1()">Push 1</button>
  <div>
    I'm array 1 {{ array1 | json }}
  </div>
  <button (click)="OnPushArray2()">Push 2</button>
  <div>
    I'm array 2 {{ array2 | json }}
  </div>
  I'm concatenated {{ concatenatedArray | json }}
  <div>
    I'm length of two arrays {{ arrayLength | json }}
  </div>`
})
export class HelloWorld {
    array1: any[] = [];
    array2: any[] = [];

    get concatenatedArray(): any[] {
      return this.array1.concat(this.array2);
    }

    get arrayLength(): number {
      return this.concatenatedArray.length;
    }

    OnPushArray1() {
        this.array1.push(this.array1.length);
    }

    OnPushArray2() {
        this.array2.push(this.array2.length);
    }
}

Here is another approach using getter and setter functions for the model.

@Component({
  selector: 'input-language',
  template: `
  …
  <input 
    type="text" 
    placeholder="Language" 
    [(ngModel)]="query" 
  />
  `,
})
export class InputLanguageComponent {

  set query(value) {
    this._query = value;
    console.log('query set to :', value)
  }

  get query() {
    return this._query;
  }
}