【问题标题】:How to extract a property from an observable using a pipe如何使用管道从可观察对象中提取属性
【发布时间】:2017-08-10 20:27:24
【问题描述】:

我正在尝试在我的 ngrx 商店中存储一个 OrderState 对象。我遇到的问题是将数据从中提取到我的 UI。我只想使用异步管道从这个可观察对象中获取子属性。

order.state.ts

export interface OrderState {
    stage: number;
    postcode: string;
}

app.component.ts

...
export class AppComponent {
  counter: Observable<number>;
  readonly orderState$: Observable<OrderState>;

    constructor(
      private appStateStore: Store<AppState>,
      private counterActions: CounterActions,

      private orderStateStore: Store<OrderState>,
      private orderActions: OrderActions,
    ) {

    this.counter = appStateStore.select('counter');
    this.orderState$ = orderStateStore.select(store => store);
    }
...

app.component.html

<div>Stage: {{ (orderState$ | async)?.stage }}</div>

从我的orderstate 对象获取stage 属性所需的语法是什么。

如果我显示{{ orderState$ }},我只会在页面上显示[Object object]

我猜我可能没有从我的商店中正确选择?


更新:我必须在这里遗漏一些基本的东西。我现在已经这样做了,试图弄清楚发生了什么......

app.component.ts

stage: number

...

    this.orderStateStore.select(s => s).subscribe((data:OrderState) => {
      this.stage = data.stage;
      console.log(this.stage);
    });

app.component.html

<div>Stage: {{ stage }}</div>

我可以在控制台中看到我的那个阶段报告为未定义。我相信这与问题有关。出于某种原因,我无法在此箭头函数中设置组件的 stage


更新:这种行为看起来很奇怪...

order.state.ts

export interface OrderState {
    stage: number;
    postcode: string;
}

app.component.ts

...
this.orderStateStore.select(s => s).subscribe((data:OrderState) => {      
  console.log('--- START ---');
  console.log(data);
  console.log('Stage: ' + data.stage);
  console.log('--- END ---');
});
...

现在这是我在控制台中得到的...

如您所见,data 实际上不是OrderState 类型。它是OrderState 周围的包装器类型,称为AppState。好的,所以我修改我的代码以记录data.orderState.stage 以获取值1。但是,当我这样做时,TypeScript 抱怨 orderState 不是数据的属性——它显然是在查看控制台输出!

【问题讨论】:

  • {{ (orderState$ | async).stage }}
  • 遗憾的是没有。不知道我做错了什么。
  • 你应该用你的例子创建 plnkr

标签: angular typescript ngrx


【解决方案1】:

当您执行 {{ orderState$ }} 时,它会显示 [Object object],因为它将您的结果从异步管道(对象)转换为字符串。要使用管道拉出某个属性,您需要执行以下操作

 {{orderState$ | async | asyncField : 'stage'}}

管道的样子

 @Pipe({name: 'asyncField'})
 export class AsyncFieldPipe implements PipeTransform {
     transform(object, key: string){
        return object[key];
     }
 }

所以本质上你是在将结果从异步管道传递到这个管道并返回一个特定的字段。这是一个工作 plunkr https://plnkr.co/edit/mnsf9s2zxEypDiDDUzrp?p=preview


更新 - 作为管道的替代方案,您还可以使用 rjxs map 方法来限制从可观察序列返回的内容。我更喜欢这种方法,因为访问响应属性可能不像上述管道那么容易,在这种情况下,可能需要在 component.ts 中包含更复杂的转换函数

this.orderState$ = orderStateStore.select(store => store).map(res => res.stage);   

这是一个有效的 plunkr https://plnkr.co/edit/zbfuSBCLXwlMIhWCPf6z?p=preview

【讨论】:

  • @RemotecUk 这个管道的替代方法是在可观察序列 .map(res => res.stage) 的末尾添加一个 rjxs .map 函数现在 {{$orderState}} 将只输出舞台财产
  • 您能否在回答中提供一个示例来替代管道?谢谢。
  • 谢谢。显然我做错了什么,因为它没有将任何内容映射到 html 中的值。
  • @RemotecUk 尝试 console.logging 地图函数中的 res 以查看值发生了什么
  • 不需要创建管道来提取属性,只需使用括号:` {{ (orderState$ | async).stage }} `
【解决方案2】:

看来我是从 ngrx 商店中选择错误的错误。

错误

this.orderState$ = orderStateStore.select(store => store);

正确

this.orderState$ = appStateStore.select(x => x.orderState);

回想起来,这很明显。我的想法是你可以切入你想要的商店。作为参考,我的商店对象如下:

app.state.ts

export interface AppState {
  counter: number;

  orderState : OrderState;
}

order.state.ts

export interface OrderState {
    stage: number;
    postcode: string;
}

OrderStateAppState 的“子”存储。在我的情况下,我仍然需要引用 appStateStore,但使用 => 函数从对象中检索 orderState

【讨论】:

    【解决方案3】:

    只需这样做: {{(orderState$ | async).stage}}

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-24
      • 1970-01-01
      • 2014-10-23
      • 1970-01-01
      • 2018-10-27
      • 1970-01-01
      • 1970-01-01
      • 2017-09-07
      相关资源
      最近更新 更多