---
title: Dynamic Matrix
product: Form Library
description: Learn how to create a dynamic matrix in a form to enable respondents to add or remove matrix rows as they interact with the question. This interactive demo contains code snippets for JavaScript and step-by-step setup guide.
framework: Angular
source: https://surveyjs.io/form-library/examples/dynamic-matrix-add-new-rows/angular
index: https://surveyjs.io/form-library/examples/overview.md
---

# Dynamic Matrix (Angular)

A Dynamic Matrix is an extendable input field that enables respondents to provide multiple answers within a single question in a format of a table. It organizes a set of questions or statements along dynamic rows and displays various response options along columns. On-question buttons allow users to manage the matrix content by adding or removing additional copies of dynamic rows. This demo will guide you through the process of setting up a Dynamic Matrix question using the SurveyJS Form Library.

## Create a Dynamic Matrix Question

To add a Dynamic Matrix question to your survey or form, create an object with the `type` property set to `"matrixdynamic"` and add the object to the [`elements`](https://surveyjs.io/form-library/documentation/api-reference/page-model#elements) array. Within this object, specify the question's [`title`](https://surveyjs.io/form-library/documentation/api-reference/dynamic-matrix-table-question-model#title) and a unique [`name`](https://surveyjs.io/form-library/documentation/api-reference/dynamic-matrix-table-question-model#name) that identifies the matrix question. Optionally, you can specify a [`description`](https://surveyjs.io/form-library/documentation/api-reference/dynamic-matrix-table-question-model#description) to place under the title.

## Configure Matrix Columns

To configure matrix columns, populate the [`columns`](https://surveyjs.io/form-library/documentation/api-reference/dynamic-matrix-table-question-model#columns) array. Each object in it specifies settings of a single column. For each column, define its unique [`name`](https://surveyjs.io/form-library/documentation/api-reference/multi-select-matrix-column-values#name), which will be used to access the column in code, and its [`title`](https://surveyjs.io/form-library/documentation/api-reference/multi-select-matrix-column-values#title), which will be visible to respondents.

Column cells can contain editors of different types: single- or multi-line inputs, drop-down menus, checkboxes, etc. Use the `cellType` property to specify the editor type. Define this property in an [individual column's configuration object](https://surveyjs.io/form-library/documentation/api-reference/multi-select-matrix-column-values#cellType) to apply the editor type to that particular column, or set the same property within the [matrix configuration object](https://surveyjs.io/form-library/documentation/api-reference/dynamic-matrix-table-question-model#cellType) to specify one editor type for all columns. Column-level settings override the matrix-level settings. 

Column editor types are based upon standalone question types. Depending on the selected editor type, the matrix column can have additional configuration properties inherited from the corresponding question type. For instance, Dropdown, Checkboxes, Radio Button Group, and Tag Box columns can specify the [`choices`](https://surveyjs.io/form-library/documentation/api-reference/radio-button-question-model#choices) array, similar to the question types upon which they are based.

Refer to the [`MatrixDropdownColumn`](https://surveyjs.io/form-library/documentation/api-reference/matrix-table-with-dropdown-list) API Reference section for a full list of matrix column properties.

## Limit the Row Count

A Dynamic Matrix renders two initial rows by default. If you want to change this number, set the [`rowCount`](https://surveyjs.io/form-library/documentation/api-reference/dynamic-matrix-table-question-model#rowCount) property. You can also limit the minimum and maximum number of matrix table rows. Assign these numbers to the [`minRowCount`](https://surveyjs.io/form-library/documentation/api-reference/dynamic-matrix-table-question-model#minRowCount) and [`maxRowCount`](https://surveyjs.io/form-library/documentation/api-reference/dynamic-matrix-table-question-model#maxRowCount) properties. In this demo, a Dynamic Matrix initially displays one row, which is also the minimum row count, and allows users to add up to 10 rows.

## Files

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

```ts
export const json = {
  "elements": [
    {
      "type": "matrixdynamic",
      "name": "teacher-performance",
      "title": "Teacher evaluation",
      "description": "Select a subject and indicate whether the following statements are true for the subject teacher",
      "addRowText": "Add Subject",
      "columnMinWidth": "130px",
      "cellType": "radiogroup",
      "choices": [
        { "text": "Yes", "value": 1 },
        { "text": "No", "value": -1 },
        { "text": "I don't know", "value": 0 }
      ],
      "columns": [
        {
          "name": "subject",
          "cellType": "dropdown",
          "title": "Subject",
          "isRequired": true,
          "minWidth": "300px",
          "choices": [
            "English: American Literature",
            "English: British and World Literature",
            "Math: Consumer Math",
            "Math: Practical Math",
            "Math: Developmental Algebra",
            "Math: Continuing Algebra",
            "Math: Pre-Algebra",
            "Math: Algebra",
            "Math: Geometry",
            "Math: Integrated Mathematics",
            "Science: Physical Science",
            "Science: Earth Science",
            "Science: Biology",
            "Science: Chemistry",
            "History: World History",
            "History: Modern World Studies",
            "History: U.S. History",
            "History: Modern U.S. History",
            "Social Sciences: U.S. Government and Politics",
            "Social Sciences: U.S. and Global Economics",
            "World Languages: Spanish",
            "World Languages: French",
            "World Languages: German",
            "World Languages: Latin",
            "World Languages: Chinese",
            "World Languages: Japanese"
          ]
        },
        {
          "name": "explains-objectives",
          "title": "Clearly explains the objectives"
        },
        {
          "name": "makes-class-interesting",
          "title": "Makes class interesting"
        },
        {
          "name": "uses-class-time-effectively",
          "title": "Uses class time effectively"
        },
        {
          "name": "knows-subject-matter",
          "title": "Knows the subject matter"
        },
        {
          "name": "recognizes-effort",
          "title": "Recognizes and acknowledges effort"
        },
        {
          "name": "informs-about-progress",
          "title": "Keeps me informed of my progress"
        },
        {
          "name": "encourages-different-opinions",
          "title": "Encourages and accepts different opinions"
        },
        {
          "name": "respects-students",
          "title": "Respects the students"
        },
        {
          "name": "encourages-cooperation",
          "title": "Encourages cooperation and participation"
        },
        {
          "name": "communicates-with-parents",
          "title": "Communicates with my parents"
        },
        {
          "name": "encourages-self-thinking",
          "title": "Encourages me to think for myself"
        },
        {
          "name": "negative-feedback",
          "cellType": "comment",
          "title": "Is there anything about this class that frustrates you?",
          "minWidth": "250px"
        },
        {
          "name": "positive-feedback",
          "cellType": "comment",
          "title": "What do you like best about this class and/or teacher?",
          "minWidth": "250px"
        },
        {
          "name": "improvement-feedback",
          "cellType": "comment",
          "title": "What do you wish this teacher would do differently that would improve this class?",
          "minWidth": "250px"
        }
      ],
      "rowCount": 1,
      "minRowCount": 1,
      "maxRowCount": 10
    }
  ]
};
```

### `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);
        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
<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/dynamic-matrix-add-new-rows/reactjs.md)
- [Vue 3](https://surveyjs.io/form-library/examples/dynamic-matrix-add-new-rows/vue3js.md)
- [jQuery](https://surveyjs.io/form-library/examples/dynamic-matrix-add-new-rows/jquery.md)
- [Vanilla JS](https://surveyjs.io/form-library/examples/dynamic-matrix-add-new-rows/vanillajs.md)
