【问题标题】:ng2-bootstrap pagination pageChanged triggered multiple timesng2-bootstrap 分页 pageChanged 触发多次
【发布时间】:2016-05-06 23:53:59
【问题描述】:

我正在尝试使用 ng2-bootrap 在我的 angular2 应用程序中实现分页。我关注http://valor-software.github.io/ng2-bootstrap/#pagination

我的app.html

<div>
    <div class="col-lg-12 text-right">
        <pagination [totalItems]="totalItems" [itemsPerPage]='2' (pageChanged)="pageChanged($event)" [(ngModel)]="currentPage" [maxSize]="maxSize"
        class="pagination-sm" [boundaryLinks]="true"></pagination>
    </div>
</div>

我的组件

import { Component, View, Inject} from 'angular2/core';
import { CORE_DIRECTIVES } from 'angular2/common';
import { PAGINATION_COMPONENTS } from 'ng2-bootstrap/ng2-bootstrap';

// webpack html imports
@View({
    templateUrl: '/scripts/src/components/demo/demo.html',
    directives: [PAGINATION_COMPONENTS, CORE_DIRECTIVES]
})
@Component({
    selector: 'tabs-demo',
})
export class DemoComponent {
    private totalItems: number = 64;
    private currentPage: number = 4;

    private maxSize: number = 5;
    private bigTotalItems: number = 175;
    private bigCurrentPage: number = 1;

    private setPage(pageNo: number): void {
        this.currentPage = pageNo;
    };

    private pageChanged(event: any): void {
        console.log('Page changed to: ' + event.page);
        console.log('Number items per page: ' + event.itemsPerPage);
    };
}

它在不点击分页的情况下多次触发 pageChange 事件

【问题讨论】:

  • 我也有同样的问题。但是很奇怪,在demo页面上却可以正常运行...
  • 为什么会有totalItems 和bigTotalItems?我遇到了这个问题。

标签: pagination angular ng2-bootstrap


【解决方案1】:

每次更新组件的page 属性时,实际上都会触发该事件(这可以通过编程方式完成,无需来自 UI 的任何交互)。

其实这个事件在初始化pagination组件的时候触发了3次,原因如下:

  • 来自ngInit 方法。这是组件生命周期的一部分。

    export class Pagination implements ControlValueAccessor, OnInit, IPaginationConfig, IAttribute {
      (...)
    
      ngOnInit() {
        (...)
        this.page = this.cd.value;
        (...)
      }
    
      (...)
    }
    
  • 来自writeValue 方法。调用此方法是因为该组件符合 ngModel。当ngModel 中关联的表达式更新时,将使用新值调用此方法。在初始化期间,writeValue 方法被调用了两次:第一次使用 null 值,然后使用 1 值。

    export class Pagination implements ControlValueAccessor, OnInit, IPaginationConfig, IAttribute {
      (...)
    
      writeValue(value:number) {
        this.page = value;
        this.pages = this.getPages(this.page, this.totalPages);
      }
    
      (...)
    }
    

也就是说,在这个初始化阶段之后,pageChanged 只会在每次 page 更新时触发一次。

编辑

看了 ng2-bootstrap 的代码后,如果不更新 Pagination 组件的代码,我看不到该怎么做。

以下是您可以在本课程中进行的更新(文件 node_modules/ng2-bootstrap/components/pagination/pagination.ts):

  • 更新set page 块以仅在inited 属性为true 时触发事件:

    public set page(value) {
      this._page = (value > this.totalPages) ? this.totalPages : (value || 1);
    
      if (this.inited) { // <---------------
        this.pageChanged.next({
          page: this._page,
          itemsPerPage: this.itemsPerPage
        });
      }
    }
    
  • 更新 ngOnInit 方法,不要在其末尾将 inited 属性设置为 true:

    ngOnInit() {
      (...)
      //this.inited = true;
    }
    
  • writeValue的第一次调用结束时将inited属性设置为true:

    writeValue(value:number) {
      this.page = value;
      this.pages = this.getPages(this.page, this.totalPages);
    
      if (!this.inited) {
        this.inited = true;
      }
    }
    

这样pageChanged事件在分页初始化阶段只会被调用一次。

希望对你有帮助, 蒂埃里

【讨论】:

  • 我做了什么来阻止它,因为我的 http 调用被调用了 3 次
  • 我希望 pageChanged 仅在我点击分页时被调用
  • 有什么办法可以处理
  • 我查看了 ng2-bootstrap 的代码,如果不更新 Pagination 组件的代码,我看不到如何做到这一点。我计划提供一个补丁来改进这个...
  • 我更新了我的答案,以在 ng2-bootstrap 的 Pagination 类中提供一些更新,以倾向于您期望的行为...如果这能解决您的问题,请随时告诉我。
【解决方案2】:

如果您只想在用户点击分页时触发'pageChanged'事件,您可以将设置页面块更改为:

public set page(value) {
    var _previous = this._page;
    this._page = (value > this.totalPages) ? this.totalPages : (value || 1);
    if (_previous !== this._page && typeof _previous !== 'undefined') {
        this.pageChanged.emit({
            page: this._page,
            itemsPerPage: this.itemsPerPage
      });
    }
}

【讨论】:

    【解决方案3】:

    或者,您可以尝试自定义分页服务而不是 ng2 引导程序,我刚刚发布了 this pagination example,它使用了类似谷歌搜索结果的逻辑。

    PagerService 处理分页逻辑:

    import * as _ from 'underscore';
    
    export class PagerService {
        getPager(totalItems: number, currentPage: number = 1, pageSize: number = 10) {
            // calculate total pages
            var totalPages = Math.ceil(totalItems / pageSize);
    
            var startPage, endPage;
            if (totalPages <= 10) {
                // less than 10 total pages so show all
                startPage = 1;
                endPage = totalPages;
            } else {
                // more than 10 total pages so calculate start and end pages
                if (currentPage <= 6) {
                    startPage = 1;
                    endPage = 10;
                } else if (currentPage + 4 >= totalPages) {
                    startPage = totalPages - 9;
                    endPage = totalPages;
                } else {
                    startPage = currentPage - 5;
                    endPage = currentPage + 4;
                }
            }
    
            // calculate start and end item indexes
            var startIndex = (currentPage - 1) * pageSize;
            var endIndex = Math.min(startIndex + pageSize - 1, totalItems - 1);
    
            // create an array of pages to ng-repeat in the pager control
            var pages = _.range(startPage, endPage + 1);
    
            // return object with all pager properties required by the view
            return {
                totalItems: totalItems,
                currentPage: currentPage,
                pageSize: pageSize,
                totalPages: totalPages,
                startPage: startPage,
                endPage: endPage,
                startIndex: startIndex,
                endIndex: endIndex,
                pages: pages
            };
        }
    }
    

    AppComponent 使用分页服务:

    import { Component, OnInit } from '@angular/core';
    
    import * as _ from 'underscore';
    
    import { PagerService } from './_services/index'
    
    @Component({
        moduleId: module.id,
        selector: 'app',
        templateUrl: 'app.component.html'
    })
    
    export class AppComponent {
        constructor(private pagerService: PagerService) { }
    
        // dummy array of items to be paged
        private dummyItems = _.range(1, 151);
    
        // pager object
        pager: any = {};
    
        // paged items
        pagedItems: any[];
    
        ngOnInit() {
            // initialize to page 1
            this.setPage(1);
        }
    
        setPage(page: number) {
            if (page < 1) {
                return;
            }
    
            // get pager object from service
            this.pager = this.pagerService.getPager(this.dummyItems.length, page);
    
            // get current page of items
            this.pagedItems = this.dummyItems.slice(this.pager.startIndex, this.pager.endIndex + 1);
        }
    }
    

    AppComponent HTML,显示分页项和分页控件:

    <div>
        <div class="container">
            <div class="text-center">
                <h1>Angular 2 - Pagination Example with logic like Google</h1>
    
                <!-- items being paged -->
                <div *ngFor="let item of pagedItems">Item {{item}}</div>
    
                <!-- pager -->
                <ul *ngIf="pager.pages.length" class="pagination">
                    <li [ngClass]="{disabled:pager.currentPage === 1}">
                        <a (click)="setPage(1)">First</a>
                    </li>
                    <li [ngClass]="{disabled:pager.currentPage === 1}">
                        <a (click)="setPage(pager.currentPage - 1)">Previous</a>
                    </li>
                    <li *ngFor="let page of pager.pages" [ngClass]="{active:pager.currentPage === page}">
                        <a (click)="setPage(page)">{{page}}</a>
                    </li>
                    <li [ngClass]="{disabled:pager.currentPage === pager.totalPages}">
                        <a (click)="setPage(pager.currentPage + 1)">Next</a>
                    </li>
                    <li [ngClass]="{disabled:pager.currentPage === pager.totalPages}">
                        <a (click)="setPage(pager.totalPages)">Last</a>
                    </li>
                </ul>
            </div>
        </div>
    </div>
    

    this post 上提供了更多详细信息和工作演示。

    【讨论】:

      猜你喜欢
      • 2017-03-31
      • 2015-05-17
      • 1970-01-01
      • 2019-02-16
      • 2016-08-20
      • 1970-01-01
      • 2014-05-02
      • 2020-03-13
      • 1970-01-01
      相关资源
      最近更新 更多