子组件 Angular 17 中的输入主题为空

问题描述 投票:0回答:1

我正在尝试将数据从 Angular 17 中的父组件传递到其子组件。 通过获取项目数组的 API 从后端检索数据。

在我的父组件中,items$ 是一个主题:

items$ = Subject<Array<Item>> = new Subject();

我订阅了从后端检索所有项目的服务方法:

ngOnInit(){
    this.itemService.getItems().subscribe(this.items$);
}

在我的 parent.html 模板中,此代码确实显示有项目:

@if(items$ | async){
"There are items!"
}@else{
"There aren't any items"
}

然后我调用我的子组件:

@if(items$ | async){
<app-child [items$]=items$>
}

这就是我的 child.component.ts 的样子:

export class ChildComponent implements OnInit{
@Input() items$: Observable<Array<Item>>;

ngOnInit(){
this.items$.subscribe();
}
}

一个 child.component.html:

@if(items$ | async){
"There are items in the child component!"
}@else{
"There aren't any items in the child component"
}

嗯,它显示子组件中没有任何项目。

我知道我不需要订阅子组件的 onInit() 方法,但我真的只是想确保我确实订阅了我的多播可观察对象。

此外,有趣的是,当我将子组件从 parent.html 中的 @if 条件中取出时,项目正在显示!

知道为什么吗?如何根据项目的存在来调节子组件的显示?

angular rxjs observable angular17 subject
1个回答
0
投票

您可以将

Subject
转换为
BehaviorSubject
,以便它保持状态(数组)。当您想要触发不保持状态的事件(事件总线)的发射时,首选主题。

您还应该在订阅中编写一个回调,使用 API 中的数据调用

next
BehaviorSubject
方法。

itemService = inject(ItemService);
items$: BehaviorSubject<Array<any> | null> =
  new BehaviorSubject<Array<any> | null>(null);

ngOnInit() {
  this.itemService.getItems().subscribe((data: any) => {
    this.items$.next(data);
  });
}

完整代码:

import { Component, inject, Injectable, Input, OnInit } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import { Observable, of, Subject, BehaviorSubject } from 'rxjs';
import { CommonModule } from '@angular/common';

@Injectable({ providedIn: 'root' })
export class ItemService {
  getItems() {
    return of([{ test: 1 }]);
  }
}

@Component({
  selector: 'app-child',
  imports: [CommonModule],
  template: `
    @if(items$ | async) {
      "There are items in the child component!"
    } @else {
      "There aren't any items in the child component"
    }
  `,
})
export class ChildComponent implements OnInit {
  @Input() items$!: Observable<Array<any> | null>;

  ngOnInit() {
    this.items$.subscribe();
  }
}

@Component({
  selector: 'app-root',
  imports: [CommonModule, ChildComponent],
  template: `
    @if(items$ | async){
      "There are items!"
    }@else{
      "There aren't any items"
    }
    <hr/>
    @if(items$ | async) {
      <app-child [items$]="items$"/>
    }
  `,
})
export class App {
  itemService = inject(ItemService);
  items$: BehaviorSubject<Array<any> | null> =
    new BehaviorSubject<Array<any> | null>(null);

  ngOnInit() {
    this.itemService.getItems().subscribe((data: any) => {
      this.items$.next(data);
    });
  }
}

bootstrapApplication(App);

Stackblitz 演示

© www.soinside.com 2019 - 2024. All rights reserved.