【问题标题】:Sharing Data between Sibling Components using Shared Service returning empty in Angular使用共享服务在 Angular 中返回空的兄弟组件之间共享数据
【发布时间】:2021-10-30 12:56:33
【问题描述】:

我试图在 Angular 中的两个同级组件之间共享一个字符串,但它似乎对我不起作用。

我有两个组件,auth.component.tsupdate.component.ts。然后我有一个名为 shared.service.ts 的服务。

编辑 2: 根据 cmets 中的建议,我将包含整个 shared.services.ts 文件。

shared.service.ts

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

@Injectable({
  providedIn: 'root'
})

export class SharedService {

  private useridSource = new BehaviorSubject('empty');

  useridMessage$ = this.useridSource.asObservable();

  constructor() { }

  sendUserId(userId:string) {
    this.useridSource.next(userId);
  }
}

auth 组件的目的是允许用户通过 firebase 的身份验证方法登录/注册。然后,我检索用户的唯一 ID,并希望将该字符串传递给 update.ts 组件,以便它可以在 Firebase 实时数据库中以该名称创建一个节点。请注意,在使用 firebase 时,我也在使用 Angular Fire Library

这是 auth.component.ts

的代码的 sn-ps
  //I store the unique ID created by firebase in this string
  userId?:string;

  //I inject the AngularFireAuth from the Angular Fire library as well as my Shared Service 
  constructor(public auth: AngularFireAuth, private sharedService: SharedService ) { }

  //the user logs in or signs up using google
  login() {
    this.auth.signInWithPopup(new firebase.auth.GoogleAuthProvider());
  }

  //this function sets the userId string - if I console.log() this string, it prints out correctly
  printUserId() {
    this.auth.authState.subscribe( authState => {
      this.currentAuth = authState;
      this.userId = this.currentAuth.uid;
    })
  }

  //I use this function to send the data via the shared service when a button is pressed in the HTML file. 
  sendUserData(){
    if(this.userId) {
      console.log(this.userId);
      this.sharedService.sendUserId(this.userId);
    } else {
      console.log("User Id has not been set");
    }
  }

auth.component.html 文件中,我通过以下方式将数据发送到服务:

  <button (click)="sendUserData()"> Send Current User </button>

update.component.ts中,我收到了数据,想打印出来。

  //string to receive the data in 
  userId?:string;

  //inject the shared service. The CrowboxdbService is another service I use to interact with firebase
  constructor(private cbservice: CrowboxdbService, private sharesService: SharedService) {
  }

  //this function is invoked when a button is pressed in the view (HTML file)
  getUserId(){
    this.sharesService.useridMessage$.subscribe(x => {
      this.userId = x;
      console.log(this.userId);
    }  
    );
  }

update.component.html


<button (click)="getUserId()">Get User ID </button>
<h1>User Id is: {{userId}}</h1>

因此,当我尝试通过 auth.component.ts 文件中的sendUserData() 发送数据时,它可以正常工作。我也可以在控制台窗口中打印用户 ID。然而,在 update.component.ts 中,当我订阅 observable 时,我仍然收到“空”。这是否意味着它没有改变值?

我已经尝试在 ngOnInit() 两个 ts 文件中订阅 observable,但仍然没有返回正确的值。我错过了什么吗?我一直在关注this tutorial

编辑 1: 重要说明(我认为?),这两个组件也用作两条不同的路线。以下是 app-routing.module.ts

中设置的路由
const routes: Routes = [
  { path:'', component:TestUpdateComponent },
  { path:'auth', component:AuthComponentComponent }
];

【问题讨论】:

  • 为什么不能在sharedServe中使用getset方法?使用set 方法将用户ID 设置为sharedService,您可以在所有组件中订阅get。还是我错过了什么?
  • @Lenzman 我会试一试。但它本质上不是一样的吗?
  • 在您从 this.auth.authState 的回调中打印的 auth.component.ts 文件中,对吗?
  • 打印到控制台?不,我在 sendUserData() 函数中将用户 ID 打印到控制台。所以基本上我点击一个调用printUserId()的按钮,它在设置变量this.userId之后将它打印到auth组件的HTML文件{{userId}}
  • 我还应该补充一点,这两个组件在角度上是两条独立的路线。这会有所作为吗?

标签: angular observable angularfire angular-services


【解决方案1】:

问题实际上与我试图在不同路由中的组件之间共享数据的事实有关。因此,这些是不相关的组件,我无法使用标准的数据共享方法(例如,从父组件到子组件或在兄弟组件之间)。

我遵循this website 的第三个示例。我通过ng g s shared 命令创建了一个简单的服务。我将此服务导入到我的 app.module.ts 文件中,并将其作为providers 之一。

shared.service.ts 文件非常简单,我只想传递一个字符串:

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})

export class SharedService {

  public userId:any;

  constructor() { }
}

然后,在需要发送数据的文件 auth.component.ts 中,我有一个在单击按钮时执行的函数。此函数检查是否先前设置了相关字符串(在这种情况下由用户登录)。如果设置了字符串,则在提供程序文件中设置字符串并导航到接收器组件页面。

  //function is invoked by a button in the view page 
  sendUserData(){
    if (this.userId) {
      this.sharedService.userId = this.userId;
      this.router.navigate(['data']);
    } else {
      console.log("User Id has not been set");
    }
  }

为了接收 update.component.ts 中的数据,我有一个简单的函数,它也可以在单击按钮时执行:


  getUserId(){
    this.userId = this.sharesService.userId;
    console.log(this.userId);    
  }

这会打印出值。如果我没记错的话,这个方法还可以让所有可以访问这个特定提供者的组件全局使用这个变量。

【讨论】:

    【解决方案2】:

    嗯,我检查了你的代码,问题可能是由很多原因引起的,但我认为问题是你在多个模块中提供了这个服务。

    确保您仅在声明这两个组件的一个模块中或在app.module.ts 中提供此服务

    我的建议是创建一个components.module.ts 并在其中声明所有组件,以便您可以在任何需要的地方导入它。

    我还建议您在服务中声明一个公共变量,而不是这种令人困惑的 setter 和 getter,这样您就可以在任何地方更新它,它会在其他地方更新。

    【讨论】:

    • 嗨!感谢您浏览我的代码。两个组件都使用相同的服务,一切都通过app.module.ts 文件。我还没有任何其他模块文件。我会考虑将其更改为公共变量
    猜你喜欢
    • 2021-01-04
    • 2018-02-17
    • 2017-10-01
    • 2018-02-22
    • 2018-12-19
    • 2018-03-10
    • 2017-09-14
    • 1970-01-01
    • 2018-04-05
    相关资源
    最近更新 更多