khollenbeck
khollenbeck

Reputation: 16157

Angular 2, share an object between two components that have no direct relationship

I have an app that is structured like this.

<app>
   <header>
      <component-a></component-a>
   </header>
   <div>
     <router-outlet></router-outlet>
     <component-b></component-b>  <!-- loaded through router -->
   </div>
</app>

In component-b some data is retrieved and later set to a new object. For example, something like this..

 {
    infoThatComponentANeeds    : true,
    someMoreInfoAddedFromCompB : []
 }

This info is needed for the template in component-a. At first I tried to pass the info up to component-a via @Outuput and eventEmitter using a custom event. But I was unable to get it to bubble up. I suspect that has to do with it being loaded through the router. So now I am trying to share the data between the two components using a shared service.

My Service So Far:

import {Injectable} from 'angular2/core';

@Injectable()
export class SharedService
{
    public spec:Spec= null;

    public getSpec()
    {
        return this.spec;
    }
    public setSpec(spec:Spec)
    {
        this.spec = spec;
    }
}

This is how I am trying to use it in component-a:

ngDoCheck()
{
    if(this._sharedService.spec)
    {
        this.spec= this._sharedService.getSpec();
    }
}

The Problem:

After the spec is set in component-b and ngDoCheck from component-a checks to see if the spec has been set. It comes back as undefined so the getSpec() function does not run, and no spec is returned. So I am not sure what I am missing, or why it would still be undefined in my SharedService after it has been set. Should the shared service keep a reference to what was set? Or am I completely misunderstanding this concept?

I have also explored ways of sharing this data via promises/observables. However I have not had any luck with that either. And the majority of the examples I have found use HTTP, which I really do not need at this point.

Update:

Here is some more info.

Boot.ts

import {bootstrap} from 'angular2/platform/browser';
import {HTTP_PROVIDERS} from 'angular2/http';
import {
    ROUTER_PROVIDERS,
    APP_BASE_HREF,
    Location,
    LocationStrategy,
    HashLocationStrategy,
    PathLocationStrategy
} from 'angular2/router';

import {AppComponent} from './components/app.component';
import {SharedService} from './services/shared.service';

bootstrap(<any>AppComponent, [
    ROUTER_PROVIDERS,
    SharedService,
    provide(LocationStrategy, {useClass: PathLocationStrategy})
]);

AppComponent.ts

import {AfterViewInit, Component, OnInit} from 'angular2/core';
import {RouteConfig, ROUTER_DIRECTIVES} from 'angular2/router';
import {ComponentA} from './componentA';


@Component({
    selector   : 'body',
    directives : [ComponentA, ROUTER_DIRECTIVES],
    template   : `
        <app>
            <header>
                <component-a></component-a>
            </header>
            <div>
                <router-outlet></router-outlet>
            </div>
        </app>
    `
})

@RouteConfig([
    {path: '/:appName/', name: 'ComponentB', component: ComponentB}
])

export class AppComponent
{
    constructor(){}
}

Update 2:

Here is a plunker I created to try to isolate the issue. I removed the router stuff and simplified the whole thing. I am still seeing the same result..

https://plnkr.co/edit/kx6FWWGS1i04bH5J9DXM?p=preview

Watch the console.log()

Fixed:

This was the key.

Be sure to remove configurations in the providers attribute of your two components.

Upvotes: 3

Views: 205

Answers (1)

Thierry Templier
Thierry Templier

Reputation: 202316

Perhaps your service isn't actually shared. I mean you could have two instances according to the way you configured providers.

To be sure, just add the service when bootstrapping your application:

bootstrap(AppComponent, [ SharedService ]);

Be sure to remove configurations in the providers attribute of your two components.

If you're interested in hierarchical injectors of Angular2 (the concept behind this), you could have a look at this question:

Upvotes: 1

Related Questions