web-dev-qa-db-fra.com

Angular2 - Partager des données entre composants à l'aide de services

J'ai un objet que je souhaite partager entre mes composants dans une application Angular2.

Voici la source du premier composant:

/* 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);
    }
}

et le deuxième élément:

/* 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();
    }
  }

et enfin mon petit service, le 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;
    }
}

Mes données ne sont pas partagées, dans le grid.component.ts, la ligne _configService.getConfig() retourne un objet vide, mais il est rempli juste avant dans app.component.ts.

J'ai lu les documents et les tutoriels, rien n'a fonctionné.

Qu'est-ce que je rate ?

Merci

RÉSOLU

Mon problème était que j'injectais mon ConfigService deux fois. Dans le bootstrap de l'application et dans le fichier où je l'utilise).

J'ai supprimé le paramètre providers et cela a fonctionné!

27
keversc

Vous le définissez dans vos deux composantes. Le service n'est donc pas partagé. Vous avez une instance pour le composant AppComponent et une autre pour le composant Grid.

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

La solution rapide consiste à supprimer l'attribut providers de votre composant Grid ... De cette façon, l'instance de service sera partagée par le AppComponent et ses composants enfants.

L'autre solution consiste à enregistrer le fournisseur correspondant dans la fonction bootstrap. Dans ce cas, l'instance sera partagée par l'ensemble de l'application.

bootstrap(AppComponent, [ ConfigService ]);

Pour comprendre pourquoi vous devez le faire, vous devez être conscient de la fonction "injecteurs hiérarchiques" d'Angular2. Les liens suivants pourraient être utiles:

28
Thierry Templier

Pour la dernière version d'angular, si vous souhaitez partager le service, vous ne pouvez pas l'ajouter à la fonction bootstrap. Ajoutez-le simplement à la liste des fournisseurs NgModule comme vous le feriez avec un normal service, son comportement par défaut sera singleton.

bootstrap (AppComponent);

@NgModule({
    declarations: [
        ....
    ],
    imports: [
       ....     
    ],
    providers: [
        ConfigService,
....
6
Mike D

N'ajoutez pas ConfigService à providers de votre composant. Il en résulte de nouvelles instances pour chaque composant. Ajoutez-le à providers d'un composant parent commun. Si vous l'ajoutez à votre composant racine ou à bootstrap(App, [ConfigService]), votre application entière partage une seule instance.

4
Günter Zöchbauer