---
title: Paginate Matrix Rows
product: Form Library
description: Learn how to enable paging in a SurveyJS Dynamic Matrix and Multi-Select Matrix to simplify navigation through long lists of rows. This demo for JavaScript shows how to set the maximum number of rows per page, track the current page, and get the total page count.
framework: Angular
source: https://surveyjs.io/form-library/examples/paging-in-matrices/angular
index: https://surveyjs.io/form-library/examples/overview.md
---

# Paginate Matrix Rows (Angular)

Paging divides matrix rows into smaller sections so that respondents can work with long lists without scrolling through the entire table. This demo displays 30 orders in a [Dynamic Matrix](https://surveyjs.io/form-library/documentation/api-reference/dynamic-matrix-table-question-model) or [Multi-Select Matrix](https://surveyjs.io/form-library/documentation/api-reference/matrix-table-with-dropdown-list). You can switch between the matrices using the **Switch to Multi-Select Matrix** or **Switch to Dynamic Matrix** action in the matrix title.

> Paging is available in SurveyJS Form Library v3.2.2 and later.

## Enable Paging

You can enable paging by setting the matrix's [`pageSize`](/form-library/documentation/api-reference/dynamic-matrix-table-question-model#pageSize) property to the number of rows per data page. The default value, `0`, disables paging. The effective page size is limited by the global [`settings.maxPageSize`](/form-library/documentation/api-reference/settings#maxPageSize) property. If you need to remove this limit, set the property to `0`.

In addition, you can use [`pageIndex`](/form-library/documentation/api-reference/dynamic-matrix-table-question-model#pageIndex) to read or change the current data page index and [`pageCount`](/form-library/documentation/api-reference/dynamic-matrix-table-question-model#pageCount) to access the total number of data pages.

Both matrices in this example display five rows per page. You can switch between data pages using the navigation controls below each matrix.

## See Also

[Demo: Paging in Dynamic Panel](/form-library/examples/paging-in-dynamic-panel/ (linkStyle))

## Files

### `src/app/components/json.ts`

```ts
export const json = {
  "showNavigationButtons": false,
  "pages": [
    {
      "name": "dynamic-matrix",
      "elements": [
        {
          "type": "matrixdynamic",
          "name": "dynamicOrders",
          "title": "Orders (Dynamic Matrix)",
          "description": "You can edit orders in the matrix and use the navigation controls below it to switch between data pages.",
          "pageSize": 5,
          "addRowText": "Add order",
          "columns": [
            {
              "name": "id",
              "title": "Order #",
              "cellType": "text",
              "inputType": "number",
              "readOnly": true,
              "width": "70px"
            },
            {
              "name": "customer",
              "title": "Customer",
              "cellType": "text",
              "isRequired": true
            },
            {
              "name": "product",
              "title": "Product",
              "choices": [
                "Laptop",
                "Monitor",
                "Keyboard",
                "Mouse",
                "Headset",
                "Docking station",
                "Webcam",
                "Desk lamp",
                "Office chair",
                "USB-C cable"
              ]
            },
            {
              "name": "quantity",
              "title": "Qty",
              "cellType": "text",
              "inputType": "number",
              "min": 1,
              "width": "80px"
            },
            {
              "name": "price",
              "title": "Unit price ($)",
              "cellType": "text",
              "inputType": "number",
              "min": 0,
              "width": "110px"
            },
            {
              "name": "total",
              "title": "Total",
              "cellType": "expression",
              "expression": "{row.quantity} * {row.price}",
              "displayStyle": "currency"
            }
          ]
        }
      ]
    },
    {
      "name": "multi-select-matrix",
      "elements": [
        {
          "type": "matrixdropdown",
          "name": "fixedOrders",
          "title": "Orders (Multi-Select Matrix)",
          "description": "You can edit orders in the matrix and use the navigation controls below it to switch between data pages.",
          "pageSize": 5,
          "columns": [
            {
              "name": "customer",
              "title": "Customer",
              "cellType": "text",
              "isRequired": true
            },
            {
              "name": "product",
              "title": "Product",
              "choices": [
                "Laptop",
                "Monitor",
                "Keyboard",
                "Mouse",
                "Headset",
                "Docking station",
                "Webcam",
                "Desk lamp",
                "Office chair",
                "USB-C cable"
              ]
            },
            {
              "name": "quantity",
              "title": "Qty",
              "cellType": "text",
              "inputType": "number",
              "min": 1,
              "width": "80px"
            },
            {
              "name": "price",
              "title": "Unit price ($)",
              "cellType": "text",
              "inputType": "number",
              "min": 0,
              "width": "110px"
            },
            {
              "name": "total",
              "title": "Total",
              "cellType": "expression",
              "expression": "{row.quantity} * {row.price}",
              "displayStyle": "currency"
            }
          ]
        }
      ]
    }
  ]
}
;
```

### `src/app/components/survey.component.css`

```css
/* You can add your custom CSS here. */
```

### `src/app/components/survey.component.html`

```html
<survey [model]="model" style="position: absolute; top: 0; left: 0; right: 0; bottom: 0; height:100%"></survey>
```

### `src/app/components/survey.component.ts`

```ts
import { Component, OnInit } from "@angular/core";
import { Model } from "survey-core";
import { json } from "./json";
import "./survey.component.css";
import "survey-core/survey-core.min.css";

@Component({
    // tslint:disable-next-line:component-selector
    selector: "component-survey",
    templateUrl: "./survey.component.html",
    styleUrls: ["./survey.component.css"]
})
export class SurveyComponent implements OnInit {
    model: Model;
    ngOnInit() {
        const survey = new Model(json);
        const orders = [
          { id: 1001, customer: "Bob Brown", product: "Mouse", quantity: 4, price: 39 },
          { id: 1002, customer: "Grace Smith", product: "Laptop", quantity: 1, price: 1290 },
          { id: 1003, customer: "Quinn Smith", product: "USB-C cable", quantity: 2, price: 15 },
          { id: 1004, customer: "Elena Tanaka", product: "Monitor", quantity: 1, price: 340 },
          { id: 1005, customer: "Bob Rossi", product: "Monitor", quantity: 5, price: 340 },
          { id: 1006, customer: "Liam Garcia", product: "Laptop", quantity: 5, price: 1290 },
          { id: 1007, customer: "Sven Chen", product: "USB-C cable", quantity: 5, price: 15 },
          { id: 1008, customer: "Rosa Larsen", product: "Desk lamp", quantity: 2, price: 45 },
          { id: 1009, customer: "Noah Novak", product: "Mouse", quantity: 3, price: 39 },
          { id: 1010, customer: "Olga Petrova", product: "Webcam", quantity: 2, price: 89 },
          { id: 1011, customer: "Ines Tanaka", product: "Laptop", quantity: 2, price: 1290 },
          { id: 1012, customer: "Tara Silva", product: "Docking station", quantity: 3, price: 219 },
          { id: 1013, customer: "Liam Kowalski", product: "Monitor", quantity: 1, price: 340 },
          { id: 1014, customer: "Pablo Ivanova", product: "Keyboard", quantity: 4, price: 79 },
          { id: 1015, customer: "Noah Haddad", product: "Docking station", quantity: 1, price: 219 },
          { id: 1016, customer: "Ann Silva", product: "Monitor", quantity: 2, price: 340 },
          { id: 1017, customer: "Grace Müller", product: "Office chair", quantity: 2, price: 410 },
          { id: 1018, customer: "Elena Silva", product: "Webcam", quantity: 2, price: 89 },
          { id: 1019, customer: "Dmitri Okafor", product: "Office chair", quantity: 3, price: 410 },
          { id: 1020, customer: "Mei Brown", product: "USB-C cable", quantity: 3, price: 15 },
          { id: 1021, customer: "Sofia Martin", product: "Headset", quantity: 2, price: 119 },
          { id: 1022, customer: "Lucas Chen", product: "Laptop", quantity: 1, price: 1290 },
          { id: 1023, customer: "Amira Hassan", product: "Desk lamp", quantity: 4, price: 45 },
          { id: 1024, customer: "Oscar Silva", product: "Keyboard", quantity: 3, price: 79 },
          { id: 1025, customer: "Hana Novak", product: "Monitor", quantity: 2, price: 340 },
          { id: 1026, customer: "Leo Rossi", product: "Webcam", quantity: 1, price: 89 },
          { id: 1027, customer: "Maya Garcia", product: "Office chair", quantity: 3, price: 410 },
          { id: 1028, customer: "Ivan Larsen", product: "Docking station", quantity: 2, price: 219 },
          { id: 1029, customer: "Nina Tanaka", product: "Mouse", quantity: 5, price: 39 },
          { id: 1030, customer: "Adam Kowalski", product: "USB-C cable", quantity: 4, price: 15 }
        ];
        
        let nextOrderId = Math.max(...orders.map(order => order.id)) + 1;
        survey.onMatrixRowAdded.add((_, options) => {
          if (options.question.name === "dynamicOrders") {
            options.row.getQuestionByColumnName("id").value = nextOrderId++;
          }
        });
        survey.onGetQuestionTitleActions.add((_, options) => {
          const name = options.question.name;
          if (name !== "dynamicOrders" && name !== "fixedOrders") return;
        
          const isDynamic = name === "dynamicOrders";
          options.actions.push({
            id: "switch-matrix-type",
            title: isDynamic ? "Switch to Multi-Select Matrix" : "Switch to Dynamic Matrix",
            action: () => {
              survey.currentPageNo = isDynamic ? 1 : 0;
            }
          });
        });
        
        survey.getQuestionByName("fixedOrders").rows = orders.map(order => String(order.id));
        
        const fixedOrders = {};
        orders.forEach(order => {
          fixedOrders[order.id] = {
            customer: order.customer,
            product: order.product,
            quantity: order.quantity,
            price: order.price
          };
        });
        
        survey.data = {
          dynamicOrders: orders,
          fixedOrders: fixedOrders
        };
        
        survey.onComplete.add((sender, options) => {
            console.log(JSON.stringify(sender.data, null, 3));
        });
        this.model = survey;
    }
}
```

### `src/app/components/theme.ts`

```ts
export const themeJson = {};
```

### `src/app/app.component.css`

```css

```

### `src/app/app.component.html`

```html
<component-survey></component-survey>
```

### `src/app/app.component.ts`

```ts
import { Component } from "@angular/core";

@Component({
    selector: "app-root",
    templateUrl: "./app.component.html",
    styleUrls: ["./app.component.css"]
})
export class AppComponent {
    title = "CodeSandbox";
}
```

### `src/app/app.module.ts`

```ts
import { BrowserModule } from "@angular/platform-browser";
import { NgModule } from "@angular/core";

import { AppComponent } from "./app.component";
import { SurveyModule } from "survey-angular-ui";
import { SurveyComponent } from "./components/survey.component";

@NgModule({
    declarations: [AppComponent, SurveyComponent],
    imports: [BrowserModule, SurveyModule],
    providers: [],
    bootstrap: [AppComponent]
})
export class AppModule { }
```

### `src/environments/environment.prod.ts`

```ts
export const environment = {
    production: true
};
```

### `src/environments/environment.ts`

```ts
// The file contents for the current environment will overwrite these during build.
// The build system defaults to the dev environment which uses `environment.ts`, but if you do
// `ng build --env=prod` then `environment.prod.ts` will be used instead.
// The list of which env maps to which file can be found in `.angular-cli.json`.

export const environment = {
    production: false
};
```

### `src/index.html`

```html
<link href="https://fonts.googleapis.com/css?family=Open%20Sans:400,600&display=swap" rel="stylesheet">
<app-root></app-root>
```

### `src/main.ts`

```ts
import { enableProdMode } from "@angular/core";
import { platformBrowserDynamic } from "@angular/platform-browser-dynamic";

import { AppModule } from "./app/app.module";
import { environment } from "./environments/environment";

if (environment.production) {
    enableProdMode();
}

platformBrowserDynamic()
    .bootstrapModule(AppModule)
    .catch(err => console.log(err));
```

### `src/polyfills.ts`

```ts
/**
 * This file includes polyfills needed by Angular and is loaded before the app.
 * You can add your own extra polyfills to this file.
 *
 * This file is divided into 2 sections:
 *   1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
 *   2. Application imports. Files imported after ZoneJS that should be loaded before your main
 *      file.
 *
 * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
 * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
 * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
 *
 * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html
 */

/***************************************************************************************************
 * BROWSER POLYFILLS
 */

/** IE9, IE10 and IE11 requires all of the following polyfills. **/
// import 'core-js/es6/symbol';
// import 'core-js/es6/object';
// import 'core-js/es6/function';
// import 'core-js/es6/parse-int';
// import 'core-js/es6/parse-float';
// import 'core-js/es6/number';
// import 'core-js/es6/math';
// import 'core-js/es6/string';
// import 'core-js/es6/date';
// import 'core-js/es6/array';
// import 'core-js/es6/regexp';
// import 'core-js/es6/map';
// import 'core-js/es6/weak-map';
// import 'core-js/es6/set';

/** IE10 and IE11 requires the following for NgClass support on SVG elements */
// import 'classlist.js';  // Run `npm install classlist.js`.

/** IE10 and IE11 requires the following for the Reflect API. */
// import 'core-js/es6/reflect';

/** Evergreen browsers require these. **/
// Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove.
import "core-js/proposals/reflect-metadata";

/**
 * Required to support Web Animations `@angular/platform-browser/animations`.
 * Needed for: All but Chrome, Firefox and Opera. http://caniuse.com/#feat=web-animation
 **/
// import 'web-animations-js';  // Run `npm install web-animations-js`.

/***************************************************************************************************
 * Zone JS is required by default for Angular itself.
 */
import "zone.js/dist/zone"; // Included with Angular CLI.

/***************************************************************************************************
 * APPLICATION IMPORTS
 */
```

### `src/styles.css`

```css
/* You can add your custom CSS here. */
```

### `src/typings.d.ts`

```ts
/* SystemJS module definition */
declare var module: NodeModule;
interface NodeModule {
    id: string;
}
```

### `.angular-cli.json`

```json
{
  "apps": [
    {
      "root": "src",
      "outDir": "dist",
      "assets": [ "assets", "favicon.ico" ],
      "index": "index.html",
      "main": "main.ts",
      "polyfills": "polyfills.ts",
      "prefix": "app",
      "styles": [ "styles.css" ],
      "scripts": [ ],
      "environmentSource": "environments/environment.ts",
      "environments": {
        "dev": "environments/environment.ts",
        "prod": "environments/environment.prod.ts"
      }
    }
  ]
}
```

### `_tsconfig.json`

```json
{
  "compileOnSave": false,
  "compilerOptions": {
    "baseUrl": "./",
    "outDir": "./dist/out-tsc",
    "sourceMap": true,
    "declaration": false,
    "allowSyntheticDefaultImports": true,
    "downlevelIteration": true,
    "experimentalDecorators": true,
    "moduleResolution": "node",
    "importHelpers": true,
    "resolveJsonModule": true,
    "target": "es2015",
    "module": "es2020",
    "lib": [
      "es2018",
      "dom"
    ]
  }
}
```

### `package.json`

```json
{
  "name": "surveyjs-angular",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build --prod",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "14.1.1",
    "@angular/cdk": "14.1.1",
    "@angular/common": "14.1.1",
    "@angular/compiler": "14.1.1",
    "@angular/core": "14.1.1",
    "@angular/forms": "14.1.1",
    "@angular/platform-browser": "14.1.1",
    "@angular/platform-browser-dynamic": "14.1.1",
    "@angular/router": "14.1.1",
    "core-js": "3.6.4",
    "rxjs": "6.5.4",
    "survey-core": "latest",
    "survey-angular-ui": "latest",
    "tslib": "1.13.0",
    "zone.js": "0.11.7"
  },
  "devDependencies": {
    "@angular/cli": "1.6.6",
    "@angular/compiler-cli": "^5.2.0",
    "@angular/language-service": "^5.2.0",
    "@types/core-js": "0.9.46",
    "@types/jasmine": "~2.8.3",
    "@types/jasminewd2": "~2.0.2",
    "@types/node": "~6.0.60",
    "codelyzer": "^4.0.1",
    "jasmine-core": "~2.8.0",
    "jasmine-spec-reporter": "~4.2.1",
    "karma": "~2.0.0",
    "karma-chrome-launcher": "~2.2.0",
    "karma-coverage-istanbul-reporter": "^1.2.1",
    "karma-jasmine": "~1.1.0",
    "karma-jasmine-html-reporter": "^0.2.2",
    "protractor": "~5.1.2",
    "ts-node": "~4.1.0",
    "tslint": "~5.9.1",
    "typescript": "3.9.7"
  },
  "keywords": [ "angular", "surveyjs" ],
  "description": "SurveyJS-Angular example project"
}
```

## Other Frameworks

- [React](https://surveyjs.io/form-library/examples/paging-in-matrices/reactjs.md)
- [Vue 3](https://surveyjs.io/form-library/examples/paging-in-matrices/vue3js.md)
- [jQuery](https://surveyjs.io/form-library/examples/paging-in-matrices/jquery.md)
- [Vanilla JS](https://surveyjs.io/form-library/examples/paging-in-matrices/vanillajs.md)
