---
title: Multi-Select Matrix
product: Form Library
description: Explore the versatility of multi-select matrix questions with our demo using the SurveyJS Form Library. Learn how to configure and implement multiple rows and columns in a matrix question with multiple responses. View an example for JavaScript to learn more.
framework: Angular
source: https://surveyjs.io/form-library/examples/multi-select-matrix-question/angular
index: https://surveyjs.io/form-library/examples/overview.md
---

# Multi-Select Matrix (Angular)

A Multi-Select Matrix, also known as a matrix question with multiple responses, is a type of survey or form question that presents a grid or table structure where respondents can select multiple answers for each row or column combination. This demo shows a Multi-Select Matrix question example and describes how to configure multiple rows and columns selection in a matrix using the SurveyJS Form Library.

## Create a Multi-Select Matrix Question

To add a Multi-Select Matrix question to your survey, create an object with the `type` property set to `"matrixdropdown"` 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/matrix-table-with-dropdown-list#title) and a unique [`name`](https://surveyjs.io/form-library/documentation/api-reference/matrix-table-with-dropdown-list#name) that identifies the matrix question. Optionally, you can specify a [`description`](https://surveyjs.io/form-library/documentation/api-reference/matrix-table-with-dropdown-list#description) to place under the title.

## Configure Matrix Columns

To configure matrix columns, populate the [`columns`](https://surveyjs.io/form-library/documentation/api-reference/matrix-table-with-dropdown-list#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 a column's [`cellType`](https://surveyjs.io/form-library/documentation/api-reference/multi-select-matrix-column-values#cellType) property to specify the editor type, which is Dropdown by default.

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.

Columns also support conditional logic. Use the [`visibleIf`](https://surveyjs.io/form-library/documentation/api-reference/multi-select-matrix-column-values#visibleIf), [`requiredIf`](https://surveyjs.io/form-library/documentation/api-reference/multi-select-matrix-column-values#requiredIf), [`enableIf`](https://surveyjs.io/form-library/documentation/api-reference/multi-select-matrix-column-values#enableIf), [`setValueIf`](https://surveyjs.io/form-library/documentation/api-reference/multi-select-matrix-column-values#setValueIf), and [`resetValueIf`](https://surveyjs.io/form-library/documentation/api-reference/multi-select-matrix-column-values#resetValueIf) properties to dynamically show or hide a column, mark it as required, enable or disable its editors, set or reset the value of its cells. In this demo, the `enableIf` property is used to enable column editors only if a respondent answers "Yes" to the "Do you use the framework?" question. 

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.

## Configure Matrix Rows

To configure matrix rows, populate the `rows` array. Similar to `columns`, the `rows` array contains objects, and each object configures a single row. However, row objects can have only two properties:

```js
{
  "value": any, // A value to be saved in the survey results
  "text": string, // A row title. When `text` is undefined, `value` is used.
}
```

Refer to the `survey.json` file listing for a code example.

## Transpose Columns to Rows

A Multi-Select Matrix allows you to transpose its content, i.e. display columns as rows, and vice versa. If you find that your matrix would benefit from transposing, set the matrix's [`transposeData`](https://surveyjs.io/form-library/documentation/api-reference/dynamic-matrix-table-question-model#transposeData) property to `true`, as shown in this demo.

## Files

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

```ts
export const json = {
  "elements": [
    {
      "type": "matrixdropdown",
      "name": "framework-ratings",
      "title": "Please leave your feedback about JavaScript frameworks",
      "columnMinWidth": "130px",
      "columns": [
        {
          "name": "usage",
          "title": "Do you use the framework?",
          "cellType": "radiogroup",
          "choices": [ "Yes", "No" ],
          "defaultValue": "Yes"
        },
        {
          "name": "experience",
          "title": "How long have you used it?",
          "choices": [
            { "text": "3-5 years", "value": 4 },
            { "text": "1-2 years", "value": 1.5 },
            { "text": "Less than a year", "value": 0.5 }
          ],
          "enableIf": "{row.usage} = 'Yes'"
        },
        {
          "name": "strengths",
          "title": "Which are the framework's main strengths?",
          "cellType": "checkbox",
          "choices": [
            "Scalability",
            "Performance",
            "Complete functionality",
            "Learning materials",
            "Strong community"
          ],
          "colCount": 1,
          "enableIf": "{row.usage} = 'Yes'"
        },
        {
          "name": "free-form-feedback",
          "title": "Describe what you like and dislike about the framework",
          "cellType": "comment",
          "enableIf": "{row.usage} = 'Yes'",
          "allowResize": false
        },
        {
          "name": "rating",
          "title": "Rate your experience with the framework",
          "cellType": "rating",
          "rateValues": [
            { "text": "Excellent", "value": 5 },
            { "text": "Good", "value": 4 },
            { "text": "Average", "value": 3 },
            { "text": "Fair", "value": 2 },
            { "text": "Poor", "value": 1 }
          ],
          "displayMode": "dropdown",
          "enableIf": "{row.usage} = 'Yes'"
        }
      ],
      "rows": [
        { "text": "Angular", "value": "angular" },
        { "text": "React", "value": "react" },
        { "text": "Vue.js", "value": "vue" }
      ],
      "transposeData": true
    }
  ]
};
```

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