【问题标题】:How to use an ngrx selector that has a parameter that depends on another selector如何使用具有依赖于另一个选择器的参数的ngrx选择器
【发布时间】:2019-09-22 17:43:57
【问题描述】:

我正在尝试使用一个 ngrx 选择器,该选择器采用 jobId 的属性来将一些数据作为可观察对象返回。

我首先从数据库加载所有作业和任务,但它们没有及时返回选择器,并且我收到错误,因为 this.task 未定义,我认为这会阻止可观察对象运行再次。

有没有办法在选择器尝试从存储中获取数据之前等待数据返回?

this.store.dispatch(fromTasks.loadAllTasks());
this.store.dispatch(fromJobs.loadAllJobs());

taskSubscription$ = this.store.pipe(
	select(fromTask.getSelectedTask),
	tap(task => this.task = task)).subscribe()

jobSubscription$ = this.store.pipe(
	select(fromJob.getJobById, {jobId: this.task.jobId}),
	tap(job => this.job = job)).subscribe();

【问题讨论】:

    标签: angular rxjs ngrx


    【解决方案1】:

    这是您可以考虑的一种方法:

    1) 选择器getSelectedTask 如果没有选择任务则返回null

    export const getSelectedTask = createSelector(
      selectEntities,
      getSelectedTaskId,
      (entities: Dictionary<Task>, selectedId: number) => {
        return selectedId ? entities[selectedId] : null;
      }
    )
    

    2) 在模板内使用async 管道和*ngIf

    组件.ts

    @Component({
      selector: 'my-component',
      ...
    })
    export class MyComponent {
      selectedTask$ = this.store.pipe(select(getSelectedTask));
    ...
    }
    

    模板.html

    <ng-container *ngIf="selectedTask$ | async as selectedTask else noSelection">
    
      <my-task [task]="selectedTask"></my-task>
      // or 
      <span>{{ selectedTask.description }}</span>
    
    </ng-container>
    
    <ng-template #noSelection>
      Please select a task !
    </ng-template>
    

    通过这种方法,您将使用带有角度模板语法的强大的可观察对象。 如果用户取消选择当前任务,getSelectedTask 选择器将返回null,模板将自动更新。

    尽管如此,您可以继续使用subscription,但在这种情况下,最好在subscribe 方法中设置值并确保取消订阅。

    @Component({
      selector: 'my-component',
      ...
    })
    export class MyComponent implements OnInit, OnDestroy {
      subscription: Subscription;
      selectedTask$ = this.store.pipe(select(getSelectedTask));
      selectedTask: Task;
    
      constructor(
        private store: Store<AppState>
      ) { }
    
      ngOnInit() {
        this.subscription = this.selectedTask$.subscribe(task 
          => this.selectedTask = task);
      }
    
      ngOnDestroy() {
        this.subscription.unsubscribe();
      }
    }
    

    【讨论】:

    • 感谢您的回答。如果选择器返回 null,那么它在尝试执行点击操作时是否仍然会导致问题?
    • 在哪些tap操作中?您应该避免将逻辑放在 tap 运算符或 subscribe 中。更喜欢创建一个新的selector,例如getSelectedJobs,它将返回当前所选任务的所有作业。在这种情况下,您将能够测试getSelectedIdgetSelectedTask,然后也为getSelectedJobs 返回null。所以你的*ngIf 在这种情况下也能完美运行。希望它会有所帮助。
    【解决方案2】:

    你可以尝试使用 RxJS 过滤器。

    taskSubscription$ = this.store.pipe( select(fromTask.getSelectedTask), filter(task => !!task), tap(task => this.task = task)).subscribe()

    【讨论】:

    • 这可以工作,但缺点是如果以后没有更多选择的任务,this.task 将不会分配给null,在这种情况下,不会通知组件。
    • 谢谢!这似乎有效,但我不确定为什么。你能解释一下 !! 任务在做什么吗?
    • !!task 的意思是“不是不是任务”。它相当于task !==undefined &amp;&amp; task !== null。在这种情况下,正如 Thierry Falvo 所写,this.task 不会分配给null。如果需要'null',您可以明确写task !=='undefined' 或使用他的解决方案。我希望你成功!
    猜你喜欢
    • 2012-01-30
    • 2020-10-09
    • 2019-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多