2

当我尝试更改页面(小于)时,遵循 Angular 2 - Meteor分页说明给了我这个错误:pageSizetotalItems

    Exception in queued task: EXCEPTION: Error in client/components/entities/players/player-list.html:2:8
    ORIGINAL EXCEPTION: TypeError: Cannot read property 'type' of undefined
    ORIGINAL STACKTRACE:
    TypeError: Cannot read property 'type' of undefined
        at AppElement.detachView (http://localhost:3000/packages/modules.js?hash=fa01f730b3659d348eabf8ba338dffb7d96b4033:11331:17)
        at ViewContainerRef_.remove (http://localhost:3000/packages/modules.js?hash=fa01f730b3659d348eabf8ba338dffb7d96b4033:11531:34)
        at NgFor._bulkRemove (http://localhost:3000/packages/modules.js?hash=fa01f730b3659d348eabf8ba338dffb7d96b4033:21719:37)
        at NgFor._applyChanges (http://localhost:3000/packages/modules.js?hash=fa01f730b3659d348eabf8ba338dffb7d96b4033:21684:33)
        at NgFor.ngDoCheck (http://localhost:3000/packages/modules.js?hash=fa01f730b3659d348eabf8ba338dffb7d96b4033:21670:22)
        at DebugAppView._View_PlayerList0.detectChangesInternal (PlayerList.template.js:94:41)
        at DebugAppView.AppView.detectChanges (http://localhost:3000/packages/modules.js?hash=fa01f730b3659d348eabf8ba338dffb7d96b4033:12703:14)
        at DebugAppView.detectChanges (http://localhost:3000/packages/modules.js?hash=fa01f730b3659d348eabf8ba338dffb7d96b4033:12808:44)
        at DebugAppView.AppView.detectViewChildrenChanges (http://localhost:3000/packages/modules.js?hash=fa01f730b3659d348eabf8ba338dffb7d96b4033:12729:19)
        at DebugAppView._View_PlayersPage0.detectChangesInternal (PlayersPage.template.js:395:8)
    ERROR CONTEXT:
    [object Object]
    9debug.js:41 Exception in queued task: TypeError: Cannot read property 'splice' of null
        at MongoCursorObserver._removeAt (http://localhost:3000/packages/modules.js?hash=fa01f730b3659d348eabf8ba338dffb7d96b4033:77671:19)
        at removedAt (http://localhost:3000/packages/modules.js?hash=fa01f730b3659d348eabf8ba338dffb7d96b4033:77649:35)
        at http://localhost:3000/packages/modules.js?hash=fa01f730b3659d348eabf8ba338dffb7d96b4033:77364:20
        at ZoneDelegate.invoke (http://localhost:3000/packages/modules.js?hash=fa01f730b3659d348eabf8ba338dffb7d96b4033:124251:29)
        at Zone.run (http://localhost:3000/packages/modules.js?hash=fa01f730b3659d348eabf8ba338dffb7d96b4033:124144:44)
        at Object.removedAt (http://localhost:3000/packages/modules.js?hash=fa01f730b3659d348eabf8ba338dffb7d96b4033:77363:23)
        at removed (http://localhost:3000/packages/minimongo.js?hash=88217d643bc16fdf3505c6d4b2b8f5ddc400c49a:3745:28)
        at self.applyChange.removed (http://localhost:3000/packages/minimongo.js?hash=88217d643bc16fdf3505c6d4b2b8f5ddc400c49a:3674:44)
        at http://localhost:3000/packages/modules.js?hash=fa01f730b3659d348eabf8ba338dffb7d96b4033:77364:20
        at ZoneDelegate.invoke (http://localhost:3000/packages/modules.js?hash=fa01f730b3659d348eabf8ba338dffb7d96b4033:124251:29)

我的文件是他们教程的简化版本:

import { Component }   from '@angular/core';
import { Players } from '../../../../collections/players';
import { Mongo }       from 'meteor/mongo';
import { MeteorComponent } from 'angular2-meteor';
import { ReactiveVar } from 'meteor/reactive-var';
import { PaginationService, PaginatePipe, PaginationControlsCmp } from 'angular2-pagination';

@Component({
  selector: 'player-list',
  viewProviders: [PaginationService],
  templateUrl: 'client/components/entities/players/player-list.html',
  directives: [PaginationControlsCmp],
  pipes: [PaginatePipe]
})
export class PlayerList extends MeteorComponent{
  players: Mongo.Cursor<Party>;
  pageSize: number = 5;
  curPage: ReactiveVar<number> = new ReactiveVar<number>(1);
  nameOrder: number = 1;

  constructor() {
    super();

    this.autorun(() => {
      let options = {
        limit: this.pageSize,
        skip: (this.curPage.get() - 1) * this.pageSize,
        sort: { name: this.nameOrder }
      };

      this.subscribe('players', options, () => {
        this.players = Players.find({}, { sort: { name: this.nameOrder } });
      }, true);
    });
  }

  onPageChanged(page: number) {
    this.curPage.set(page);
  }
}

以及相关的 HTML:

<div>
  <ul>
    <li *ngFor="let player of players | paginate:{currentPage: 1, itemsPerPage: pageSize, totalItems: 14}">
      <p>{{player.name}}</p>
    </li>
  </ul>
  <pagination-controls (change)="onPageChanged($event.page)"></pagination-controls>
</div>

我已签入该publish函数以验证每次返回的文档数量是否正确。(.fetch().length用于正确衡量 的影响limit: 10

我试过 的我已经改变了:

this.players = Players.find({}, { sort: { name: this.nameOrder } });

至:

this.players = Players.find({}, { sort: { name: this.nameOrder } }).fetch();

这可以防止在更改分页页面时出现上述错误。

这会创建一个新的(非破坏性)错误,其中length集合在切换页面后从 5 变为 10 - 再次切换页面似乎使其保持在 10。好像订阅正在记住上次订阅调用中的文档,即使publish日志显示要返回的正确数量的文档。

问题

  1. 应该ngFor使用游标吗?如果是这样,什么可能导致错误发生?

  2. 订阅是否有理由记住以前的文档?我尝试存储订阅并调用stop(),但这导致界面出现故障。

4

1 回答 1

1

ngFor 应该使用游标吗?如果是这样,什么可能导致错误发生?

是的,它可以工作,但是它有问题。我之前创建了这个问题。但是现在它有时仍然是错误的。它发生在您使用sort.

原因似乎是因为当您使用Mongo.Cursorwithsort时,当这些项目的顺序发生变化时,它无法正确触发 Angular 2 的变更检测。您可以从您在问题中发布的错误中看到它。

并随时在 github 上创建问题并进行复制。

如果你有使用ngrx的应用程序状态或者你有自己的应用程序状态,通常我们保存Array在应用程序状态内部而不是Mongo.Cursor. 而应用状态中的数组可以帮助我们跟踪和发现问题,因为我们总是知道数组中有什么。

(一种特殊情况,当您有大量数据,可能有数千个项目时,您需要使用Mongo.Cursor避免使用Array,因为fetch()需要时间)

一个好消息是返回 Observable 的新 API 即将发布。没有更多的光标,在这里跟踪:https ://github.com/Urigo/angular2-meteor/pull/358

订阅是否有理由记住以前的文档?

查看我的演示Desugar Meteor、Angular 2、RxJS 5 和 ngrx第 34 页:

在此处输入图像描述

这就是 Meteor 的工作原理。如果您不停止订阅,并尝试再次订阅(注意相同的Collection,在您的情况下为PlayersCollection),旧数据仍将位于蓝色矩形中(在 Minmongo 中)。Meteor 会在蓝色矩形PlayersCollection)中添加新数据,所以蓝色矩形会越来越大)。

两种方式:

1)您已经尝试过的第一种方式。停止订阅。并再次订阅。这样,您将Players在 Minmongo 中清理 Collection。但不是一个很好的方法。它导致不必要stop的和resubscribe。它花费时间,使您的页面闪烁。

2)添加搜索条件:

Players.find({
  // add your search conditions here, limit to the data you need
}, { sort: { name: this.nameOrder } })

在演示页面 34 中,这意味着尽管您在 Minmongo 中有很多数据。但是您只需要黄色矩形部分的数据。

于 2016-07-28T03:44:42.257 回答