你如何在路由器导航后强制 ngFor 重新运行? (Angular 2)

How do you force ngFor to re-run after router navigation? (Angular 2)

使用以下路由定义:

export const routes: Routes = [
  { path: '', redirectTo: '/home', pathMatch: 'full' },
  { path: 'home', component: GeneralComponent },
  { path: 'test', component: TestComponent }
];

export const routing: ModuleWithProviders = RouterModule.forRoot(routes);

我在作为 "home" 加载序列的一部分加载的模块中设置了以下 for 循环:

<div *ngFor="let row of rows; let i = index">
  <div class="rows">
    <div *ngFor="let coach of row">
      <bio [coach]='coach'></bio>
    </div>
  </div>
</div>

这由后端的一个简单组件支持:

export class TeamListingComponent implements OnInit {
  rows: Array<Array<Coach>>;

  constructor(private service: CoachListingService) { }

  ngOnInit () {
    this.rows = this.service.get();
  }
}

初始页面加载到 .../home 时,一切看起来都很好。

如果我导航到 .../test 然后返回到 .../home,for 循环似乎不会被触发。 HTML-only 内容加载正常,但 for 循环提供的内容不会呈现。 (在 JS 控制台中没有报告错误)。

我已经确认 "this.rows" 已正确重置并且在 return 行程中有内容并且服务似乎按预期工作并且非 "for loop" HTML 在组件中加载并完全按照预期呈现。

版本:

*ng --version*
angular-cli: 1.0.0-beta.24
node: 7.0.0
os: darwin x64
@angular/common: 2.4.10
@angular/compiler: 2.4.10
@angular/core: 2.4.10
@angular/forms: 2.4.10
@angular/http: 2.4.10
@angular/platform-browser: 2.4.10
@angular/platform-browser-dynamic: 2.4.10
@angular/router: 3.4.10
@angular/compiler-cli: 2.4.10

更新:

根据下面列出的建议使用 NgZone 模块的方法的评论,我查看了帖子和随后的 NgZone API 页面,并将以下内容添加到相关组件中:

constructor(private service: CoachListingService, private zone: NgZone) {
  this.zone.runOutsideAngular(() => {
    this._updateList(() => {
    console.log(this.rows);
      this.zone.run(() => { console.log('Forcing re-draw', this.rows); });
    });
  });
}

ngOnInit () {
  this.rows = this.service.get();
}


_updateList (doneCallback: () => void) {
  this.rows = this.service.get();
}

这个好像没有效果。我确定我没有正确考虑这个问题。

我后来更改了“_updateList”以调用回调:

_updateList (doneCallback: () => void) {
  this.rows = this.service.get();
  doneCallback();
}

它确实在 javascript 控制台中显示了正确的输出。所以数据是存在的。

想法?

TIA

该服务应该 return 一个可观察的,并且您应该在模板中使用异步管道。这将确保在值更改时更新视图。 (注意:'$' 后缀是我用于可观察对象的命名约定。)

export class TeamListingComponent implements OnInit {
  rows$: Observable<Array<Array<Coach>>>;

  constructor(private service: CoachListingService) { }

  ngOnInit () {
    this.rows$ = this.service.getRows$();
  }
}

模板:

<div *ngFor="let row of rows$ | async; let i = index">

我不知道你的服务中发生了什么,但如果它只是简单地获取和设置,你可以使用 rxjs 主题,如下所示:

@Injectable()
export class CoachListingService {
  private rowsSubject = new Subject<Array<Array<Coach>>>();
  private _rows$ = this.rowsSubject.asObservable();

  getRows$() {
    return this._rows$;
  }

  setRows(rows: Array<Array<Coach>>) {
    this.rowsSubject.next(rows);
  }
}

你绝对不应该去搞乱 NgZone 之类的东西。