Búsqueda de sitios web

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!

Artículos relacionados