typescript - Pasar valor entre dos componentes (páginas) en Angular 2
Estoy usando Angular 2 (TypeScript)
Tengo dos componentes (en realidad también son dos páginas). NO tienen una relación de padre e hijo.
Quiero pasar un valor al segundo componente (página) cuando haga clic en el enlace en el primer componente (página).
Sé manejar los "parámetros de URL" a través del enrutador. Pero no quiero mostrar este parámetro en el enlace. ¿Hay alguna otra forma?
¡Gracias!
Respuesta #1
La forma canónica es establecer un servicio injectable e inyectar el servicio en cualquier componente que necesite los datos. Dado que el servicio es un singleton, los componentes estarán accediendo a los mismos datos. No debería importar que estén en diferentes páginas. Plunker aquí.
Editar: Aquí hay un ejemplo más elaborado que muestra la comunicación bidireccional entre componentes suscribiéndose a un eventEmitter en un servicio: Plunker
import {Component, Injectable} from 'angular2/core'
// your shared service
// provide reference in parent component or bootstrap
@Injectable()
export class myService {
sharedData:string = "String from myService"
}
@Component({
selector: 'page1',
providers: [],
template: `
<div>
<b>Component Page1 - shared data:</b> {{SharedData}}
</div>
`,
directives: [],
})
export class Page1 {
constructor(aService: myService) {
this.SharedData = aService.sharedData
}
}
@Component({
selector: 'page2',
providers: [],
template: `
<div>
<b>Component Page2 - shared data:</b> {{SharedData}}
</div>
`,
directives: [],
})
export class Page2 {
constructor(aService: myService) {
this.SharedData = aService.sharedData
}
}
Respuesta #2
¡Gracias MarkM! Funciona, pero ha sido difícil para mí porque lo tengo todo en archivos diferentes y usando Angular CLI en la última versión de Angular2... Así que lo explico aquí:
Primero que nada: Necesitas crear un archivo con la clase que deseas compartir con otros componentes: data.service.ts y hacerlo "@Injectable":
import { Injectable } from '@angular/core';
@Injectable()
export class myService {
public sharedData:string;
constructor(){
this.sharedData = "String from myService";
}
setData (data) {
this.sharedData = data;
}
getData () {
return this.sharedData;
}
}
Asegúrate de establecer la clase creada (myService) en 'providers' solo una vez en el archivo app.module.ts e importar el archivo injectable: data.service.ts:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { routing, appRoutingProviders } from './app.routing';
import { AppComponent } from './app.component';
import { AppContent } from './components/content.component';
import { AppInsertContent } from './components/insert.component';
import { myService } from './services/data.service';
@NgModule({
declarations: [
AppComponent,
AppContent,
AppInsertContent,
],
imports: [
BrowserModule,
routing
],
providers: [appRoutingProviders, myService],
bootstrap: [AppComponent]
})
export class AppModule { }
Dondequiera que quieras usar tu clase compartida, utiliza el constructor para crear un objeto de la clase (este objeto será único para tus componentes, gracias al decorador @Injectable). ¡Recuerda importarlo en cada archivo en el que lo uses!...
En mi caso, esta vista establece los datos del objeto con un campo de texto: input.component.ts
import { Component } from '@angular/core';
import { myService } from '../services/data.service';
@Component({
selector: 'insert-content',
template: `
<input id="textbox" #textbox type="text">
<button (click)="this._myService.setData(textbox.value); SharedData = textbox.value;">SAVE</button>
Object data: {{SharedData}}
<div class="full-button">
<a routerLink="/" routerLinkActive="active">BACK</a>
</div>
`
})
export class AppInsertContent {
SharedData: string;
constructor (private _myService: myService){
console.log(this._myService.getData());
}
}
Y en esta vista solo veo los datos que se han establecido en el objeto: content.component.ts
import { Component } from '@angular/core';
import { myService } from '../services/data.service';
@Component({
selector: 'app-content',
template: `
<div style="float:left; clear:both;">
{{_myService.getData()}}
</div>
<div class="full-button">
<a routerLink="/insert" routerLinkActive="active">INSERT</a>
</div>
`
})
export class AppContent {
constructor (private _myService: myService){
console.log(this._myService.getData());
}
}
¡Espero que esta información sea útil!
