web-dev-qa-db-ja.com

Angular 2ルーターアウトレットからの出力

ルーターアウトレット内でレンダリングする子コンポーネントからナビゲーションを作成したい。私の親コンポーネントにはルーター設定があり、何らかのイベントが発生した場合に手動でナビゲートしたいと考えています。しかし、出力せずに(ナビゲーション用の)データを子から親に渡す方法はわかりません。この構造は機能しないため

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

どうすれば正しい方法でそれを行うことができますか?たぶん子供からそれをナビゲートしますか?しかし、子から親メソッドを取得する方法。助けてくれてありがとう!

47
Velidan

<router-outlet></router-outlet>は、ルーティングされたコンポーネントを追加するための単なるプレースホルダーです。あらゆる種類のバインディングはサポートされていません。

カスタム<router-outlet>を作成して、それを可能にするか、より一般的に、共有サービスを使用して親コンポーネントとルーティングされたコンポーネント間で通信することができます。

詳細については、 https://angular.io/docs/ts/latest/cookbook/component-communication.html を参照してください

update

追加されたコンポーネントを取得できるイベントがあります

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

componentAdded()のコンポーネントと通信(ゲッター、セッター、およびメソッドを呼び出す)できるようにします

ただし、共有サービスが好ましい方法です。

43

<router-outlet></router-outlet>を使用して、子コンポーネントからイベントを発行することはできません。 2つのコンポーネント間で通信する1つの方法は、共通のサービスを使用することです。

サービスを作成する

shared-service.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);
    }
}

次に、上記のサービスのインスタンスを、親コンポーネントと子コンポーネントの両方のコンストラクターに注入します。

子コンポーネントは、onClick()メソッドが呼び出されるたびに変更を発行します

child.component.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');

 }
}

親コンポーネントはその変更を受け取るものとします。そのためには、親のコンストラクター内でサブスクリプションをキャプチャします。

parent.component.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);
        });
      }

}

お役に立てれば :)

111
Antara Datta

上記の答えは正確かつ完全です。ソリューションがうまくいかなかった人のために、サービスをシングルコンポーネントを取得するために、子ではなく親コンポーネントのみのプロバイダーにサービスを追加する必要があることを追加します。そうしないと、2つのサービスインスタンスが作成した。この応答は、前の応答の@HeisenBergのコメントに触発されています。

5
Bacem

アンタラダッタの答えから少し変更しました。サブスクライバーサービスを作成しました

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

情報を共有するために2つのコンポーネントが必要になるたびに、サブスクライブするコンストラクターにこのサービスを注入します。

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

そしてそれを更新するもの

constructor(protected router: Router, protected apiService: ApiService, protected layoutOptions: Subscriber<Partial<LayoutOptions>>)
  {
    this.layoutOptions.next({showNavBar: false});
  }
2
Raza