web-dev-qa-db-ja.com

Angular 6データ共有サービスの購読がトリガーされていません

1つのコンポーネント(コンポーネントA)に値を設定し、別のコンポーネント(コンポーネントB)に値を受け取る必要があります。コンポーネントAとコンポーネントBは親と子ではありません。

2つのコンポーネント間でデータを共有するための共有サービスを作成しました。コンポーネントBから値を設定できますが、サブスクライブしてコンポーネントAの値を取得すると、トリガーされません。

これが私が試したものです:

プロジェクト内のすべてのコンポーネントで使用できるように、@NgModuleファイルのappmodule.tsproviders配列にServiceを追加しました。

サービスコード:

import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from '../../node_modules/rxjs';

@Injectable({
  providedIn: 'root'
})
export class SocialService {

  constructor() { }

  private valueObs: BehaviorSubject<string> = new BehaviorSubject<string>(null);

 public setValue(value: string):void {
     this.valueObs.next(value);
     this.getValue();
 }

 public getValue():Observable<string> {
     return this.valueObs;

 }

}

コンポーネントB:ここに設定値

@Component({
  selector: 'app-componentb',
  templateUrl: './componentb.component.html',
  styleUrls: ['./componentb.component.scss']
})


constructor(private socialService: SocialService, private http: HttpClient) {



}

 buttonClick()
 {

    this.socialService.setValue("linked successfully");
 }

コンポーネントA:ここで値を取得

@Component({
  selector: 'app-componenta',
  templateUrl: './componenta.component.html',
  styleUrls: ['./componenta.component.scss']
})


constructor(private socialService: SocialService, private http: HttpClient) {

       this.socialService.getValue().subscribe(data=>{

    console.log('Trigger from ComponentB');
    console.log(data);

});

}

ComponentAのトリガーは、ComponentAがnullのデータでロードされるときに呼び出されます。ただし、ComponentBからbuttonClickが呼び出されても呼び出されません。

[〜#〜]更新[〜#〜]

私は問題を理解しました、私は私の質問を適切に言い表すべきでした。 ComponentAとComponentBが同じページ(URL)にある場合、コードは完全に機能します。

2つの異なるページ(URL)にある場合、2つのコンポーネント間でデータを送信するにはどうすればよいですか。

例:ユーザーはボタンのあるURL1(Renders ComponentA)を開き、ボタンをクリックすると、ボタンのある新しいタブでURL2(Renders ComponentB)にリダイレクトされます。ユーザーがボタンをクリックすると、データを渡す必要がありますComponentAに、URL2を閉じます。 ComponentBで渡されたデータを取得して、URL1で使用する必要があります。サービスを使用することは可能ですか?そうでない場合、どのアプローチに従うべきですか?

7
Anirudh

サービスに問題があります。データを設定するとき、件名はすでに値を出力しています。このようにしてください。

  1. サービスでBehaviorSubjectをパブリックにすると、getValueメソッドは不要になります。

  2. ComponetAからデータを受け取るCompoenetBで、BehaviorSubjectであるvalueObsを購読します。

Serviceクラスを次のように変更しました。

import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';

@Injectable()
export class SocialService {

  public valueObs: BehaviorSubject<string> = new BehaviorSubject<string>(null);

  constructor() {}

  public setValue(value: string):void {
     this.valueObs.next(value);
     // this.getValue();
  }

 // public getValue():Observable<string> {
 //     return this.valueObs;
 // }
}
0

私が間違っていない場合は、subsribeを使用するか、コンポーネントaのテンプレートでasyncパイプを使用して、常に監視可能なストリームの最新の値を取得します。

これを説明する簡単なアプリを作成しました。

2つのルートがあり、それぞれが関連するコンポーネント(a、b)をレンダリングするとします。

サービスを使用して、2つのコンポーネント間でデータを共有します。

Injectable()
export class MyService {

  private _data = new BehaviorSubject<string>(null);

  setValue(value: string): void {
    this._data.next(value)
  }

  get data(): Observable<string> {
    return this._data;
  }

}

次に、コンポーネントaで、サービスの監視可能なストリームの変更をリッスンします。

@Component({
  selector: 'a-component',
  template: `Component A <br> Data: <pre>{{data}}</pre>`,
})
export class AComponent {
  @Input() name: string;

  data: Observable<string>;

  constructor(private myService: MyService) {
    this.myService.data.subscribe(data => this.data = data);
  }

コンポーネントbでは、service setValueメソッドを使用してデータを編集するだけです。

@Component({
  selector: 'b-component',
  template: `Component B <br> 
  <input type="text" placeholder="set data for component a" [(ngModel)]="modifiedData" (ngModelChange)="editServiceData($event)"/>`,
})
export class BComponent  {
  @Input() name: string;
  modifiedData;

  constructor(private myService: MyService) {}

  editServiceData(data: string) {
    this.myService.setValue(data)
  }
}

上記のフローを示すスニペットです

0
Korte
getValue method should return observable.

public getValue():Observable<string> {
     return this.valueObs.asObservable();
}

SetValue()メソッドで呼び出されているgetValue()を削除できます。

コンポーネント:

this.socialService.getValue().subscribe(data=>{
    console.log('Trigger from ComponentB');
    console.log(data);
  });

StackBlitz: https://stackblitz.com/edit/angular-e6uxlo?file=src%2Fapp%2Fhello.component.ts

0