Angular Material - Implementing pagination for a dynamic table

I'm facing a challenge with my Angular Material dynamic table, as I am fetching data from an external database using an API. I am attempting to implement pagination on the table, but I can't seem to find suitable examples that match my scenario.

In my HTML file, I have added the mat-paginator tag to enable pagination, but I'm struggling to make it work in the .ts file where I handle the logic. Below is a snippet of my component.ts code:

import { Component, OnInit, ViewChild } from '@angular/core';
import { FormGroup, FormBuilder } from '@angular/forms';
import { ClientService } from '../../services/clients.service';
import { Client } from '../../domain/clients';
import { MatPaginator } from '@angular/material/paginator';
import { MatTableDataSource } from '@angular/material/table';

export class ClientsComponent implements OnInit {

  @ViewChild(MatPaginator) paginator: MatPaginator;

  public displayedColumns: string[] = ['name'];
  public client: Client;
  public clients: Client[];

  constructor(
    public fb: FormBuilder,
    private clientService: ClientService
  ) { }

  ngOnInit() {
    this.getClients();
  }

  getClient() {
    this.clientService.list()
    .subscribe(clients => this.clients = clients);
  }

}

And here is the component.html file:

<div class="title">Customers</div>
<mat-divider></mat-divider>

<div fxLayout="column" fxLayoutGap="10px" class="m-3">
  <mat-card class="mat-elevation-z8">
    <mat-table [dataSource]="clients">

      <ng-container matColumnDef="name">
        <mat-header-cell *matHeaderCellDef>Name</mat-header-cell>
        <mat-cell *matCellDef="let clients; let i = index">
          <mat-form-field floatLabel="never" [appearance]="editIndex != i ? 'none' : 'legacy'">
            <input matInput placeholder="{{clients.name}}" [(ngModel)]="clients.name" [readonly]="editIndex!=i">
          </mat-form-field>
        </mat-cell>
      </ng-container>

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

    </mat-table>
    <mat-paginator [pageSizeOptions]="[5, 10, 20]" showFirstLastButtons></mat-paginator>
  </mat-card>
</div>

Answer №1

Use the MatTableDataSource as the data source, which includes the paginator property for table pagination.

SOLUTION

.component.html

<mat-table [dataSource]="this.dataSource">

    <ng-container matColumnDef="name">
        <mat-header-cell *matHeaderCellDef>Name</mat-header-cell>
        <mat-cell *matCellDef="let client; let i = index">
          <mat-form-field floatLabel="never" [appearance]="editIndex != i ? 'none' : 'legacy'">
            <input matInput placeholder="{{client.name}}" [(ngModel)]="client.name" [readonly]="editIndex!=i">
          </mat-form-field>
        </mat-cell>
    </ng-container>

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

<mat-paginator [pageSizeOptions]="[5, 10, 20]" showFirstLastButtons></mat-paginator>

.component.ts

export class ClientsComponent implements OnInit {
  ...

  dataSource: MatTableDataSource<Client>;
  @ViewChild(MatPaginator) paginator: MatPaginator;

  ...

  getClients() {
    this.clienteService.list().subscribe(client => {
      this.clients = client;
      this.dataSource = new MatTableDataSource(this.clients);
      this.dataSource.paginator = this.paginator;
    });
  }
}

Solution on StackBlitz


RECOMMENDATION(S)

<mat-form-field floatLabel="never" [appearance]="editIndex != i ? 'none' : 'legacy'">
    <input matInput placeholder="{{client.name}}" [(ngModel)]="client.name" [readonly]="editIndex!=i">
</mat-form-field>

When using [appearance], ensure you provide a supported value for MatFormFieldAppearance as outlined in the Angular documentation.

type MatFormFieldAppearance = 'legacy' | 'standard' | 'fill' | 'outline';

If strict mode is enabled for the Angular compiler in tsconfig.json, you may encounter the following error.

Type '"none"' is not assignable to type 'MatFormFieldAppearance'.

To address this issue, consider commenting out the section related to angularCompilerOptions in tsconfig.json.

tsconfig.json

{
  ...
},
// "angularCompilerOptions": {
//   "enableIvy": true,
//   "fullTemplateTypeCheck": true,
//   "strictInjectionParameters": true
// }

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

Working with JSON data in AngularJS2's templates

Is there a way for me to process JSON from the template in a manner similar to the second code I provided? First code. This method works well when using .json and .map () @Component({ ..// template: `..// <li *ngFor="#user of users"> ...

The parameter type 'Object' cannot be assigned to the parameter type 'string'

Everything seems to be working fine in my application, but I am encountering the following error message: The argument of type 'Object' is causing an issue and cannot be assigned to a parameter of type 'string' Here is the code snip ...

does not have any exported directive named 'MD_XXX_DIRECTIVES'

I am currently learning Angular2 and I have decided to incorporate angular material into my project. However, I am encountering the following errors: "has no exported member MD_XXX_DIRECTIVES" errors (e.g: MD_SIDENAV_DIRECTIVES,MD_LIST_DIRECTIVES). Her ...

Ways to enhance the type definitions for a built-in HTML element in Vue.js?

Imagine having an element that wraps around an input and inherits all of its properties, along with some extras. In React, you would define this as: interface ExtendedInputProps extends React.ComponentPropsWithoutRef<'input'> { some: T ...

RXJS - Trigger a function based on a specific condition being fulfilled by a value emitted from an observable

I have created a search field with autocomplete functionality. By using an observable that monitors changes in the text field, I am able to trigger actions based on user input. this.term.valueChanges .debounceTime(300) .distinctUntilChange ...

Nestjs is throwing an UnhandledPromiseRejectionWarning due to a TypeError saying that the function this.flushLogs is not recognized

Looking to dive into the world of microservices using kafka and nestjs, but encountering an error message like the one below: [Nest] 61226 - 07/18/2021, 12:12:16 PM [NestFactory] Starting Nest application... [Nest] 61226 - 07/18/2021, 12:12:16 PM [ ...

Angular 2: Enhancing communication between directives and host components

I am facing an issue with a component that has 'header', 'content', and 'footer' divs in its template. Within the content div, I have implemented a custom directive to check for overflow in the div element. This part is workin ...

Is it possible to execute "green arrow" unit tests directly with Mocha in IntelliJ IDEA, even when Karma and Mocha are both installed?

My unit tests are set up using Karma and Mocha. The reason I use Karma is because some of the functionality being tested requires a web browser, even if it's just a fake headless one. However, most of my code can be run in either a browser or Node.js. ...

Issue with Side Nav bar - the presence of 'ng-template' element is causing a problem

After diligently following the guide on material.io, I executed the npm install command for @angular/material. npm install --save @angular/material However, when attempting to implement the side-nav bar component as demonstrated at https://material.angul ...

MUI Select component not displaying top border

Can anyone help me understand why the select field is behaving this way? I'm new to the project and suspect that someone may have made changes to it. https://i.sstatic.net/pB6Sx.png <mui.FormControl style={{ width: '598px' }}> ...

What is the best approach to include two ng-contents within a single template and manage them using *ngIf?

Presently, I am dealing with an Angular 2 component that is designed to showcase a Bootstrap 3 button group. This particular component has the capability of having a label or standing alone. In order to address this, I opted to utilize two ng-contents con ...

Revealing private and protected Typescript members within Angular 1.x's view

When integrating TS and Angular, I've noticed that everything in my controller is accessible from the view. For example, myPrivate will be visible on $ctrl. class MyController extends BaseController implements SomeInterface { private myPrivate: s ...

Using RxJS to send two simultaneous requests, one of which is not required, and implement a timeout

I am faced with a situation where I need to send 2 GET requests simultaneously: The first request is crucial and cannot be skipped. I must wait for the response, handle any errors that may occur, and have the ability to cancel the second request if neede ...

Multiple Invocations of Angular Observable Service

I am facing an issue with my service method that returns an observable. In my component, I subscribe to this observable when it is loaded and have added a console.log in the service to track each time it is called. Upon running my application and checking ...

Transforming file location to base64 encoded format using TypeScript

I have the path of an image and need to convert it to base64 format, similar to this data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUg... function encodeImageToBase64(url, callback) { var xhr = new XMLHttpRequest(); xhr.onload = function() { va ...

Utilize NestJS to consume EventPattern exclusively when the header variable matches a specific value

I've been working on a NestJS project where I'm using a Kafka server to emit events and NestJS to consume them. My goal is to create a consumer with the topic my-topic that is triggered only when a specific value is present in the header variable ...

The Angular application hosted within a Docker container running Nginx is experiencing difficulties accessing image files stored in

I am facing an issue with my Angular app hosted on my local machine using the Docker NGINX image. The app runs fine and I can access it through the browser with localhost:port, but I am unable to load images from a volume attached to the container. In my ...

Combining an array of objects in Angular 2 based on the object's name

When I receive a response from the backend, it looks like this: [ { "id": 1, "restaurant_name": "Ajisen Ramen Toronto", "description": "Japanese Restaurant", "phone": "416-977-8080", "address": { "id": 3, ...

I am curious about the significance of the "=>" symbol within the Ionic framework

I utilized the documentation provided on the Ionic website to incorporate Firebase into my mobile application. this.firebase.getToken() .then(token => console.log(`The token is ${token}`)) // store the token server-side and utilize it for sending not ...

Guide to transforming an embed/nested FormGroup into FormData

Presenting my Form Group: this.storeGroup = this.fb.group({ _user: [''], name: ['', Validators.compose([Validators.required, Validators.maxLength(60)])], url_name: [''], desc: ['', Validators.compose([Valida ...