Angular 2 + Ionic 2: Detect if an object was modified

However, ideally I need another way, like the angular 1 $watch, as
there are other ways my complex object can be changed, not just simple
input fields

I was working in a Google Autocomplete Component, and I was dealing with a similar issue: when the user types an address and select one from the Google suggestions, I needed to update some other fields (like city, province, zip code, and so on).

Like @Günter Zöchbauer says, I’ve created an observable in order to know when something has changed in my autocomplete component, but the second problem was that the view was not being updated when that happened. That’s because something very interesting and powerfull called Zones. If the concept is new for you, please refer to here and here for a great explanation.

As you can read there,

Application state change is caused by three things:

  1. Events – User events like click, change, input, submit, …

  2. XMLHttpRequests – E.g. when fetching data from a remote service

  3. Timers – setTimeout(),setInterval(), because JavaScript

… it turns out that these are the only cases when Angular is actually
interested in updating the view.

So if

there are other ways my complex object can be changed

You will have to let Angular know that something has changed and needs to we aware of updating things. This is what I did:

import {Injectable} from '@angular/core';
import {Observable} from 'rxjs/Observable';

@Injectable()
export class AutocompleteService {

    private autocompleteObserver: any;
    public autocomplete: any;

    constructor(...) {
        this.autocompleteObserver = null;

        this.autocomplete = Observable.create(observer => {
            this.autocompleteObserver = observer;
        });
    }

    public initializeAutocomplete(element): void { 

        // Where all the magic happens
        // ...

        // Send informtaion back to the caller
        this.autocompleteObserver.next(addressInformation);
    }

And then in my page .ts:

import { Component, NgZone } from '@angular/core';
import { AutocompleteService } from '../../providers/autocomplete-service/autocomplete-service';

@Component({
  templateUrl: 'build/pages/my-new-page/my-new-page.html',
  directives: [FORM_DIRECTIVES],
  providers: [AutocompleteService]
})
export class MyNewPage {

    constructor(..., private autocompleteService : AutocompleteService) {
    
        // Initialize all the things you need
        // ... 

       this.autocompleteService.autocomplete.subscribe((addressInfo) => {
            this.ngZone.run(() => {
                // Update the fields of the form, and Angular will update
                // the view for you.
                this.updateAddress(addressInfo);
            });
        });
    }
}

So by executing some code inside an angular zone you’re telling Angular that it needs to be aware of those changes because things will probably need to be updated.

Leave a Comment