0

I have a setup that goes something like this:

main.ts - Usual structure, no problem there

app.component.ts - Usual structure, no problem there

app.component.html

<navigation-cart></navigation-cart>
<div id="content">
    ... other stuff ...
    <start-arrow></start-arrow>
</div>

ui-layout.service.ts - This service takes care of opening and closing all regions in the app.

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

@Injectable()

export class UiLayoutService {

    startArrowIsVisible: boolean = true;

    openStartArrow() {
        this.startArrowIsVisible = true;
        console.log('openStartArrow', this.startArrowIsVisible);
    }

    closeStartArrow() {
        this.startArrowIsVisible = false;
        console.log('closeStartArrow', this.startArrowIsVisible);
    }
    ...

}

Both navigation-cart.component.ts and start-arrow.component.ts have the UiLayoutService injected

start-arrow.component.html

<a (click)="uiLayoutService.openStartArrow();">Open</a>
<a (click)="uiLayoutService.closeStartArrow();">Close</a>

<div id="start-arrow" [ngClass]="{active: uiLayoutService.startArrowIsVisible}">
    ... Some pretty content here ...
</div>

navigation-cart.component.html

<a (click)="uiLayoutService.openStartArrow();">Open</a>
<a (click)="uiLayoutService.closeStartArrow();">Close</a>
... Some other content...

Here's what's troubling me:

  • If I click on Open and Close links from within <start-arrow> it all works just fine. The template gets updated and <div id="start-arrow"> get's closed and or reopened as expected. The console shows these actions running just fine.
  • If I click on Open and Close links from within <navigation-cart> the console fires the messages, I see the startArrowIsVisible value getting updated, but no template update happens in <start-arrow>. [ngClass]="{active: uiLayoutService.startArrowIsVisible} just doesn't seem to trigger the template update. I guess that this is because of optimisations done in order to prevent rendering the layout for all the app needlessly. How can I trigger the layout refresh in this situation?
Adrian Moisa
  • 3,923
  • 7
  • 41
  • 66
  • I may have found an answer here: [Global Events in Angular 2](http://stackoverflow.com/a/34703015/1903781). I'm still reading trying to understand how it works. – Adrian Moisa Jul 30 '16 at 19:23
  • 1
    I assume you provide the ´UiLayoutService` service multiple times and when click, the value is updated on a different instance than the one the components view is bound to. Angular DI creates a new instance per provider. If you want a single instance to be shared among your application, just share it once on the root component (or another common parent) – Günter Zöchbauer Jul 31 '16 at 11:26
  • Yes ideed, as you said, there were multiple instances. I checked with a separate `console.log` link and I saw the difference in model. I thought that angular2 DI injects singletones like angular1 + require.js. Now, the next question, how do I share this service from `app.component.ts` down below to children components? Should I use `@Input decorator`? – Adrian Moisa Jul 31 '16 at 12:24
  • 1
    It is shared automatically. Just add it as parameter to a component and you will get the instance of the first provider Angulars DI finds looking from your component towards the root component and `bootstrap(...)` `@Input()` is **not** related to shared services but only to binding like `
    `
    – Günter Zöchbauer Jul 31 '16 at 12:26

1 Answers1

1

I assume you provide the UiLayoutService service multiple times and when click, the value is updated on a different instance than the one the components view is bound to. Angular DI creates a new instance per provider. If you want a single instance to be shared among your application, just share it once on the root component (or another common parent)

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • Yup, finally managed it! I followed the instructions from this [answer](http://stackoverflow.com/a/36018798/1903781) and it all fit toghether just like you said. Thank you! – Adrian Moisa Jul 31 '16 at 13:21