Je dois définir la valeur dans un composant (composant A) et recevoir la valeur dans un autre composant (composant B). Le composant A et le composant B ne sont pas parents et enfants.
J'ai créé un service partagé pour partager des données entre les 2 composants. Je peux définir la valeur du composant B, mais lorsque je m'abonne pour obtenir la valeur du composant A, elle n'est pas déclenchée.
Voici ce que j'ai essayé:
J'ai ajouté le service dans @NgModule
providers
tableau dans appmodule.ts
fichier afin qu'il soit disponible pour tous les composants du projet.
Code de 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;
}
}
Composant B: Définition de la valeur ici
@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");
}
Composant A: Obtenez la valeur ici
@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);
});
}
Le déclencheur dans ComponentA est appelé lorsque ComponentA est chargé avec des données null
. Mais il n'est pas appelé lorsque buttonClick est appelé à partir de ComponentB.
MISE À JOUR :
J'ai compris le problème, j'aurais dû formuler ma question correctement. Lorsque ComponentA et ComponentB sont dans la même page (URL), le code fonctionne parfaitement.
Comment envoyer des données entre 2 composants lorsqu'ils se trouvent sur 2 pages différentes (URL).
Exemple: L'utilisateur ouvre URL1 (Renders ComponentA) qui a un bouton, l'utilisateur clique sur le bouton et est redirigé vers URL2 (Renders ComponentB) dans un nouvel onglet qui a un bouton, lorsque l'utilisateur clique sur le bouton, je dois transmettre des données à ComponentA et fermez URL2. J'ai besoin de récupérer les données transmises dans ComponentB et de les utiliser dans URL1. Est-il possible d'utiliser les services? Sinon, quelle approche dois-je suivre?
Le problème est à votre service. Lorsque vous définissez les données, le sujet a déjà émis la valeur. Fait comme ça.
Dans votre service, rendez BehaviorSubject
public et vous n'avez plus besoin de la méthode getValue
.
Dans ComponetA
où vous recevez les données de CompoenetB
, abonnez-vous à BehaviorSubject
qui est valueObs
.
Classe de service modifiée comme suit.
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;
// }
}
Si je ne me trompe pas, vous avez besoin de subsribe
ou d'utiliser async
pipe dans le modèle pour le composant a afin que vous obteniez toujours la dernière valeur du flux observable.
J'ai créé une application simple pour vous le démontrer.
Supposons que nous ayons 2 routes, dont chacune rend le composant pertinent (a, b).
Nous utilisons un service pour partager des données entre deux composants.
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;
}
}
Ensuite, dans le composant a, nous écoutons les changements du flux observable du service.
@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);
}
Dans le composant b, nous éditons simplement les données via la méthode 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();
}
Vous pouvez supprimer getValue () qui est appelée dans la méthode setValue ().
Composant:
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