Meteor Angular 2 无法使用分页教程
Meteor Angular 2 cannot get pagination tutorial working
在 Angular 2 - Meteor instructions for pagination 之后,当我尝试更改页面时出现此错误(pageSize
小于 totalItems
):
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
函数以验证每次 return 编辑的文档数量是否正确。 (使用 .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
日志显示 return.
的正确文档数
问题
ngFor
应该使用游标吗?如果是,是什么原因导致错误发生?
请问为什么订阅会记住以前的文档?我尝试存储订阅并调用 stop()
,但这导致界面出现故障。
Should ngFor work with cursors? If so, what could be causing the
errors to occur?
是的,它可以工作,但是它有错误。我之前创建了 this issue。但现在它有时仍然是越野车。当您使用 sort
.
时会发生这种情况
原因似乎是因为当您将 Mongo.Cursor
与 sort
一起使用时,当这些项目的顺序发生变化时,它无法正确触发 Angular 2 的更改检测。你可以从你在问题中发布的错误中看到它。
并随时在 github 上创建问题并复制。
如果您有使用 ngrx 的应用状态或您有自己的应用状态,通常我们会在应用状态中保存 Array
而不是 Mongo.Cursor
。 Array in app state 帮助我们跟踪和发现问题,因为我们总是知道数组中有什么。
(一个特例,当你有大量的数据,可能有几千条时,你需要使用Mongo.Cursor
避免使用Array
因为fetch()
需要时间)
好消息是新的 API which return Observable 即将发布。没有更多的光标,在这里跟踪:https://github.com/Urigo/angular2-meteor/pull/358
Is there a reason why the subscription is remembering the previous
documents?
查看我的演示文稿 Desugar Meteor, Angular 2, RxJS 5, and ngrx 第 34 页:
这就是 Meteor 的工作原理。如果您不停止订阅,并尝试再次订阅(注意相同的 Collection,在您的情况下,Players
Collection),旧数据将仍在 蓝色矩形(在 Minmongo 中)。 Meteor 会在blue rectangle(Players
Collection)中添加新数据,所以蓝色矩形会越来越大。
两种方式:
1) 您已经尝试过的第一种方法。停止订阅。下次再订阅。这样您将清理 Minmongo 中的 Players
集合。但不是一个很好的方法。它会导致不必要的 stop
和 resubscribe
。它花费时间,使您的页面闪烁。
2) 添加搜索条件:
Players.find({
// add your search conditions here, limit to the data you need
}, { sort: { name: this.nameOrder } })
在演示文稿第34页,这意味着虽然你在Minmongo中有很多数据。但是你只需要黄色矩形部分数据。
在 Angular 2 - Meteor instructions for pagination 之后,当我尝试更改页面时出现此错误(pageSize
小于 totalItems
):
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
函数以验证每次 return 编辑的文档数量是否正确。 (使用 .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
日志显示 return.
问题
ngFor
应该使用游标吗?如果是,是什么原因导致错误发生?请问为什么订阅会记住以前的文档?我尝试存储订阅并调用
stop()
,但这导致界面出现故障。
Should ngFor work with cursors? If so, what could be causing the errors to occur?
是的,它可以工作,但是它有错误。我之前创建了 this issue。但现在它有时仍然是越野车。当您使用 sort
.
原因似乎是因为当您将 Mongo.Cursor
与 sort
一起使用时,当这些项目的顺序发生变化时,它无法正确触发 Angular 2 的更改检测。你可以从你在问题中发布的错误中看到它。
并随时在 github 上创建问题并复制。
如果您有使用 ngrx 的应用状态或您有自己的应用状态,通常我们会在应用状态中保存 Array
而不是 Mongo.Cursor
。 Array in app state 帮助我们跟踪和发现问题,因为我们总是知道数组中有什么。
(一个特例,当你有大量的数据,可能有几千条时,你需要使用Mongo.Cursor
避免使用Array
因为fetch()
需要时间)
好消息是新的 API which return Observable 即将发布。没有更多的光标,在这里跟踪:https://github.com/Urigo/angular2-meteor/pull/358
Is there a reason why the subscription is remembering the previous documents?
查看我的演示文稿 Desugar Meteor, Angular 2, RxJS 5, and ngrx 第 34 页:
这就是 Meteor 的工作原理。如果您不停止订阅,并尝试再次订阅(注意相同的 Collection,在您的情况下,Players
Collection),旧数据将仍在 蓝色矩形(在 Minmongo 中)。 Meteor 会在blue rectangle(Players
Collection)中添加新数据,所以蓝色矩形会越来越大。
两种方式:
1) 您已经尝试过的第一种方法。停止订阅。下次再订阅。这样您将清理 Minmongo 中的 Players
集合。但不是一个很好的方法。它会导致不必要的 stop
和 resubscribe
。它花费时间,使您的页面闪烁。
2) 添加搜索条件:
Players.find({
// add your search conditions here, limit to the data you need
}, { sort: { name: this.nameOrder } })
在演示文稿第34页,这意味着虽然你在Minmongo中有很多数据。但是你只需要黄色矩形部分数据。