【问题标题】:Server-side pagination using ngx-pagination使用 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
        });
      });
});

【问题讨论】:

    标签: node.js angular mongodb express mongoose


    【解决方案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.pagesizereq.query.page 吗?该解决方案应该在没有.limit 的情况下工作,但使用skiplimit 的其他解决方案也应该工作这只是一种不同的方法,但我觉得你的问题出在客户端。
    • 我修改了您的代码并添加了限制并使其正常工作,但我认为逻辑有问题。我现在每页只能得到 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
    猜你喜欢
    • 1970-01-01
    • 2021-11-01
    • 2018-02-12
    • 2019-03-16
    • 2018-01-21
    • 2010-10-31
    • 1970-01-01
    • 2019-09-27
    • 2016-05-04
    相关资源
    最近更新 更多