Mat paginator with checkbox not working properly in angular 8

556 views Asked by At

I have data within Mat table with pagination and checkbox where i can select master checkbox to select or deselect checkboxes at a time. My issue is when i'm on 1st page and mastercheckbox is selected ,everything seems to work properly like all the checkbox of each page are selected and is i deselect any checckbox it remains as it is,but when i select master checkbox other than 1st page it doesnot select all checkboxes on previous page .

componet.html

            <div class="order-table">
                <table mat-table [dataSource]="dataSource" (matSortChange)="sortTable($event)" matSort
                    class="app-table ">
                    <ng-container matColumnDef="select">
                        <th mat-header-cell *matHeaderCellDef>
                            <mat-checkbox [(ngModel)]="masterCheckboxSelected"
                                (ngModelChange)="masterCheckBoxSelection()"
                                [checked]="selection.hasValue() && isAllSelected()" color="primary">
                            </mat-checkbox>
                        </th>
                        <td mat-cell *matCellDef="let row; let i = index;">
                            <div class="checkbox-class">
                                <mat-checkbox (ngModelChange)="rowSelection(row, i)" [ngModel]="row.selected"
                                    color="primary">
                                </mat-checkbox>
                            </div>
                        </td>
                    </ng-container>
                    <ng-container matColumnDef="po_number">
                        <th mat-header-cell *matHeaderCellDef mat-sort-header="po_number">PO#
                            <div class="sort-indicator" [ngClass]="{ desc: sortDirection }">
                                {{ sortIndicator('po_number') }}
                            </div>
                        </th>
                        <td mat-cell *matCellDef="let element">{{element.po_number}} </td>
                    </ng-container>
                    <ng-container matColumnDef="message">
                        <th mat-header-cell *matHeaderCellDef mat-sort-header="message"> Message
                            <div class="sort-indicator" [ngClass]="{ desc: sortDirection }">
                                {{ sortIndicator('message') }}
                            </div>
                        </th>
                        <td mat-cell *matCellDef="let element"> {{element.message}} </td>
                    </ng-container>
                    <ng-container matColumnDef="vendor">
                        <th mat-header-cell *matHeaderCellDef mat-sort-header="vendor">Vendor
                            <div class="sort-indicator" [ngClass]="{ desc: sortDirection }">
                                {{ sortIndicator('vendor') }}
                            </div>
                        </th>
                        <td mat-cell *matCellDef="let element"> {{element.vendor}} </td>
                    </ng-container>

                    <ng-container matColumnDef="vendor_number">
                        <th mat-header-cell *matHeaderCellDef mat-sort-header="vendor_number">Vendor#
                            <div class="sort-indicator" [ngClass]="{ desc: sortDirection }">
                                {{ sortIndicator('vendor_number') }}
                            </div>
                        </th>
                        <td mat-cell *matCellDef="let element"> {{element.vendor_number}} </td>
                    </ng-container>

                    <ng-container matColumnDef="shopNumber">
                        <th mat-header-cell *matHeaderCellDef mat-sort-header="shopNumber">Shop#
                            <div class="sort-indicator" [ngClass]="{ desc: sortDirection }">
                                {{ sortIndicator('shopNumber') }}
                            </div>
                        </th>
                        <td mat-cell *matCellDef="let element"> {{element.shopNumber}} </td>
                    </ng-container>


                    <ng-container matColumnDef="po_date">
                        <th mat-header-cell *matHeaderCellDef mat-sort-header="po_date">PO Date
                            <div class="sort-indicator" [ngClass]="{ desc: sortDirection }">
                                {{ sortIndicator('po_date') }}
                            </div>
                        </th>
                        <td mat-cell *matCellDef="let element"> {{element.po_date}} </td>
                    </ng-container>
                    <ng-container matColumnDef="edit">
                        <th mat-header-cell *matHeaderCellDef>Edit</th>
                        <td mat-cell *matCellDef="let element"><a (click)="onEditClick(element)"
                                style="color:#4980B3">Edit</a></td>
                    </ng-container>
                    <ng-container matColumnDef="delete">
                        <th mat-header-cell *matHeaderCellDef>Delete</th>
                        <td mat-cell *matCellDef="let element">
                            <button mat-raised-button class="btn order-delete" color="danger"
                                (click)="onDeleteClick(element)" data-bs-toggle="modal"
                                data-bs-target="#deleteModal">Delete</button>
                        </td>
                    </ng-container>
                    <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
                    <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>

                </table>

                <mat-paginator center="align" (page)="onPaginateChange($event)" [hidePageSize]="true"
                    [length]="totalRecords" [pageSize]="pageSize" showFirstLastButtons
                    [pageIndex]="poErrorRequestObj?.pageNo" class="mat-paginator mat-paginator-center"
                    aria-label="Select page of periodic elements">
                </mat-paginator>
            </div>

Component.ts

import { SelectionModel } from '@angular/cdk/collections';
import { Component, OnInit, ViewChild } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { MatPaginator, PageEvent } from '@angular/material/paginator';
import { MatSort, Sort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table';
import { DatePipe } from '@angular/common'
import { PoErrorsSearchDialogComponent } from '../po-errors-search-dialog/po-errors-search-dialog.component';
import { ActivatedRoute, Router } from '@angular/router';
import { PoErrorsService } from 'src/app/ordermanagement/services/po-errors.service';
import { HttpResponse } from '@angular/common/http';
import { mySaveSearch, poErrorData, poErrorsObject } from 'src/app/ordermanagement/models/po-errors';
import { Location } from '@angular/common';
import { SRSUser, SRSUserService } from 'srs-user-lib';
import { uniqBy } from 'lodash';

@Component({
  selector: 'app-po-errors',
  templateUrl: './po-errors.component.html',
  styleUrls: ['./po-errors.component.scss']
})
export class PoErrorsComponent implements OnInit {

  isButtonEnable: boolean = true;
  selection = new SelectionModel<poErrorData>(true, []);
  purchaseOrders: poErrorData[] = [];
  mySaveSearchData: mySaveSearch[] = [];
  isDeleteClicked: boolean;
  poErrorRequestObj: poErrorsObject = {
    message: '',
    order: '',
    orderBy: '',
    pageNo: 0,
    pageSize: 10,
    po_number: '',
    vendor: '',
    vendor_number: ''
  };
  @ViewChild(MatSort) sort: MatSort;
  @ViewChild(MatPaginator) paginator: MatPaginator;
  @ViewChild('savedSearchPaginator') mySavedSearchPaginator: MatPaginator;
  displayedColumns: string[] = ['select', 'po_number', 'message', 'vendor', 'vendor_number',
    'shopNumber', 'po_date', 'edit', 'delete'];
  mySaveSearchDisplayedColumns: string[] = ['name', 'addDate', 'select', 'delete']
  dataSource = new MatTableDataSource(this.purchaseOrders);
  currentSortColumn = 'select';
  sortDirection = true;
  showClearSearchButton: boolean;
  totalRecords: number;
  mySaveSearchTotalRecords: number;
  message: any;
  poErrorDeleteData: any[] = [];
  isCheckBoxSelected: boolean = false;
  mySaveSearchDataSource: any[] = [];
  pageSize = 10;
  pageNo = 0
  mySavedSearchDeleteId: number
  public changeTabIndex;
  editedSearchName: {};
  mySaveSearchList: any[] = [];
  counter: number = 0;
  currentPage = 0;
  currentOrderBy = "po_date";
  currentOrder = "desc"
  isMySaveSearchEnable: boolean = false;
  mySaveSearchId: number;
  srsUser: SRSUser = undefined;
  userProfileId: number;
  
  masterCheckboxSelected = false;
  selectedRows = [];
  unSelectedRows = [];
  userNavigatePages = {0: 1};
  isAllCheckFlag:string='N';

  constructor(
    private dialog: MatDialog,
    private _poService: PoErrorsService,
    private srsUserService: SRSUserService,
    private activatedRoute: ActivatedRoute,
    private router: Router,
    private location: Location,
    public datepipe: DatePipe
  ) {
     this.selection.changed.subscribe(item => {
      this.isButtonEnable = this.selection.selected.length == 0;
     })
  }

  ngOnInit(): void {
    this.srsUserService.getUser().subscribe(user => {
      this.srsUser = user;
      this.userProfileId=this.srsUser.employeeId;
    });
    this.getPoErrorData();
    this.dataSource.paginator = this.paginator;

    if(this.location.getState()['statusCode']){
      this.message = { statusCode: this.location.getState()['statusCode'], 
        statusText: this.location.getState()['statusText'] };
      
      this.getPoErrorData();
    }
  }
  ngAfterViewInit() {

    this.dataSource.sort = this.sort;
  }
  // METHOD TO DISPLAY PO ERROR DATA IN TABLE
  getPoErrorData() {
    // this.selection.clear();
    this.purchaseOrders = []

    let filterCriteria = null;

    if (this.location.getState() && this.location.getState()['filterCriteria']) {
      filterCriteria = this.location.getState()['filterCriteria'];
      this.currentOrder = filterCriteria['order'];
      this.currentOrderBy = filterCriteria['orderBy'];
      this.showClearSearchButton = true;
    }

    this.poErrorRequestObj.po_number = filterCriteria ? filterCriteria['po_number'] : this.poErrorRequestObj?.po_number || '';
    this.poErrorRequestObj.vendor = filterCriteria ? filterCriteria['vendor'] : this.poErrorRequestObj?.vendor || '';
    this.poErrorRequestObj.vendor_number = filterCriteria ? filterCriteria['vendor_number'] : this.poErrorRequestObj?.vendor_number || '';
    this.poErrorRequestObj.message = filterCriteria ? filterCriteria['message'] : this.poErrorRequestObj?.message || '';
    this.poErrorRequestObj.pageNo = this.currentPage;
    this.poErrorRequestObj.pageSize = 10;
    this.poErrorRequestObj.order = this.currentOrder;
    this.poErrorRequestObj.orderBy = this.currentOrderBy;

    if (this.poErrorRequestObj.vendor ||
      this.poErrorRequestObj.vendor_number ||
      this.poErrorRequestObj.po_number ||
      this.poErrorRequestObj.message
    ) {
      this.showClearSearchButton = true;
    }

    this.getPoData();
  }

  /**
   * set poErrorRequestObj then,
   * just the API call
   */
  getPoData() {
    this._poService.getPoErrorListData(this.poErrorRequestObj).subscribe(result => {
      this.purchaseOrders = result.vendorOrderPOs;
      this.totalRecords = result.totalRecords;

      this.purchaseOrders?.forEach(element => {
        const findRowToMakeSelected = this.selectedRows?.find(data => data.id == element.id);
        if (findRowToMakeSelected) {
          element['selected'] = true;
        } else {
          // element['selected'] = false;
          if (this.userNavigatePages[this.currentPage] == 1) {
            element['selected'] = this.masterCheckboxSelected;
            if (this.masterCheckboxSelected) {
              this.selectedRows.push(element);
            }
          }
        }
      });
      this.dataSource = new MatTableDataSource(this.purchaseOrders);
      this.selectedRows = uniqBy(this.selectedRows, 'id');
    })
  }

  // METHOD TO DISPLAY MY SAVED SEARCH DATA
  getAllMySaveSearchData(pageNo) {
    const TYPE = "PURCHASE_ORDER_ERROR_SEARCH";
    this._poService.getMySaveSearchData(this.userProfileId, TYPE, pageNo, this.pageSize).subscribe(result => {
      this.mySaveSearchList = result.searchprofiles
      this.mySaveSearchDataSource = result.searchprofiles;
      this.mySaveSearchDataSource.forEach(element => {
        element.isEdit = false;
        element.displayError = false;
        element.saveSearchName = "";
        element.isEmpty = false;
      })
      this.mySaveSearchTotalRecords = result.totalRecords;
    })
  }
  // METHOD TO CALL MY SAVE SEARCH TAB UPON SAVING SEARCH NAME
  tabClick(event) {
    if (event.index == 1) {
      this.getAllMySaveSearchData(0);
    }
  }

  onPaginateChange(event: PageEvent) {
    this.currentPage = event.pageIndex;
    /**
     * userNavgatePages for handling pagination checkbox selection
     */
    if (this.userNavigatePages[this.currentPage]) {
      this.userNavigatePages[this.currentPage] += 1
    } else {
      this.userNavigatePages[this.currentPage] = 1;
    }
    if (this.isMySaveSearchEnable) {
      this._poService.onSelectMySaveSearch(this.userProfileId, this.mySaveSearchId, event.pageIndex, this.pageSize).subscribe(result => {
        this.changeTabIndex = 0;
        this.purchaseOrders = result.vendorOrderPOs
        this.totalRecords = result.totalRecords;

        this.purchaseOrders?.forEach(element => {
          const findRowToMakeSelected = this.selectedRows?.find(data => data.id == element.id);
          if (findRowToMakeSelected) {
            element['selected'] = true;
          } else {
            // element['selected'] = false;
            if (this.userNavigatePages[this.currentPage] == 1) {
              element['selected'] = this.masterCheckboxSelected;
              if (this.masterCheckboxSelected) {
                this.selectedRows.push(element);
              }
            }
          }
        });
        this.selectedRows = uniqBy(this.selectedRows, 'id');
        this.dataSource = new MatTableDataSource(this.purchaseOrders);
      });
    }
    else {
      this.poErrorRequestObj.pageNo = event.pageIndex;
      this.getPoData();
    }
  }

  onMySaveSearchPaginateChange(event: PageEvent) {
    this.getAllMySaveSearchData(event.pageIndex)
  }

  // METHOD TO UPDATE THE SAVE SEARCH NAME
  onEditSavaSearchClick(event) {
    event.saveSearchName = event.name;
    event.isEdit = true;
  }

  // METHOD TO CLEAR SAVE SEARCH NAME NAME AND DISPLAYS EXISTING NAME
  clearMySaveSearchName(element) {
    element.isEdit = false;
  }

  //  METHOD TO RESTRICT CHARACTERS UPON REACHING MAX LIMIT
  onEnterSearchName(element) {
    if (element.saveSearchName != "") {
      element.isEmpty = false;
    }
    if (element.saveSearchName.length >= 25) {
      element.displayError = true
    }
    else {
      element.displayError = false;
    }
  }
  // ON SAVING MY SAVE SEARCH NAME UPON EDIT
  onSavingMySaveSearchName(element) {
    element.isEmpty = element.saveSearchName == "";

    this.mySaveSearchList.forEach((data, index) => {
      if (data.name == element.saveSearchName) {
        this.counter++;
        this.editedSearchName = element.saveSearchName + this.counter;
      } else {
        this.editedSearchName = element.saveSearchName;
      }
    })

    let obj = {name: this.editedSearchName,type : ""}

    this._poService.onSavingMySaveSearch(this.userProfileId, element.id, obj).subscribe(result => {
      if (result == false) {
        element.isEdit = false;
        this.message = { statusCode: 200, statusText: "Name change saved!" }
        this.getAllMySaveSearchData(this.pageNo);
      }

    })

  }

  //TO OPEN A SEARCH FLYOUT UPON CLICK
  onSearch() {
    this.isMySaveSearchEnable = false;
    let dialogRef = this.dialog.open(PoErrorsSearchDialogComponent, {
      width: '33%',
      height: '100%',
    })
    dialogRef.afterClosed().subscribe((payload) => {
      if (payload) {
        this.poErrorRequestObj = payload.event;
        this.showClearSearchButton = true;
        this.purchaseOrders = payload.data.vendorOrderPOs;
        this.totalRecords = payload.data.totalRecords;
        this.purchaseOrders?.forEach(element => {
          const findRowToMakeSelected = this.selectedRows?.find(data => data.id == element.id);
          if (findRowToMakeSelected) {
            element['selected'] = true;
          } else {
            // element['selected'] = false;
            if (this.userNavigatePages[this.currentPage] == 1) {
              element['selected'] = this.masterCheckboxSelected;
              if (this.masterCheckboxSelected) {
                this.selectedRows.push(element);
              }
            }
          }
        });
        this.selectedRows = uniqBy(this.selectedRows, 'id');
        this.dataSource = new MatTableDataSource(this.purchaseOrders);
        this.dataSource.paginator = this.paginator;
      }
    })
  }
  onEditClick(event) {
    this.router.navigate(['po-details'],
      {
        relativeTo: this.activatedRoute,
        state: { event: event, totalRecords: this.totalRecords, filterParams: this.poErrorRequestObj }
      });
  }

  // ON DELETE CLICK FROM PO ERROR TABLE
  onDeleteClick(element) {
    this.poErrorDeleteData = []
    this.isDeleteClicked = true;
    this.poErrorDeleteData.push(element.id);
  }

  // ON DELETE RECORD IN PO ERROR TABLE
  onDeleteRecords() {
    this.selectedRows.forEach(x => this.poErrorDeleteData.push(x.id));
    this._poService.deletePoErrors(this.poErrorDeleteData).subscribe(response => {
      this.poErrorDeleteData = [];
      this.currentPage = 0;
      this.getPoErrorData();
      this.selectedRows= [];
      this.message = { statusCode: 200, statusText: "Purchase order(s) successfully deleted" }
    },
      (error) => {
        this.message = { statusCode: 400, statusText: "Failed to delete Purchase Order(s)" }
      }
    )

  }
  // ON DELETE MY SAVE SEARCH UPON CLICK
  onDeleteMySaveSearchClick(element) {
    this.mySavedSearchDeleteId = element.id;
  }
  // TO DELETE MY SAVE SEARCH DATA 
  onDeleteSaveSearch() {
    console.log("hello")
    this._poService.deleteMySaveSearchData(this.userProfileId, this.mySavedSearchDeleteId).subscribe(result => {
      this.getAllMySaveSearchData(0);
      this.mySavedSearchPaginator.firstPage();
      this.message = { statusCode: 200, statusText: "Search successfully deleted from saved searches" }
    },
      (error) => {
        this.message = { statusCode: 400, statusText: "Failed to Delete my Saved search" }
      }
    )

  }
  // TO DISPLAY SELECTED RECORD IN PO ERROR TABLE
  onSelectMySaveSearchClick(element) {
    this.mySaveSearchId = element.id
    this._poService.onSelectMySaveSearch(this.userProfileId, this.mySaveSearchId, this.pageNo, this.pageSize).subscribe(result => {
      this.changeTabIndex = 0;
      this.isMySaveSearchEnable = true;
      this.purchaseOrders = result.vendorOrderPOs;
      this.totalRecords = result.totalRecords;
      this.purchaseOrders?.forEach(element => {
        const findRowToMakeSelected = this.selectedRows?.find(data => data.id == element.id);
        if (findRowToMakeSelected) {
          element['selected'] = true;
        } else {
          // element['selected'] = false;
          if (this.userNavigatePages[this.currentPage] == 1) {
            element['selected'] = this.masterCheckboxSelected;
            if (this.masterCheckboxSelected) {
              this.selectedRows.push(element);
            }
          }
        }
      });
      this.selectedRows = uniqBy(this.selectedRows, 'id');
      this.dataSource = new MatTableDataSource(this.purchaseOrders);
      this.dataSource.paginator = this.paginator;

    })
  }
  onClearSearch() {
    this.showClearSearchButton = false;
    if (this.location.getState()['filterCriteria']) {
      this.location.getState()['filterCriteria'] = null;
    }
    this.poErrorRequestObj.message = '';
    this.poErrorRequestObj.po_number = '';
    this.poErrorRequestObj.vendor = '';
    this.poErrorRequestObj.vendor_number = '';
    this.currentPage = 0;
    this.getPoData();
  }

  onSelectClick(element) {

  }
  sortIndicator(source: string): string {
    if (source === this.currentSortColumn) {
      return 'T';
    } else {
      return 'T';
    }
  }

  sortTable(sort: Sort) {
    this.currentOrderBy = sort.active;
    this.currentOrder = sort.direction;
    this.poErrorRequestObj.orderBy = this.currentOrderBy;
    this.poErrorRequestObj.order = this.currentOrder;
    this.getPoData();
  }

  // isAllSelected() {
  //   const numSelected = this.selection.selected.length;
  //   const numRows = this.dataSource.data.length;
  //   return numSelected === numRows;
  // }

  // masterToggle() {
  //   this.isAllSelected() ?
  //     this.selection.clear() :
  //     this.dataSource.data.forEach(row => this.selection.select(row));
  // }

  // selectAll() {
  //   if (this.selection.hasValue() && this.isAllSelected()) {
  //     this.dataSource.data.forEach(row => this.selection.select(row));
  //   } else {
  //     this.selection.clear();
  //   }
  // }

  unableDisableButton() {
    if (this.selection.selected.length > 0 || this.selectedRows.length > 0) {
      this.isButtonEnable = false;
    } else { 
      this.isButtonEnable = true;
    }
  }

  onSelectSingleCheckBox(row, event) {
    if (event.checked) {
      this.poErrorDeleteData.push(row.id)
    } else {
      this.poErrorDeleteData = this.poErrorDeleteData.filter(e => e !== row.id);
    }
  }

  createNew() {
    setTimeout(() => {
    this.router.navigate(['/supplies/request-supplies'],
        {
          relativeTo: this.activatedRoute,
          state: { tabIndex: 1}
        });
    }, 1000);
  }

  exportPOErrorRecords() {
    this.isAllCheckFlag = this.masterCheckboxSelected ? 'Y' : 'N';
    this._poService.exportPoErrors(this.masterCheckboxSelected ? this.unSelectedRows : this.selectedRows, this.isAllCheckFlag)
      .subscribe(
        (response: HttpResponse<Blob>) => {
          let filename = "poErrors.csv";
          let binaryData = [];
          binaryData.push(response);
          let downloadLink = document.createElement('a');
          downloadLink.href = window.URL.createObjectURL(new Blob(binaryData, { type: 'text/csv' }));
          downloadLink.setAttribute('download', filename);
          document.body.appendChild(downloadLink);
          downloadLink.click();
        }
      )
  }

  masterCheckBoxSelection() {
    this.purchaseOrders?.forEach(element => {
      element['selected'] = this.masterCheckboxSelected;
      if (this.masterCheckboxSelected) {
        this.selectedRows.push(element);
      } else {
        this.selectedRows = [];
        this.unSelectedRows = [];
      }
    });
    this.dataSource = new MatTableDataSource(this.purchaseOrders);
    this.selectedRows = uniqBy(this.selectedRows, 'id');
    this.unableDisableButton();
  }

  rowSelection(row, index) {
    row['selected'] = !row.selected;

    if (row.selected) {
      const isPresentAlreadyInSelectedRows = this.selectedRows?.find(data => data.id == row.id);
      if (!isPresentAlreadyInSelectedRows) {
        this.selectedRows.push(this.dataSource.filteredData[index]);
      }
      this.unSelectedRows = this.unSelectedRows.filter(data => data?.id !== row?.id);
    } else {
      this.selectedRows = this.selectedRows.filter(data => data.id !== row.id);
      this.unSelectedRows.push(row);
    }

    this.selectedRows = uniqBy(this.selectedRows, 'id');
    this.unableDisableButton();
  }

}

If anyone can help me how to solve this issue.

Expected result : even if i have checked mastercheckbox on any page whether it 1st ,2nd ,5th or last second page all checkbox sholud get selected by default and if i manually deselect any checkbox then it should be deselect . Currently it is working when i have select master checkbox on 1st page.

0

There are 0 answers