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é!
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:
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,
....
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.