كيفية إنشاء ترقيم الصفحات (pagination) بواسطة Angular

 الطريقة هذه تكون إما من خلال الواجهة الأمامية وذلك للبيانات القليلة أو من خلال الواجهة الخلفية وذلك للبيانات الضخمة، أما هنا فنحن نتحدث عن عن الواجهة الأمامية فقط:

ملف الـ HTML:

<div [dir]="translateService.currentLang === 'ar'? 'rtl':'ltr'">
    <h2 mat-dialog-title>{{'BUTTONS.CARDS_HISTORY' | translate}}</h2>
    <mat-divider></mat-divider>
    <mat-dialog-content class="mat-typography">

        <div class="row d-flex justify-content-center">

            <div class="col-12 grid-margin stretch-card min-max-height-for-history">
                <div class="card">
                    <div class="card-body">
                        <h4 class="card-title">{{'LABELS.PRE_PRINTED_CARDS' | translate}}</h4>
                        <p class="card-description">
                            {{'LABELS.DIRECTLY' | translate}}
                        </p>

                        <div class="col-12">
                            <mat-form-field appearance="outline" class="w-100">
                                <mat-label>{{'SEARCH_ENGINE.BUTTON' | translate}}</mat-label>
                                <input #search matInput                                
                                    [placeholder]="'SEARCH_ENGINE.PLACEHOLDER_CARDS_HISTORY' | translate" type="text"
                                    [(ngModel)]="searchInput"
                                    (keyup)="searchEngine()"
                                    >
                                <button *ngIf="searchInput" matSuffix mat-icon-button aria-label="Clear"
                                    (click)="searchInput=''">
                                    <mat-icon>close</mat-icon>
                                </button>
                                <mat-icon [matTooltip]="'SEARCH_ENGINE.BUTTON' | translate"
                                    *ngIf="search.value.length === 0" class="icon-color" matSuffix>search</mat-icon>
                            </mat-form-field>
                        </div>
                        <div class="table-responsive">
                            <table style="width: 1000px !important;" class="table">
                                <thead>
                                    <tr>
                                        <th class="text-center"><b>{{'LABELS.EMPLOYEE_NAME' | translate}}</b></th>
                                        <th class="text-center"><b>{{'LABELS.EMPLOYEE_ID' | translate}}</b></th>
                                        <th class="text-center"><b>{{'LABELS.MODIFIED_AT' | translate}}</b></th>
                                        <th class="text-center"><b>{{'LABELS.ACTIONS' | translate}}</b></th>
                                    </tr>
                                </thead>
                                <tbody>
                                    <tr *ngFor="let item of pageSlice">
                                        <td class="text-center">{{translateService.currentLang === 'ar'?
                                            item.ar_employee_name:item.en_employee_name}}</td>
                                        <td class="text-center">{{item.employee_id}}</td>
                                        <td class="text-center cursor-pointer" [matTooltip]="('TOOLTIPS.LAST_UPDATE_BY' | translate) + item.modified_by">
                                            {{item.modified_at | date: 'dd/MM/yyyy - HH:mm:ss'}}</td>
                                        <td class="text-center"><label class="link-primary cursor-pointer">{{'BUTTONS.CARD_REUSE' | translate}}</label></td>
                                </tbody>
                            </table>
                            <nav *ngIf="items.length > 0" class="d-flex justify-content-center" aria-label="...">
                                <ul *ngIf="search.value.length === 0" class="pagination">
                                    <li [matTooltip]="'PAGINATOR.PREVIOUS_PAGE_LABEL' | translate" [class]="currentPage == 1? 'page-item disabled' : 'page-item cursor-pointer'">
                                        <span class="page-link text-uppercase"
                                            (click)="changePageForPrevious(currentPage)">{{'BUTTONS.PREVIOUS' |
                                            translate}}</span>
                                    </li>

                                    <li *ngFor="let i of pages"
                                        [class]="(i == currentPage)? 'page-item text-uppercase active cursor-pointer':'page-item text-uppercase cursor-pointer'">
                                        <a class="page-link" (click)="changePage(i)">{{i}}</a>
                                    </li>

                                    <li [matTooltip]="'PAGINATOR.NEXT_PAGE_LABEL' | translate"
                                        [class]="currentPage == pages[pages.length -1]? 'page-item text-uppercase disabled' : 'page-item text-uppercase cursor-pointer'">
                                        <a class="page-link" (click)="changePageForNext(currentPage)">{{'BUTTONS.NEXT' |
                                            translate}}</a>
                                    </li>
                                </ul>
                            </nav>
                        </div>
                    </div>
                </div>
            </div>

        </div>



    </mat-dialog-content>
    <mat-dialog-actions align="end">
        <button mat-button mat-dialog-close>{{'BUTTONS.CLOSE' | translate}}</button>
        <!-- <button mat-button [mat-dialog-close]="true" cdkFocusInitial>Install</button> -->
    </mat-dialog-actions>
</div>


محتوى ملف الـ ts

import { Component } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { EmployeeCard } from 'src/app/models/employee-cards';
import { EmployeeCardsService } from 'src/app/services/employee-cards.service';

@Component({
  selector: 'app-employee-cards-history-dialog',
  templateUrl: './employee-cards-history-dialog.component.html',
  styleUrls: ['./employee-cards-history-dialog.component.scss']
})
export class EmployeeCardsHistoryDialogComponent {
  items: EmployeeCard[] = [];
  public pageSlice: EmployeeCard[] = [];

  public searchInput: string = '';
  public currentPage: number = 1;
  public pageSize: number = 3;
  public startItem: number = 0;
  public endItem: number = 3;

  public totalPage: number = 0;

  public pages: any = [];

  constructor(private employeeCardsService: EmployeeCardsService,
    public translateService: TranslateService) { }

  ngOnInit() {
    this.employeeCardsService.history().subscribe(res => {
      this.items = res;
      this.totalOfPages();
      this.pageSlice = res.slice(this.startItem, this.endItem);
    });
  }

  searchEngine() {
    this.pages = [];
    if (this.searchInput != "") {
      this.items = [];
      this.employeeCardsService.history()
        .subscribe((resp) => {
          this.items = resp;
          this.pageSlice = resp
            .filter((a: EmployeeCard) =>
              a.ar_employee_name.includes(this.searchInput.toUpperCase()) ||
              a.en_employee_name.includes(this.searchInput.toUpperCase()) ||
              a.mobile.includes(this.searchInput.toUpperCase()) ||
              a.employee_id.includes(this.searchInput.toUpperCase())
            );
          this.totalOfPages();
        });
    } else {
      this.clear();
    }
  }

  public changePage(pageNumber: any) {//رقم الصفحة -1
    this.currentPage = pageNumber;
    let pageIndex = Number(pageNumber) - 1;
    this.startItem = pageIndex * this.pageSize;
    this.endItem = this.startItem + this.pageSize;
    this.pageSlice = this.items.slice(this.startItem, this.endItem);
  }
  public changePageForPrevious(pageNumber: number) {
    this.currentPage = Number(pageNumber) - 1;
    let pageIndex = Number(this.currentPage) - 1;
    this.startItem = pageIndex * this.pageSize;
    this.endItem = this.startItem + this.pageSize;
    this.pageSlice = this.items.slice(this.startItem, this.endItem);
  }


  public changePageForNext(pageNumber: number) {
    this.currentPage = Number(pageNumber) + 1;
    let pageIndex = Number(this.currentPage) - 1;
    this.startItem = pageIndex * this.pageSize;
    this.endItem = this.startItem + this.pageSize;
    this.pageSlice = this.items.slice(this.startItem, this.endItem);
  }


  totalOfPages() {
    this.totalPage = 0;
    this.pages = [];
    for (let i = 0; i < this.items.length; i++) {
      if (((i + 1) % this.pageSize) === 0) {
        this.totalPage++;
        this.pages.push(this.totalPage.toString());
      }
    }
  }

  public clear() {
    this.searchInput = '';
    this.employeeCardsService.history().subscribe(res => {
      this.items = res;
      this.totalOfPages();
      this.pageSlice = res.slice(this.startItem, this.endItem);
      this.totalOfPages();
    });
  }

}


محتوى ملف الـ Scss


.flex {
    -webkit-box-flex: 1;
    -ms-flex: 1 1 auto;
    flex: 1 1 auto
}

@media (max-width:991.98px) {
    .padding {
        padding: 1.5rem
    }
}

@media (max-width:767.98px) {
    .padding {
        padding: 1rem
    }
}

.padding {
    padding: 5rem
}

.card {
    box-shadow: none;
    -webkit-box-shadow: none;
    -moz-box-shadow: none;
    -ms-box-shadow: none
}

.pl-3,
.px-3 {
    padding-left: 1rem !important
}

.card {
    position: relative;
    display: flex;
    flex-direction: column;
    min-width: 0;
    word-wrap: break-word;
    background-color: #fff;
    background-clip: border-box;
    border: 1px solid #d2d2dc;
    border-radius: 0
}

.card .card-title {
   color: #000000;
   margin-bottom: 0.625rem;
   text-transform: capitalize;
   font-size: 0.875rem;
   font-weight: 500;
}

.card .card-description {
   margin-bottom: .875rem;
   font-weight: 400;
   color: #76838f;
}

p {
   font-size: 0.875rem;
   margin-bottom: .5rem;
   line-height: 1.5rem;
}

.table-responsive {
   display: block;
   width: 100%;
   overflow-x: auto;
   -webkit-overflow-scrolling: touch;
   -ms-overflow-style: -ms-autohiding-scrollbar;
}

.table, .jsgrid .jsgrid-table {
   width: 100%;
   max-width: 100%;
   margin-bottom: 1rem;
   background-color: transparent;
}

.table thead th, .jsgrid .jsgrid-table thead th {
   border-top: 0;
   border-bottom-width: 1px;
   font-weight: 500;
   font-size: .875rem;
   text-transform: uppercase;
}

.table td, .jsgrid .jsgrid-table td {
   font-size: 0.875rem;
   padding: .875rem 0.9375rem;
}

.badge {
   border-radius: 0;
   font-size: 12px;
   line-height: 1;
   padding: .375rem .5625rem;
   font-weight: normal;
}


-----------------------------------------------------------------------------------------------------------------------

الطريقة الجديدة وبكل ساطة كالتالي:

  constructor(private employmentApplicationsService: EmploymentAplicationsService,
    private breakpointObserver: BreakpointObserver,
    private ahsaVillagesService: AhsaVillagesService,
    private jobsService: JobsService,
    private qualificationsService: QualificationsService,
    private paginatorIntl: MatPaginatorIntl,
    public translateService: TranslateService,
    public dialog: MatDialog,
    private smsMessagesService: SmsMessagesService,
    public snackBarService: SnackBarService,
  ) {
    if (this.translateService.currentLang === 'ar') {
      this.paginatorIntl.itemsPerPageLabel = 'العناصر لكل صفحة';
      this.paginatorIntl.firstPageLabel = 'الصفحة الأولى';
      this.paginatorIntl.lastPageLabel = 'الصفحة الأخيرة';
      this.paginatorIntl.nextPageLabel = 'الصفحة التالية';
      this.paginatorIntl.previousPageLabel = 'الصفحة السابقة';
      this.paginatorIntl.getRangeLabel = this.getRangeDisplayText;
    } else {
      this.paginatorIntl.itemsPerPageLabel = 'Items per page';
      this.paginatorIntl.firstPageLabel = 'First Page';
      this.paginatorIntl.lastPageLabel = 'Last Page';
      this.paginatorIntl.nextPageLabel = 'Next Page';
      this.paginatorIntl.previousPageLabel = 'Previous Page';
      this.paginatorIntl.getRangeLabel = this.getRangeDisplayTextEn;
    }
  }


  getRangeDisplayText = (page: number, pageSize: number, length: number) => {
    length = this.length;
    const initialText = '';  // customize this line
    if (length == 0 || pageSize == 0) {
      return `${initialText} 0 من ${length}`;
    }
    length = Math.max(length, 0);
    const startIndex = page * pageSize;
    const endIndex = startIndex < length
      ? Math.min(startIndex + pageSize, length)
      : startIndex + pageSize;
    return `${initialText}  من ${startIndex + 1} إلى ${endIndex} المجموع الكلي ${this.length}`; // customize this line
  }

  getRangeDisplayTextEn = (page: number, pageSize: number, length: number) => {
    length = this.length;
    const initialText = '';  // customize this line
    if (length == 0 || pageSize == 0) {
      return `${initialText} 0 from ${length}`;
    }
    length = Math.max(length, 0);
    const startIndex = page * pageSize;
    const endIndex = startIndex < length
      ? Math.min(startIndex + pageSize, length)
      : startIndex + pageSize;
    return `${initialText}  from ${startIndex + 1} to ${endIndex} of ${this.length}`; // customize this line
  }


المرجع:

https://g.co/gemini/share/872a335303e0













تعليقات

المشاركات الشائعة من هذه المدونة

ngx-extended-pdf-viewer

how to getting access token for https://fcm.googleapis.com/v1/projects/al-ayahya-co/messages:send for angular and backend nestjs

طريقة تفعيل زر Inline Keyboard في Telegram Bot