使用 ngx-pagination 的服务器端分页
Posted
技术标签:
【中文标题】使用 ngx-pagination 的服务器端分页【英文标题】:Server-side pagination using ngx-pagination 【发布时间】:2020-05-01 10:40:05 【问题描述】:我让 ngx-pagination 模块与 GET 中的所有列表一起工作,但我希望分页也能在服务器端工作,但我不确定如何进一步实现它。我正在查看 ngx-pagination 的文档,但我有点困惑。这就是我所拥有的。
html代码
<body [ngClass]="[(this.isOpen && this.mobile) || (this.isOpen && this.tablet) ? 'hideContent' : 'showContent']">
<div class="loading">
<!-- <mat-spinner class="loader" *ngIf="isLoading"></mat-spinner> -->
<ngx-spinner id="loadingIcon" *ngIf="isLoading" type="cog" size="large" color="#3071a9">
<p class="loadingTitle">Loading...</p>
</ngx-spinner>
</div>
<div class="spacing"></div>
<div class="container">
<div class="row no-gutters"
*ngIf="!this.isOpen && this.mobile || this.isOpen && !this.mobile || !this.isOpen && !this.mobile">
<div class="class col-md-7"></div>
</div>
<!-- /|slice:0:show -->
<!--; let i = index-->
<div class="row"
*ngFor="let auction of posts | paginate: itemsPerPage: 10, currentPage: p, totalItems: this.posts.count ">
<div class="col-md-12 col-centered">
<div class="listingCard" [@simpleFadeAnimation]="'in'">
<div class=container>
<div class="row">
<div class="col-md-3">
</div>
<div class="col-md-6">
<div id="title">auction.title</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<pagination-controls (pageChange)="p = $event"></pagination-controls>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
</head>
<body [ngClass]="[(this.isOpen && this.mobile) || (this.isOpen && this.tablet) ? 'hideContent' : 'showContent']">
<div class="loading">
<!-- <mat-spinner class="loader" *ngIf="isLoading"></mat-spinner> -->
<ngx-spinner id="loadingIcon" *ngIf="isLoading" type="cog" size="large" color="#3071a9">
<p class="loadingTitle">Loading...</p>
</ngx-spinner>
</div>
<div class="spacing"></div>
<div class="container">
<div class="row no-gutters"
*ngIf="!this.isOpen && this.mobile || this.isOpen && !this.mobile || !this.isOpen && !this.mobile">
<div class="class col-md-7"></div>
</div>
<!-- /|slice:0:show -->
<!--; let i = index-->
<div class="row"
*ngFor="let auction of posts | paginate: itemsPerPage: 10, currentPage: p, totalItems: this.posts.count ">
<div class="col-md-12 col-centered">
<div class="listingCard" [@simpleFadeAnimation]="'in'">
<div class=container>
<div class="row">
<div class="col-md-3">
</div>
<div class="col-md-6">
<div id="title">listing.title</div>
</div>
</div>
</div>
=
</div>
</div>
</div>
</div>
<pagination-controls (pageChange)="p = $event"></pagination-controls>
</body>
.ts 文件组件
p: number = 1;
ngOnInit()
this.submitListingService.getListings(this.postsPerPage, this.currentPage);
this.listingService
.getPostUpdateListener()
.pipe(takeUntil(this.destroy))
.subscribe((postData: listing: Listing[]; postCount: number ) =>
this.isLoading = false;
this.totalPosts = postData.postCount;
this.posts = postData.listing;
this.filteredPosts = postData.listing;
);
角度服务
getListings(postsPerPage: number, currentPage: number)
let listings = "Get Listings";
const params = new HttpParams().set("listings", listings);
const queryParams = `?pagesize=$postsPerPage&page=$currentPage`;
this.http
.get< message: string; posts: any; maxPosts: number >(
"http://localhost:3000/api/listings" + queryParams,
params
)
.pipe(
map(postData =>
return
posts: postData.posts.map(post =>
return
title: post.title,
id: post._id
;
),
maxPosts: postData.maxPosts
;
)
)
.pipe(takeUntil(this.destroy))
.subscribe(transformedPostData =>
this.posts = transformedPostData.posts;
this.postsUpdated.next(
listing: [...this.posts],
postCount: transformedPostData.maxPosts
);
);
-> 服务器代码 app.js
app.get("/api/listings", (req, res, next) =>
Post.find( auctionEndDateTime: $gte: Date.now() )
.populate("creator", "username")
.then(documents =>
req.params.Id = mongoose.Types.ObjectId(req.params.Id);
res.status(200).json(
message: "Auction listings retrieved successfully!",
posts: documents
);
);
);
【问题讨论】:
【参考方案1】:这是另一种方法。 这可能更适合您的情况。
Post.find( auctionEndDateTime: $gte: Date.now() )
.populate("creator", "username")
.then(documents =>
req.params.Id = mongoose.Types.ObjectId(req.params.Id);
let per_page = req.query.pagesize;
let page = req.query.page || 1;
let offset = (page - 1) * per_page;
res.status(200).json(
message: "Auction listings retrieved successfully!",
posts: documents.slice(offset).slice(0,
per_page)
);
);
这是使用slice
的另一种方法
var skip = req.query.pagesize * (req.query.page - 1)
Post.where('auctionEndDateTime').gte(Date.now()).slice([skip, req.query.pagesize])
.populate("creator", "username")
.then(documents =>
res.status(200).json(
message: "Auction listings retrieved successfully!",
posts: documents
);
)
【讨论】:
我目前有 32 个列表。当我添加您的代码时,它会抓取所有这些而不是前 10 个。如果我添加 .limit(10) 那么我只会在分页中获得页码1
。如果使用 .limit(),则没有第 2 页及以后的选项。我需要它一次只抓取 10 个,同时显示我目前不在的所有页面。这是我更新的代码pastebin.com/vJbzF3wB
服务器端有req.query.pagesize
和req.query.page
吗?该解决方案应该在没有.limit
的情况下工作,但使用skip
和limit
的其他解决方案也应该工作这只是一种不同的方法,但我觉得你的问题出在客户端。
我修改了您的代码并添加了限制并使其正常工作,但我认为逻辑有问题。我现在每页只能得到 10 个项目,它会像我想要的那样从服务器中获取下一页。在我的 32 个列表示例中,当我到达第 4 页时,它有 10 个项目,当我单击返回第 3 页时,它有最后 2 个?我的后端代码中有什么东西会导致这种情况吗?更新代码:pastebin.com/qdmL25CP.
不太清楚为什么,但是您编辑的解决方案破坏了我在前端的代码。我加载了您的更改,控制台说v.parent.context.$implicit.watchingGroup is undefined"
(这是列表应该返回的值)pastebin.com/ap7uuzx1
您不需要第一个解决方案中的代码,只需发送文档即可【参考方案2】:
服务器端需要两个值,一个是页面,即显示哪个页码,第二个是限制,即在页面上显示多少结果。 然后只需使用:
.skip(limit * (page - 1)).limit(limit)
第一个操作员将跳过不需要的结果,例如:如果页面为 2,限制为 20,那么在第一个操作中,前 20 个结果将被跳过,然后在第二个操作中,我们将结果限制为 20 个结果,因此您将获得文档 21到 40,这是期望的结果。
【讨论】:
虽然这确实将页面限制在我设置的任何限制。比如说 10,它只显示 10 并且 ngx-paginator 变成灰色。我如何限制它,但仍然能够获得下一页的下 10 个。【参考方案3】:您的服务文件,
getListings(postsPerPage: number, currentPage: number)
// let listings = "Get Listings";
// const params = new HttpParams().set("listings", listings);
// const queryParams = `?pagesize=$postsPerPage&page=$currentPage`;
const queryParams = postsPerPage+"/"+currentPage; //change this .
this.http
.get< message: string; posts: any; maxPosts: number >(
"http://localhost:3000/api/listings/" + queryParams
)
.pipe(
map(postData =>
return
posts: postData.posts.map(post =>
return
title: post.title,
id: post._id
;
),
maxPosts: postData.maxPosts
;
)
)
.pipe(takeUntil(this.destroy))
.subscribe(transformedPostData =>
this.posts = transformedPostData.posts;
this.postsUpdated.next(
listing: [...this.posts],
postCount: transformedPostData.maxPosts
);
);
当您发送参数时,您需要更改 API 的 URL,如下我在服务器代码中提到的,
您的服务器代码如下,
app.get("/api/listings/:postPerPage/:currentPage", (req, res, next) =>
let postPerPage = req.params.postPerPage;
let currentPage = req.params.currentPage;
Post.find( auctionEndDateTime: $gte: Date.now() )
.populate("creator username")
.skip(postPerPage * currentPage)
.limit(postPerPage)
.then(documents =>
req.params.Id = mongoose.Types.ObjectId(req.params.Id);
res.status(200).json(
message: "Auction listings retrieved successfully!",
posts: documents
);
);
);
从上面的代码你会得到帖子等于 postPerPage 。 希望这是您要找的。谢谢你
【讨论】:
我添加了您的代码,目前有 12 个列表。所以最后 2 个应该在第 2 页上可用,但是 ngx-paginator 已将任何选项显示为灰色,但第 1 页。我无法转到第 2 页。如果我注释掉 .limit(),那么我可以看到第 2 页,但我不能去。我输出了单击分页器上的下一步按钮的值,它说应该是 2,但我不在第 2 页上,除非我刷新页面,否则我不能回到 1。 (点击分页器时列表永远不会改变)这是对html的引用pastebin.com/9pzVidJ6以上是关于使用 ngx-pagination 的服务器端分页的主要内容,如果未能解决你的问题,请参考以下文章
ngx-pagination:Angular 6 服务器端实现