Angular 2 salida de router-outlet


Quiero hacer la navegación desde componentes secundarios que se renderizan dentro del router-outlet. Mi componente padre tiene una configuración de enrutador y quiero navegar manualmente en algún evento. Pero no se como puedo pasar de niño a padre algunos datos (para navegación) sin salida. Porque esta construcción no funciona

 <router-outlet (navigateTo)="navigateToMessagePart($event)"></router-outlet>

¿Cómo puedo hacerlo de la manera correcta? Tal vez navegar desde el niño? Pero cómo puedo obtener métodos de padres de niño. Muchas gracias por cualquier ayuda!

Author: Velidan, 2016-06-06

4 answers

<router-outlet></router-outlet> es solo un marcador de posición para agregar componentes enrutados. No hay soporte para ningún tipo de unión.

Puede crear un <router-outlet> personalizado que le permita hacer eso o más común, usar un servicio compartido para comunicarse entre el componente padre y el componente enrutado.

Para más detalles ver https://angular.io/docs/ts/latest/cookbook/component-communication.html

Update

Ahora Hay un evento que permite obtener el añadido componente

<router-outlet (activate)="componentAdded($event)" (deactivate)="componentRemoved($event)"></router-outlet>

Que permite comunicarse (getters de llamadas, setters y métodos) con el componente en componentAdded()

Sin embargo, un servicio compartido es la forma preferida.

 33
Author: Günter Zöchbauer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-28 03:28:20

<router-outlet></router-outlet> no se puede usar para emitir un evento desde el componente hijo. Una forma de comunicarse entre dos componentes es utilizar un servicio común.

Crear un servicio

Servicio compartido.ts

import { Observable } from 'rxjs/Observable';
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';
@Injectable()
export class SharedService {
    // Observable string sources
    private emitChangeSource = new Subject<any>();
    // Observable string streams
    changeEmitted$ = this.emitChangeSource.asObservable();
    // Service message commands
    emitChange(change: any) {
        this.emitChangeSource.next(change);
    }
}

Ahora inyecte la instancia del servicio anterior en el constructor del componente padre e hijo.

El componente hijo emitirá un cambio cada vez que se llame al método onClick ()

Niño.componente.ts

import { Component} from '@angular/core';
@Component({
    templateUrl: 'child.html',
    styleUrls: ['child.scss']
})
export class ChildComponent {
    constructor(
        private _sharedService: SharedService
    ) { }

onClick(){
  this._sharedService.emitChange('Data from child');

 }
}

El componente principal recibirá ese cambio. Para ello,captura la suscripción dentro del constructor del padre.

Padre.componente.ts

import { Component} from '@angular/core';
@Component({
    templateUrl: 'parent.html',
    styleUrls: ['parent.scss']
})
export class ParentComponent {
    constructor(
        private _sharedService: SharedService
    ) {
          _sharedService.changeEmitted$.subscribe(
        text => {
            console.log(text);
        });
      }

}

Espero que esto ayude:)

 83
Author: Antara Datta,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-24 06:50:40

La respuesta dada arriba es correcta y completa. Solo quiero agregar para aquellos que la solución no funcionó para ellos que deben agregar el servicio a los proveedores solo en el componente padre y no en el hijo para asegurarse de que obtenga un singleton del servicio, de lo contrario se crearán dos instancias de servicio. Esta respuesta está inspirada en el comentario de @HeisenBerg en la respuesta anterior.

 1
Author: Bacem,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-24 06:35:19

Cambié un poco de la respuesta de Antara Datta. He creado un servicio de abonado

import {Injectable} from '@angular/core';
import {Subject} from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class Subscriber<T>
{
  protected observable = new Subject<T>();

  public next(item: T)
  {
    this.observable.next(item);
  }

  public subscribe(callback: (item:T)=>void) {
    this.observable.subscribe(callback);
  }
}

Cada vez que necesito dos componentes para compartir alguna información, inyecto este servicio en el constructor que se suscribe a él:

 constructor(protected layoutOptions: Subscriber<Partial<LayoutOptions>>)
 {
    layoutOptions.subscribe(options => this.options = Object.assign({}, this.options, options));
 }

Y el que lo actualiza

constructor(protected router: Router, protected apiService: ApiService, protected layoutOptions: Subscriber<Partial<LayoutOptions>>)
  {
    this.layoutOptions.next({showNavBar: false});
  }
 0
Author: Raza,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-02 19:55:45