keversc February 2016

Angular2 - Share data between components using services

I have an object that I want to share between my components into an Angular2 app.

Here is the source of the first component:

/* app.component.ts */

// ...imports
import {ConfigService} from './config.service';

@Component({
    selector: 'my-app',
    templateUrl: 'app/templates/app.html',
    directives: [Grid],
    providers: [ConfigService]
})
export class AppComponent {
    public size: number;
    public square: number;

    constructor(_configService: ConfigService) {
        this.size = 16;
        this.square = Math.sqrt(this.size);

        // Here I call the service to put my data
        _configService.setOption('size', this.size);
        _configService.setOption('square', this.square);
    }
}

and the second component:

/* grid.component.ts */

// ...imports
import {ConfigService} from './config.service';

@Component({
    selector: 'grid',
    templateUrl: 'app/templates/grid.html',
    providers: [ConfigService]
})
export class Grid {
    public config;
    public header = [];

    constructor(_configService: ConfigService) {
        // issue is here, the _configService.getConfig() get an empty object 
        // but I had filled it just before
        this.config = _configService.getConfig();
    }
  }

and finally my little service, the ConfigService:

/* config.service.ts */

import {Injectable} from 'angular2/core';

@Injectable()
export class ConfigService {

    private config = {};

    setOption(option, value) {
        this.config[option] = value;
    }

    getConfig() {
        return this.config;
    }
}

My data are not shared, in the grid.component.ts, the _configService.getConfig() line return an empty object, but it is filled just before in the app.component.ts.

I read the docs and tutorials, nothing worked.

What am I missing ?

Thanks

SOLVED

My issue was that

Answers


Thierry Templier February 2016

You define it within your two components. So the service isn't shared. You have one instance for the AppComponent component and another one for the Grid component.

@Component({
  selector: 'my-app',
  templateUrl: 'app/templates/app.html',
  directives: [Grid],
  providers: [ConfigService]
})
export class AppComponent {
  (...)
}

The quick solution is to remove the providers attribute to your Grid component... This way the service instance will be shared by the AppComponent and its children components.

The other solution is to register the corresponding provider within the bootstrap function. In this case, the instance will be shared by the whole application.

bootstrap(AppComponent, [ ConfigService ]);

To understand why you need to do that, you need to be aware of the "hierarchical injectors" feature of Angular2. Following links could be useful:


Günter Zöchbauer February 2016

Don't add ConfigService to providers of your component. This results in new instances for every component. Add it to providers of a common parent component. If you add it to your root component or bootstrap(App, [ConfigService]) your entire application shares a single instance.

Post Status

Asked in February 2016
Viewed 2,252 times
Voted 7
Answered 2 times

Search




Leave an answer