Sebastian
Sebastian

Reputation: 1912

Angular 2 Service update UI on change

I im developing an Angular2 application where I have a ConfigurationService and a component, that needs to register on changes on properties of this service.

import {Injectable} from "angular2/src/core/di/decorators";
@Injectable()
export class ConfigurationService {
    private config = {
        showDeveloperOptions: false
    }

    constructor() {}

    get isDeveloper() {
        return this.config.showDeveloperOptions;
    }


    public setDeveloperOptions(developerOptions: boolean) {
        this.config.showDeveloperOptions = developerOptions;
        console.warn("Set DeveloperOptions to " + this.config.showDeveloperOptions);
    }
}

my view component:

@Component({
    selector: 'developer',
    template: `<div [hidden]="config.isDeveloper">Not a Developer</div>`,
    providers: [ConfigurationService],
})

export class DeveloperComponent {
    constructor(public config: ConfigurationService) {
    }
}

Unfortunately, when I trigger ConfigurationService.setDeveloperOptions(true) from another service where this service got injected, it does not update the view.

What am I doing wrong?

Many thanks!

Seb

Upvotes: 0

Views: 2872

Answers (1)

Andr&#233; Werlang
Andr&#233; Werlang

Reputation: 5944

Never deep import an Angular module. Also, the module you import is not longer there:

import {Injectable} from "@angular/core";

This is just to mark the service for dependency injection, but is not the issue here.

The issue is how angular proceeds with change detection. A view should be updated only from:

  1. itself
  2. an input property
  3. an observable

This is to guarantee a single pass is enough to process views.

import {Injectable} from "@angular/core";
import {BehaviorSubject} from "rxjs/BehaviorSubject";

@Injectable()
export class ConfigurationService {
    private config = new BehaviorSubject({
        showDeveloperOptions: false
    });

    constructor() {}

    get isDeveloper() {
        return this.config.map(config => config.showDeveloperOptions);
    }

    public setDeveloperOptions(developerOptions: boolean) {
        this.config.next({showDeveloperOptions: developerOptions});
        console.warn("Set DeveloperOptions to " + developerOptions);
    }
}

Then you use the async pipe to unwrap the value. The view will update itself.

@Component({
    selector: 'developer',
    template: `<div [hidden]="(config.isDeveloper | async)">Not a Developer</div>`,
    providers: [ConfigurationService],
})

export class DeveloperComponent {
    constructor(public config: ConfigurationService) {
    }
}

Upvotes: 1

Related Questions