角插值未在订阅上更新

时间:2018-08-05 02:01:35

标签: angular ngrx angular-changedetection

  • 角度6.0.1
  • ngRx 6.0.1

我在视图中设置了一个插值:

{{firstName}}

绑定字段的值更改时,它不会更新。值正在更改-如果我将其注销到订阅内的控制台,则会看到更新后的值。它只是不会在用户界面中更新。

以下是相关代码:

从我的组件中订阅:

private subscribeToCurrentPerson(): void {
    this.tState$ = this.store
      .pipe(select(selectors.getCurrentPerson), takeWhile(() => this.componentActive))
      .subscribe((cp: Person) => {
        if (cp) {
          const name: string = cp.primaryName.value.parsedValue.givenNames[0];
          this.firstName = name;
          console.log('name: ' + name);  // <-- this shows correct new value
        }
  });
}
从组件的ngOnInit中调用

subscribeToCurrentPerson。在此之前,firstName属性是未定义的。

selectors.getCurrentPerson选择器如下所示:

export const getCurrentPerson: MemoizedSelector<{}, Person> = 
    createSelector(getTState, (tState: ITState) => {
      console.log('selector: ', tState); // <-- this logs the correct new value
      return tState ? tState.currentPerson : null;
    });  

从选择器返回的currentPerson值是一个新创建的对象。这是在应用程序的首次运行时发生的,因此在此之前,tState是未定义的。

如果我在构造函数中注入ChangeDetectorRef并在订阅中调用cdr.detectChanges(),则UI会更新。但是在我看来,我通常不需要像这样使用ChangeDetectorRef,它应该“可以正常工作”。

我认为问题是我的嵌套属性(cp.primaryName.value.parsedValue.givenNames)。我从非ngRx项目继承了这些实体,但我认为下一步是尝试展平该结构,以查看这是否使ngRx和Angular变化检测器更快乐。

还有其他我想念的东西吗?

谢谢

TTE

更新

我已经通过简单地更新订阅中我的组件上的本地属性来去除了嵌套的属性。所以subscribeToCurrentPerson函数现在看起来像这样:

private subscribeToCurrentPerson(): void {
        this.tState$ = this.store
          .pipe(select(selectors.getCurrentPerson), takeWhile(() => this.componentActive))
          .subscribe((cp: Person) => {
            this.myProp = 'goodbye';
            this['newProp'] = 'world';
      });
    }

myProp是我为测试添加的组件上的现有属性。 除非通过订阅中的方括号符号添加newProp,否则它不存在。结果如下:

  • myProp未更新-它显示了我在声明时为其分配的值。但是,如果在声明属性时未分配值,则在订阅中分配的值会正确显示在UI中。
  • newProp 已正确显示在界面中

我现在完全困惑。 似乎一旦属性具有值,就不会在UI中对其进行更新,即使该值本身确实发生了变化(我可以通过在更新该值后登录控制台来判断)。

我没有为组件明确设置ChangeDetectionStrategy,所以它是Default

如果我致电detectChanges,一切都会正常,但是我认为这不是必需的。

2 个答案:

答案 0 :(得分:3)

当父组件的更改检测策略设置为OnPush时,尽管此父对象及其子级的ngOnChanges方法仍在使用中,但是angular的更改检测机制不会检查该父组件的树。每次@Input属性更改时都会调用。要让angular知道该树中的某些组件需要更新,请将ChangeDetectorRef注入该组件,并使用其API通知angular有关更新,例如detectChangesmarkForCheck

答案 1 :(得分:0)

很多时候,组件的数据更新不会反映HTML模板。在这种情况下,可以将插值与三元运算符一起使用。

 {{firstName ? firstName : ''}}

对我有用。希望这会成功