ng2-bootstrap pagination pageChanged多次触发

时间:2016-01-29 09:43:03

标签: pagination angular ng2-bootstrap

我正在尝试使用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事件而不点击分页

enter image description here

3 个答案:

答案 0 :(得分:1)

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

事实上,由于以下原因,在初始化pagination组件时会触发此事件三次:

    来自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;
    }
    
  • inited的第一次调用结束时将writeValue属性设置为true:

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

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

希望它可以帮到你, 亨利

答案 1 :(得分:1)

如果您只想在用户点击分页时触发'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
      });
    }
}

答案 2 :(得分:0)

或者您可以尝试使用自定义分页服务而不是ng2 bootstrap,我刚刚发布了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上提供了更多详细信息和工作演示。