如何将异步管道过滤到Angular子组件

时间:2018-03-24 14:48:20

标签: javascript angular ngrx ngrx-store

TL,DR; 我已成功将Async Pipe的输出传递给子组件。但是当条件失败时(filter => false),我想从Observable传入先前发出的值。

详细;

使用Selectors,我订阅了两片@ngrx/store

export interface AppState {
  data: string[];
  pending: boolean;  // Are we waiting for a HTTP response?
  dirty: boolean;  // Has the data been edited locally?
}

...虽然上面有三个切片,但这个问题仅涉及dirtydata

减速器有三种情况:

  1. AppActions.GET_NEW_DATA:
    • pending设置为true以更新用户界面。
    • 正在进行HTTP请求(通过ngrx/effects)。
  2. AppActions.GET_NEW_DATA_SUCCESS:
    • pending设置为false以更新用户界面。
    • dirty设置为false,因为未进行任何修改。
  3. AppActions.EDIT_DATA:
    • 更新有效负载中提供的数据。
    • dirty设置为true,因为已进行了编辑。
  4. 代码:

    export function appReducer(state: AppState = initialState,
        action: AppActions.All
    ): AppState {
        switch (action.type) {
            case AppActions.GET_NEW_DATA:
                // Action results in HTTP request.
                return {
                    ...state,
                    pending: true
                };
            case AppActions.GET_NEW_DATA_SUCCESS:
                // HTTP response, update data!
                return {
                    data: action.payload,
                    pending: false,
                    pristine: true,
                };
            case AppActions.EDIT_DATA:
                return {
                    ...state,
                    data: action.payload,
                    pristine: false
                };
            default: {
              return state;
            }
         }
     }
    

    如前所述,使用Selectors,我在智能组件中订阅了两片@ngrx/store

    @Component({
      selector: 'app-smart',
      templateUrl: './smart.component.html',
      changeDetection: ChangeDetectionStrategy.OnPush
    })
    export class SmartComponent {
    
      public data$: Observable<string[]>;
      public dirty$: Observable<boolean>;
    
      constructor(private readonly store: Store<AppState>) {
          this.data$ = this.store.select(fromReducer.getData);
          this.dirty$ = this.store.select(fromReducer.getDirty);
      }
    }
    

    智能组件使用Async Pipe来检测何时从Observable发出新值并标记要检查更改的哑组件。

    <!-- From within <app-smart> -->
    <app-dumb [data]="data$|async"></app-dumb>
    

    这可以按预期工作,但是,我只想在dirtyfalse时更新 - 即,当发出新的HTTP请求并收到响应时。

    <app-dumb> Observable从编辑中发出更改时,我不想重绘data$。总之,我需要以下行为:

    创建时:

    • data$会发出新的价值。
      • dirty$false
      • 标记<app-dumb>以检查更改。

    编辑时:

    • data$会发出新的价值。
      • dirty$true
      • 请勿将<app-dumb>标记为要检查更改。

    这看起来像是梳理Observables的主要案例:

    this.data$ = this.store
      .select(fromReducer.getData)
      .withLatestFrom(this.dirty$)
      .filter(([_, dirty]) => !dirty)
      .map(([tree, _]) => tree);
    

    ......打破这个

    1. this.store.select(fromReducer.getData)使用ngrx/storeselectors抓取一个Observable。
    2. 新发布的 data$结果与来自dirty$最新结果相结合。
    3. 过滤dirty$是否为假。
      • 如果不脏,我们会从服务器获取新数据,并希望更新<app-dumb>
      • 如果脏,那么编辑会导致data$发出新值,我们应该忽略它。
    4. 问题是<app-smart>包含在Material Tab中,因此可以在用户切换标签时将其删除(ngOnDestroy)并重新创建(ngOnInit)。请参阅Life Cycle Hooks

      如果已进行编辑,则dirty$为真。如果用户随后切换标签并随后返回,则data$被过滤掉,因为dirty$true

      filter(([_, dirty]) => !dirty)

      我已成功将Async Pipe的输出传递给子<app-dumb>组件。但。当条件失败时,我想传递先前从data$发出的值 - 这是我可以在一些帮助下真正做到的。

1 个答案:

答案 0 :(得分:0)

尝试从脏的observable开始创建可观察的数据

this.data$ = this.store.select(fromReducer.getDirty)
.filter(dirty=>dirty)
.flatMap(()=>this.store.select(fromReducer. getData))

这样,如果脏通过过滤器

,你总是会收到新数据