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 parent et enfant.
J'ai créé un service partagé pour partager des données entre les 2 composants. Je suis en mesure de définir la valeur du composant B, mais lorsque je m'abonne pour obtenir la valeur du composant A, il n'est pas déclenché.
Voici ce que j'ai essayé:
J'ai ajouté le service dans le tableau @NgModule
fournisseurs
dans appmodule.ts
afin qu'il soit disponible pour tous les composants du projet.
Code de service:
@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); }); }
Composant B: Définition de la valeur ici
XXX
Composant A: Obtenez 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"); }
Le déclencheur dans ComponentA est appelé lorsque ComponentA est chargé avec des données étant nul
. Mais il n'est pas appelé lorsque buttonClick est appelé depuis ComponentB. p>
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 sont dans 2 pages différentes (URLS).
Exemple: l'utilisateur ouvre l'URL1 (Renders ComponentA) qui a un bouton, l'utilisateur clique sur le bouton et est redirigé vers l'URL2 (Renders ComponentB) dans un nouvel onglet qui a un bouton, lorsque l'utilisateur clique sur le bouton , Je dois transmettre certaines données à ComponentA et fermer URL2. J'ai besoin de récupérer les données passées dans ComponentB et de les utiliser dans URL1. Est-il possible d'utiliser les services? Sinon, quelle approche dois-je suivre?
6 Réponses :
Dans votre cas, vous devez vous abonner à this.valueObs
pour ne pas inclure cette méthode, car votre variable valueObs
est de type observable, vous pouvez donc vous abonner directement à cela comme ceci -
constructor(private socialService: SocialService, private http: HttpClient) { this.socialService.getValue().subscribe(data=>{ console.log('Trigger from ComponentB'); console.log(data); }); this.socialService.valueObs.subscribe(data=>{ console.log('Trigger from ComponentB on Next called'); }); }
La méthode valueObs.subscribe
n'est pas du tout appelée. La méthode getValue (). Subscribe
n'est pas non plus appelée.
this.socialService.getValue().subscribe(data=>{ console.log('Trigger from ComponentB'); console.log(data); });
J'ai essayé cela aussi, ne fonctionnant pas. Y a-t-il autre chose que je pourrais manquer?
au lieu d'appeler un appel constructor () dans ngOnInit
Stackblitz mis à jour
Si vous souhaitez partager des données entre des composants dans Tab. Mieux vaut enregistrer les données dans le stockage local et accéder à d'autres endroits.
Vous pouvez effectivement utiliser
Subject
avec le routeur. Donc, Ici est une solution en direct pour votre scénario en utilisantRouteur
etSubject
.Votre service contiendra simplement -
this.socialService.getValue().subscribe(data => { this.dataFromB = data; console.log('Trigger from ComponentB'); console.log(data); })Ensuite, votre
ComponentB
contiendra -buttonClick() { this.socialService.setValue("linked successfully"); this.router.navigate(['/a']); }Et, le constructeur de votre
ComponentA
contiendra -public setValue(value: string): void { this.valueObs.next(value); } public getValue(): Observable < string > { return this.valueObs; }
Je pense que vous auriez besoin d'un ReplaySubject pour cela. Votre composant qui s'abonne à l'observable s'abonne, une fois la valeur émise et donc l'observable n'émet plus, il n'y a aucune valeur à obtenir de cette observable. Un ReplaySubject prend soin de donner à l'abonné toutes les émissions qui ont eu lieu avant même la fin de l'abonnement.
La solution @Tushar Walzade fonctionne, car les deux composants sont dans le composant d'application, donc les deux observateurs s'abonnent avant que l'événement ne soit émis. (L'abonnement a lieu à l'intérieur du constructeur pour les deux composants, qui est appelé avant de cliquer sur le bouton). Mais si vous avez un module chargé paresseusement par exemple, le seul composant ne sera créé qu'au chargement et vous n'obtiendrez les données que si vous utilisez un ReplaySubject ou l'opérateur rxjs publier ou partager
Regardez ici:
opérateurs de publication et de partage sujets, sujets de comportement et sujets de relecture
Votre commentaire vient de sauver ma journée. Merci!
Si je ne me trompe pas, ce dont vous avez besoin est soit de souscrire
, soit d'utiliser le tube async
dans le modèle du 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.
Disons que nous avons 2 routes, chacune rendant le composant pertinent (a, b).
Nous utilisons un service pour partager des données entre deux composants.
@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) } }
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); }
Le problème est dans votre service. Lorsque vous définissez les données, le sujet a déjà émis la valeur. Faites 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
, souscrivez à 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; // } }
Veuillez fournir un exemple reproductible minimal , car cela devrait fonctionner.
Vous pouvez le faire sur stackblitz.com
@trichetriche, j'ai mis à jour ma question, pouvez-vous vérifier.
@TusharWalzade pourriez-vous me guider vers un exemple de code ou un tutoriel?
@RafaelLima s'il vous plaît voir la mise à jour dans ma question.
peut-être que cela pourrait aider angular.io/guide/component-interaction
Avez-vous essayé le ReplaySubject?
cela a fonctionné pour moi aussi dans ionic4