2016-02-08 7 views
20

Ho un oggetto che desidero condividere tra i miei componenti in un'app Angular2.Angular2 - Condivisione di dati tra componenti tramite servizi

Ecco l'origine del primo componente:

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

e il secondo componente:

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

e, infine, il mio piccolo servizio, il 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; 
    } 
} 

miei dati non sono condivisi, nel grid.component.ts, la riga _configService.getConfig() restituisce un oggetto vuoto, bu t è riempito poco prima in app.component.ts.

Ho letto i documenti e le esercitazioni, niente ha funzionato.

Cosa mi manca?

Grazie

RISOLTI

Il mio problema era che stavo iniettando il mio ConfigService due volte. Nel bootstrap dell'applicazione e nel file in cui lo sto usando.

Ho rimosso l'impostazione providers e ha funzionato!

+0

Come nota a margine, prendere in considerazione lo spostamento delle chiamate di servizio dal costruttore. – Stanislasdrg

+0

http://www.angulartutorial.net/2017/09/angular-share-data-between-components.html – Prashobh

risposta

22

Lo si definisce all'interno dei due componenti. Quindi il servizio non è condiviso. Si dispone di un'istanza per il componente AppComponent e di un'altra per il componente Grid.

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

La soluzione rapida è quella di rimuovere l'attributo providers al componente griglia ... In questo modo l'istanza del servizio sarà condiviso dai componenti AppComponent e dei suoi bambini.

L'altra soluzione è registrare il provider corrispondente all'interno della funzione bootstrap. In questo caso, l'istanza sarà condivisa dall'intera applicazione.

bootstrap(AppComponent, [ ConfigService ]); 

Per comprendere il motivo per cui avete bisogno di fare questo, è necessario essere consapevoli della funzione "iniettori gerarchici" di Angular2. Seguenti link potrebbero essere utili:

+0

OK, infatti ho entrambi ... Nel bootstrap e nei provider in ogni file che voglio. Questo può essere il mio problema quindi. Lo provo al più presto e ti dico se questo era il problema – keversc

+0

Sì, ma non ne hai bisogno. Quando si configurano i provider, l'ambito dell'istanza associata sarà l'elemento e i relativi elementi secondari. Definire nuovamente ricreerà una nuova istanza. Ad esempio, se si definisce il provider in bootstrap e uno in un componente, si avranno due istanze del servizio: una a livello di applicazione e una a livello di componente. –

+0

Se si definisce solo a livello di applicazione, tutti i componenti potrebbero utilizzare questa istanza per iniezione di dipendenza. È perché l'iniettore del componente è un iniettore secondario o l'applicazione. Sfruttano l'eredità prototipale. Il bambino può vedere gli elementi nel genitore –

4

Non aggiungere ConfigService a providers del componente. Ciò si traduce in nuove istanze per ogni componente. Aggiungilo a providers di un componente genitore comune. Se lo aggiungi al tuo componente root o bootstrap(App, [ConfigService]), l'intera applicazione condivide una singola istanza.

+0

OK grazie, vedrò questo, per ora ho ConfigService sia nel bootstrap che nel file, questo potrebbe essere il mio problema. Ci provo al più presto – keversc

5

Per l'ultima versione di angular, se si desidera condividere il servizio, non è possibile aggiungerlo alla funzione di bootstrap. Basta aggiungerlo all'elenco dei provider NgModule come faresti con un servizio normale, il suo comportamento predefinito sarà singleton.

bootstrap (AppComponent);

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