Angular 7: Utilizing Angular Material for Implementing Server-Side Pagination

I have encountered an issue with server-side pagination using Angular 7 and Angular Material. The problem is that the pagination layout does not look like what I want it to be.

https://i.sstatic.net/qCntw.jpg

I would like the pagination to appear as shown in this image https://i.sstatic.net/BzTJs.jpg

Could someone please guide me on how to achieve this? Below is an example of my code structure:-

html

<div class="example-container mat-elevation-z8">
  <div class="example-loading-shade"
       *ngIf="isLoadingResults || isRateLimitReached">
    <mat-spinner *ngIf="isLoadingResults"></mat-spinner>
    <div class="example-rate-limit-reached" *ngIf="isRateLimitReached">
      GitHub's API rate limit has been reached. It will be reset in one minute.
    </div>
  </div>

  <div class="example-table-container">

    <table mat-table [dataSource]="data" class="example-table"
           matSort matSortActive="created" matSortDisableClear matSortDirection="desc">
      <!-- Number Column -->
      <ng-container matColumnDef="number">
        <th mat-header-cell *matHeaderCellDef>#</th>
        <td mat-cell *matCellDef="let row">{{row.number}}</td>
      </ng-container>

      <!-- Title Column -->
      <ng-container matColumnDef="title">
        <th mat-header-cell *matHeaderCellDef>Title</th>
        <td mat-cell *matCellDef="let row">{{row.title}}</td>
      </ng-container>

      <!-- State Column -->
      <ng-container matColumnDef="state">
        <th mat-header-cell *matHeaderCellDef>State</th>
        <td mat-cell *matCellDef="let row">{{row.state}}</td>
      </ng-container>

      <!-- Created Column -->
      <ng-container matColumnDef="created">
        <th mat-header-cell *matHeaderCellDef mat-sort-header disableClear>
          Created
        </th>
        <td mat-cell *matCellDef="let row">{{row.created_at | date}}</td>
      </ng-container>

      <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
      <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
    </table>
  </div>

  <mat-paginator [length]="resultsLength" [pageSize]="30"></mat-paginator>
</div>

Component ts

export class TableHttpExample implements AfterViewInit {
  displayedColumns: string[] = ['created', 'state', 'number', 'title'];
  exampleDatabase: ExampleHttpDatabase | null;
  // data: GithubIssue[] = [];

  resultsLength = 0;
  isLoadingResults = true;
  isRateLimitReached = false;

  @ViewChild(MatPaginator, {static: false}) paginator: MatPaginator;
  @ViewChild(MatSort, {static: false}) sort: MatSort;

  constructor(private _httpClient: HttpClient) {}

  ngAfterViewInit() {
    this.exampleDatabase = new ExampleHttpDatabase(this._httpClient);

    // If the user changes the sort order, reset back to the first page.
    this.sort.sortChange.subscribe(() => this.paginator.pageIndex = 0);

    merge(this.sort.sortChange, this.paginator.page)
      .pipe(
        startWith({}),
        switchMap(() => {
          this.isLoadingResults = true;
          return this.exampleDatabase!.getRepoIssues(
            this.sort.active, this.sort.direction, this.paginator.pageIndex);
        }),
        map(data => {
          // Flip flag to show that loading has finished.
          this.isLoadingResults = false;
          this.isRateLimitReached = false;
          this.resultsLength = data.total_count;

          return data.items;
        }),
        catchError(() => {
          this.isLoadingResults = false;
          // Catch if the GitHub API has reached its rate limit. Return empty data.
          this.isRateLimitReached = true;
          return observableOf([]);
        })
      ).subscribe(data => this.data = data);
  }
}

Service ts

export interface GithubApi {
  items: GithubIssue[];
  total_count: number;
}

export interface GithubIssue {
  created_at: string;
  number: string;
  state: string;
  title: string;
}
export class ExampleHttpDatabase {
data: GithubIssue[] = [];



/** An example database that the data source uses to retrieve data for the table. */

  constructor(private _httpClient: HttpClient) {}

  getRepoIssues(sort: string, order: string, page: number): Observable<GithubApi> {
    const href = 'https://api.github.com/search/issues';
    const requestUrl =
        `${href}?q=repo:angular/components&sort=${sort}&order=${order}&page=${page + 1}`;

    return this._httpClient.get<GithubApi>(requestUrl);
  }
}

I have attempted to modify the code but without success. Any help on resolving this issue would be greatly appreciated.

Here is a link to my demo code.

Thank you in advance.

Answer №1

Check out my solution here

The key is to create a custom paginator instead of using the Material one. Simply add fixed navigation buttons like "First", "Prev", "Next", and "Last". With data such as length and pageSize, you can generate the page list. The only issue I encountered was with the pageSize, but hopefully you can troubleshoot that in a real application.

Manage page changes using a BehaviorSubject. You can see everything in the example provided.

I'll let you handle the styles and any minor tweaks. Perhaps consider limiting the number of displayed pages for better user experience.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Exploring the depths of useDispatch and dispatch in React-Redux

I am currently analyzing the code written by a former colleague of mine. Based on my understanding, useDispatch accepts an object containing the action type and payload, which is then compared to all reducers to update the state accordingly. However, in t ...

Error in Ionic: Although $state.go successfully changes the URL, the corresponding view fails to load

When attempting to change the state programmatically, the URL updates, but the view does not load. It only works after refreshing the page, however using $window.location.reload(true); feels unconventional. Controller myApp.controller('WelcomeContro ...

Looking for assistance with navigating through Angular routes?

I am currently working on a small Angular application that consists of 3 main pages: Login Dashboard User profile The application is functioning properly, but I have an issue. I want to hide the sidebar on the login page. The sidebar should only be visi ...

Eliminate the unnecessary code repetition in my functions using Typescript

I have 2 specific functions that manipulate arrays within an object. Instead of repeating the same code for each array, I am looking for a way to create reusable functions. Currently, my functions look like this: setLists(): void { if (this.product.ord ...

Navigate to the middle of a DIV container in Angular 7

Is there a way to programmatically scroll to the center of my element on both the Y and X axes when a specific function is executed? My HTML structure includes the following (I am aiming to scroll to the middle of #viewport): </div> <div # ...

How to effectively utilize ViewChildren _results in Angular 4?

I'm working with a list of checkboxes that are generated within an ngFor loop: <md-checkbox #hangcheck [id]="hangout?.$key" class="mychecks" > I'm Interested </md-checkbox> To reference these checkb ...

Error: Unable to access the 'next' property of null within an Angular 2 Observable

Issue Found An error of type TypeError has occurred: Cannot read property 'next' of null Problematic Template Utilizing Observer.next import { NavService } from '../../providers/services/nav-service/nav-service'; @Component({ ...

Implementing secure HTTPS for an Angular 6 application

Currently, I have an Angular 6 application running on a Tomcat web server. The server-side of the app is implemented in Java using the Spring framework and deployed on another Tomcat web server. I am looking to implement secure SSL for my entire applicat ...

Is there a way to determine if a customer's device is a tablet by using typescript or javascript?

I need help with displaying a button only on mobile and desktop devices in my application. If the user is using a tablet device, I want to hide the button using React and TypeScript. Below is the code snippet, function Parent() { return( <b ...

Module for migration located in a subdirectory

Currently, I am in the process of transitioning an Angular application to NativeScript while utilizing a code-sharing setup. For the migration of Angular modules, I have been executing the following command: ng g migrate-module --name=nameModule However ...

"Despite the inability to use the clear input field function in Angular, users can still effectively clear

Why does the X button not clear and refresh the field when clicked, but using backspace does? I want it to clear when the X button is clicked. <mat-form-field appearance="standard" fxFill> <mat-label style="font-size: 12 ...

The String retrieved from the API response does not support displaying line breaks, whereas a hard-coded string can successfully display line breaks

Greetings, My frontend is built on Angular 8, with a Java API service serving as the backend. I need to fetch a String from the backend, which will contain '\n' line breaks. For example: "Instructions:\n1. Key in 122<16 digit ...

Top strategy for integrating automatic data preservation of user inputs in Angular 2

Within my Angular 2 application, I have a requirement to synchronize any changes made in an input tag value on the UI screen with the database. The objective is to ensure that: From the end user's perspective, it appears as though the input value ha ...

Unlocking the power of variables in Next.js inline sass styles

Is there a way to utilize SASS variables in inline styles? export default function (): JSX.Element { return ( <MainLayout title={title} robots={false}> <nav> <a href="href">Title</a> ...

Using the Angular JSON pipe with angular-datatables

I am currently utilizing angular-datatables to exhibit NoSQL de-normalized data in a grid format for visualization purposes. Within my dataset, I have several intricate nested JSON objects and I intend to showcase a specific cell with formatted JSON using ...

Error: Unable to locate specified column in Angular Material table

I don't understand why I am encountering this error in my code: ERROR Error: Could not find column with id "continent". I thought I had added the display column part correctly, so I'm unsure why this error is happening. <div class="exa ...

Cracking the Code: Demystifying TypeScript Syntax within Angular 4

Recently, I delved into the world of Angular 4 and Typescript by following the step-by-step "Angular-tour-of-heroes" tutorial on the Angular.io website. Since Angular 4 relies on typescript for defining components and more, I wanted to deepen my understand ...

Middleware for Redux in Typescript

Converting a JavaScript-written React app to Typescript has been quite the challenge for me. The error messages are complex and difficult to decipher, especially when trying to create a simple middleware. I've spent about 5 hours trying to solve an er ...

Tips for extracting key values from an array of objects in Typescript

I am working with an array called studyTypes: const studyTypes = [ { value: "ENG", label: "ENG-RU", }, { value: "RU", label: "RU-ENG", }, ]; Additionally, I have a state variable set ...

Angular 6 - The exporting of the ForkJoin member is non-existent

After upgrading to Angular 6, I attempted to implement ForkJoin in my project. In my service file, I included the following code: import { forkJoin } from 'rxjs/observable/forkJoin'; However, it seems to be unable to recognize it and I encounte ...