1つのコンポーネント(コンポーネントA)に値を設定し、別のコンポーネント(コンポーネントB)に値を受け取る必要があります。コンポーネントAとコンポーネントBは親と子ではありません。
2つのコンポーネント間でデータを共有するための共有サービスを作成しました。コンポーネントBから値を設定できますが、サブスクライブしてコンポーネントAの値を取得すると、トリガーされません。
これが私が試したものです:
プロジェクト内のすべてのコンポーネントで使用できるように、@NgModule
ファイルのappmodule.ts
providers
配列に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で使用する必要があります。サービスを使用することは可能ですか?そうでない場合、どのアプローチに従うべきですか?
サービスに問題があります。データを設定するとき、件名はすでに値を出力しています。このようにしてください。
サービスでBehaviorSubject
をパブリックにすると、getValue
メソッドは不要になります。
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;
// }
}
私が間違っていない場合は、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)
}
}
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