Angular 11-如何使用服务可观察到的数据

发布于 2025-02-03 22:18:33 字数 2269 浏览 3 评论 0原文

我的目标是将可观察到的从父组件传递给其子女,我无法使用“输入”和“输出”来做到这一点,因为包含子组件的组件本身就是用于用户接口的内部库的组成部分。

我有一个父亲组成部分:home.com.ponente.ts

在父级组件中,我调用oninit事件中的服务,然后将其响应存储在“主题”类型中以存储可观察的可观察到,以便我可以订阅儿童组件:

this.tabs = [            
   {id: 'reportsTab', label: 'Files', routerLink: '/reports/1'},
   {id: 'processesTab', label: 'Tasks', routerLink: '/processes/1'},
];
ngOnInit(): void {
    this.processesService.getInfo(id).subscribe(response => { 
        this.processesService.data.next(response);
    });
}

这是proceses.service.ts服务:

export class ProcessesService {
    data: Subject<RestResponse<ScheduleDataOutput[]>> = new Subject();
    
    public getInfo(id: number): Observable<RestResponse<ScheduleDataOutput[]>> {
      let serviceName = "/processes/info";
      if (id) {
        serviceName = serviceName + '?id=' + id;
      }
      return this.service.get<any>(serviceName)
      .pipe(
        tap(_ => this.log('fetched info')),
        catchError(this.handleError<ScheduleDataOutput[]>('getInfo', []))
      );
    }
    
    getData() {
        return this.data.asObservable()
    }
}

在home.component.html文件中,我们具有内部组件,它是使用经典选项卡的UI组件,每个选项卡都是子组件:

<app-menu-tab [tabs]="tabs"></app-menu-tab>

当,当我单击一个选项卡时, ,它具有一个加载子组件的路由器链接,我想通过在家庭成分中获得的响应(可观察到),订阅儿童组件中可观察到的响应,并随着该响应在子部件中绘制datagrid。

当我正确加载子分量组件中获得的响应的屏幕时,如果我正确加载了屏幕的屏幕,则问题是,当我单击选项卡时,datragrids未加载。

这是“报告站”选项卡组件的OnInit事件:

ngOnInit(): void {
    // Here I access
    this.reportsSubscription = this.processesService.getData().subscribe(response => {
        // But within the subscription I do not access.
        console.log("response: ", response)
    });
}

问题是我无法在订阅中访问,在某个时候,可观察到的可观察到的情况是错误的,当我单击“ processEstab”选项卡的子组件时也会发生同样的情况。标签,我无法访问可观察到的订阅:

ngOnInit(): void {
    // Here I access
    this.tasksSubscription = this.processesService.getData().subscribe(response => {
        // But within the subscription I do not access.
        console.log("response: ", response)
    });
}

问题是什么?如果我将可观察到的孩子的组件传递给了孩子,但是当我重新加载页面时,它只能工作并加载数据杂志,但是如果我单击“选项卡”,我会将失去在homecorment中获得的响应,并且数据杂志出现为空。

My goal is to pass an observable from a parent component to its children, I can't do it using "Input" and "Output" because the component that contains the child components is itself a component of an internal library for user interfaces.

I have a father component: home.componente.ts

In the parent component HomeComponent, I call a service from the OnInit event and store its response in a "Subject" type to store an observable so I can subscribe to child components:

this.tabs = [            
   {id: 'reportsTab', label: 'Files', routerLink: '/reports/1'},
   {id: 'processesTab', label: 'Tasks', routerLink: '/processes/1'},
];
ngOnInit(): void {
    this.processesService.getInfo(id).subscribe(response => { 
        this.processesService.data.next(response);
    });
}

This is the processes.service.ts service:

export class ProcessesService {
    data: Subject<RestResponse<ScheduleDataOutput[]>> = new Subject();
    
    public getInfo(id: number): Observable<RestResponse<ScheduleDataOutput[]>> {
      let serviceName = "/processes/info";
      if (id) {
        serviceName = serviceName + '?id=' + id;
      }
      return this.service.get<any>(serviceName)
      .pipe(
        tap(_ => this.log('fetched info')),
        catchError(this.handleError<ScheduleDataOutput[]>('getInfo', []))
      );
    }
    
    getData() {
        return this.data.asObservable()
    }
}

In the home.component.html file, we have the inner component, it's a UI component for to use the classic sistem of tabs, and each tab is a child component:

<app-menu-tab [tabs]="tabs"></app-menu-tab>

When, I click on a tab, it has a routerLink that loads the child components, to which I want to pass the response (observable) obtained in HomeComponent, subscribe to the observable in the child component and with that response paint a Datagrid in the child components.

When refreshing the screen if I correctly load the Datagrids of the childs components with the response obtained in the HomeComponent component, the problem is that when I click on the tabs the Datragrids are not loaded.

This is the OnInit event of the "reportsTab" tab component:

ngOnInit(): void {
    // Here I access
    this.reportsSubscription = this.processesService.getData().subscribe(response => {
        // But within the subscription I do not access.
        console.log("response: ", response)
    });
}

The issue is that I cannot access within the subscription, at some point the observable was misconfigured, the same happens with the child component of the "processesTab" tab, when I click on the tab, I cannot access the subscription of the observable:

ngOnInit(): void {
    // Here I access
    this.tasksSubscription = this.processesService.getData().subscribe(response => {
        // But within the subscription I do not access.
        console.log("response: ", response)
    });
}

What could be the problem? If I am passing the observable to the childs components, but it only works and loads the Datagrids, when I reload the page, but if I click on the tabs, I lose the response obtained in the HomeComponent and the Datagrids appear empty.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

盛装女皇 2025-02-10 22:18:33

您需要使用cistionubject(或replaysubject,如果您不需要初始值),而不是普通的主题

capenionSubject将发出新订户的最新值,而主题不会做到这一点。

为了使订户从主题中获取数据,需要在发出数据之前对其进行订阅。

简而言之,数据属性应该看起来像这样:

data = new BehaviorSubject<RestResponse<ScheduleDataOutput[]>>(null);

或者,如果初始值是多余的,则可以使用replosaySubject而选择:

data = new ReplaySubject<RestResponse<ScheduleDataOutput[]>>(1);

You need to use a BehaviorSubject (or a ReplaySubject if you don't need an initial value), not a plain Subject.

The BehaviorSubject will emit the latest value to new subscribers, while Subject won't do that.

In order for a subscriber to get the data emitted from a subject, it needs to be subscribed to it prior to the data being emitted.

In short, the data property should look like this:

data = new BehaviorSubject<RestResponse<ScheduleDataOutput[]>>(null);

Or, if the initial value is superfluous, you could go with a ReplaySubject instead:

data = new ReplaySubject<RestResponse<ScheduleDataOutput[]>>(1);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文