Come posso condividere i dati tra i componenti in Angular 2?

In Angular 1.xx è sufficiente richiedere lo stesso servizio e si finisce con la stessa istanza, rendendo ansible la condivisione dei dati nel servizio.

Ora in Angular 2 ho un componente che ha un riferimento al mio servizio. Posso leggere e modificare i dati nel servizio, che è buono. Quando provo a iniettare lo stesso servizio in un altro componente, sembra che ottenga una nuova istanza.

Che cosa sto facendo di sbagliato? È il modello stesso che è sbagliato (utilizzando un servizio per condividere dati) o devo contrassegnare il servizio come un singleton (all’interno di un’istanza dell’app) o qualcosa del genere?

Sono su 2.0.0-alpha.27/ btw

appInjector un servizio tramite appInjector (modifica: ora providers ) nell’annotazione @Component e quindi salvare un riferimento nel costruttore. Funziona localmente nel componente – solo non attraverso i componenti (non condividono la stessa istanza di servizio) come pensavo avrebbero fatto.

AGGIORNAMENTO : A partire da Angular 2.0.0 ora abbiamo @ngModule dove definirai il servizio sotto la proprietà providers su said @ngModule . Ciò garantirà la stessa istanza di quel servizio da passare a ciascun componente, servizio, ecc. In quel modulo. https://angular.io/docs/ts/latest/guide/ngmodule.html#providers

Un servizio singleton è una bella soluzione. Altri modi: data/events bindings .

Ecco un esempio di entrambi:

 class BazService{ n: number = 0; inc(){ this.n++; } } @Component({ selector: 'foo' }) @View({ template: `` }) class FooComponent{ constructor(foobaz: BazService){ this.foobaz = foobaz; } } @Component({ selector: 'bar', properties: ['prop'] }) @View({ template: `` }) class BarComponent{ constructor(barbaz: BazService){ this.barbaz = barbaz; } } @Component({ selector: 'app', viewInjector: [BazService] }) @View({ template: `   `, directives: [FooComponent, BarComponent] }) class AppComponent{} bootstrap(AppComponent); 

Guarda dal vivo

Il commento di @maufarinelli merita la sua risposta perché fino a quando l’ho visto, stavo ancora sbattendo la testa contro il muro con questo problema anche con la risposta di @Alexander Ermolov.

Il problema è che quando aggiungi un providers al tuo component :

 @Component({ selector: 'my-selector', providers: [MyService], template: `
stuff
` })

Ciò causa l’iniezione di una nuova istanza del servizio, anziché essere un singleton .

Quindi rimuovi tutte le istanze dei tuoi providers: [MyService] nella tua applicazione tranne nel module , e funzionerà!

È necessario utilizzare gli input e gli output di un decoratore @Component. Ecco l’esempio più semplice di utilizzo di entrambi;

 import { bootstrap } from 'angular2/platform/browser'; import { Component, EventEmitter } from 'angular2/core'; import { NgFor } from 'angular2/common'; @Component({ selector: 'sub-component', inputs: ['items'], outputs: ['onItemSelected'], directives: [NgFor], template: ` 
{{ item }}
` }) class SubComponent { onItemSelected: EventEmitter; items: string[]; constructor() { this.onItemSelected = new EventEmitter(); } select(i) { this.onItemSelected.emit(this.items[i]); } } @Component({ selector: 'app', directives: [SubComponent], template: `
` }) class App { items: string[]; constructor() { this.items = ['item1', 'item2', 'item3']; } itemSelected(item: string): void { console.log('Selected item:', item); } } bootstrap(App);

Nel modello Componente padre:

   

Nella componente secondaria:

 @Input() hero: Hero; 

Fonte: https://angular.io/docs/ts/latest/cookbook/component-communication.html

Ci sono molti modi. Questo è un esempio che utilizza la propagazione tra elementi padre e figlio. Questo è molto efficiente.

Ho presentato un esempio che consente di visualizzare l’utilizzo di due metodi di associazione dati all’interno di due forms. Se qualcuno può fornire un campione plunkr questo sarebbe molto bello 😉

Puoi cercare un altro modo usando un fornitore di servizi. Puoi anche dare un’occhiata a questo video per riferimento: ( Condivisione dei dati tra i componenti in Angolare )

mymodel.ts (dati da condividere)

 // Some data we want to share against multiple components ... export class mymodel { public data1: number; public data2: number; constructor( ) { this.data1 = 8; this.data2 = 45; } } 

Ricorda: ci deve essere un genitore che condividerà “mymodel” con componenti figlio.

Componente genitore

 import { Component, OnInit } from '@angular/core'; import { mymodel } from './mymodel'; @Component({ selector: 'app-view', template: '  '   ', }) export class MainComponent implements OnInit { public model: mymodel; constructor() { this.model = new mymodel(); } ngOnInit() { } } 

Componente figlio, mychild.component.ts

 import { Component, OnInit,Input } from '@angular/core'; import { FormsModule } from '@angular/forms'; // < -- NgModel lives here import { mymodel } from './mymodel'; @Component({ selector: 'app-mychild', template: ' 
label>data2
data2 is required
', }) export class MychildComponent implements OnInit { @Input() model: mymodel ; // Here keywork @Input() is very important it indicates that model is an input for child component constructor() { } ngOnInit() { } }

Nota: in alcuni rari casi, è ansible che si verifichi un errore durante l’analisi del codice HTML, in quanto il modello non è “pronto” da utilizzare durante l’inizializzazione della pagina. In questo caso, prefisso il codice HTML con una condizione ngIf:

 
{{model.data1}}