在模板中绑定时未找到 Observable 的属性

Properties on Observable aren't being found when bound to in template

我正在调用来自 NGXS 状态的数据,当我 console.log() 显示时,它以用于描述它的界面的形式存在。有一个 items 属性 是一个包含 3 个对象的数组,我想在我的模板中对其进行迭代。但是,当我定位 items 属性 时,我在 vsCode 中收到错误消息,告诉我 属性 在该类型上不存在,并且屏幕上没有任何内容。

我的状态模型是这样的

export interface CattegoryIndexItem{
    cattegory: string;
    products: ProductIndexListItem[];
}

export interface ProductIndexListModel{ items: CattegoryIndexItem[]; }

我的组件看起来像这样

export class ProductPageComponent implements OnInit {

  @Select() productIndexState$: Observable<ProductIndexListModel>;

  constructor(private store: Store) {}

  ngOnInit(): void {
    this.store.dispatch(new GetProductIndexList());

  }

  showData(){
    this.productIndexState$.subscribe(res => console.log(res));
  }

}

在我的模板中

<article *ngFor="let item of productIndexState$.items | async">
    <p>{{item.cattegory}}</p>
</article>

<button (click)="showData()">click</button>

页面加载时出现此错误

error TS2339: Property 'items' does not exist on type 'Observable'.

我在使用 observables 时从未遇到过这个问题,NGXS 是否有什么让我们需要以不同的方式访问它?

看起来像是模板语法中的一个小故障 - 无法在 Observable 本身上调用 .items,您想在 Observable 发出的对象上调用它。

所以您需要先通过 async 传送 Observable,例如

<ng-container *ngIf="productIndexState$ | async as productIndexState">
    <article *ngFor="let item of productIndexState.items">
        <p>{{item.cattegory}}</p>
    </article>

    <button (click)="showData()">click</button>
</ng-container>

很高兴给出的答案已经有所帮助。

我想在这里回答你的评论,只是为了补充这个答案。

您问:现在发生这种情况的原因是什么?

现在发生的事情是这样的:

您的方法 showData() 调用对 observable 本身的订阅并解包它。这应该具有您的界面结构。这个界面然后有项目 属性.

模板中的异步管道

<article *ngFor="let item of productIndexState$.items | async">
    <p>{{item.cattegory}}</p>
</article>

在另一个站点上,目标不是可观察对象本身,而是项目 属性。这在这里还不存在,也不是异步可以处理的有效可观察对象。

async pipe of Angular 的工作方式类似于 showData() 中的订阅。它接受包裹在可观察对象中的任何内容,并使其可用于处理。

@Garth Mason 在他的回答中所做的是首先调用可观察对象的异步 "unwrap" 它并使用别名 as 给它一个合适的名称(没有$).展开的对象包含您正在寻找的项目,现在可以通过 ngfor 对其进行迭代。

再次引用他的代码以便更好地参考:

<ng-container *ngIf="productIndexState$ | async as productIndexState">
    <article *ngFor="let item of productIndexState.items">
        <p>{{item.cattegory}}</p>
    </article>

    <button (click)="showData()">click</button>
</ng-container>

只是对包装您的标签的 ng-container 的补充评论。 Angular 只允许 single directive like ngFor or ngIf on a tag. Therefor, whenever you need to do two "Angular process steps" within your template, you need something to do the first step (the ng-container here) 然后你的实际标签 () 执行第二步。 ng-container 没有标记,因此在您的 HTML 中不可见。这就是为什么包装这样的处理步骤是完美的 ;-)