---
title: Collaborative Survey Review
product: Form Library
description: Facilitate the feedback process with collaborative review mode, a commenting feature that allows users to collect insightful comments from survey reviewers. Learn how to display a completed survey in read-only format and incorporate editable comment fields after each survey question, enabling reviewers to provide targeted feedback. View this free demo for JavaScript to learn more.
framework: Angular
source: https://surveyjs.io/form-library/examples/survey-review-mode/angular
index: https://surveyjs.io/form-library/examples/overview.md
---

# Collaborative Survey Review (Angular)

Collaborative survey review is a commenting feature that enables survey reviewers to engage with user responses in a more meaningful way and enhance the feedback loop. With the review mode enabled, survey creators or administrators can use editable text entry fields to leave comments for individual answers given by users. Every comment is then attached to its corresponding answer. In order to prevent answer modifications, reviewers access a completed survey in read-only state.

To display a survey in review mode, follow the steps below:

1. Populate form fields.\
Assign an object with respondent answers to `SurveyModel`'s [`data`](https://surveyjs.io/form-library/documentation/api-reference/survey-data-model#data) property.

1. Set questions to read-only state.\
Iterate through survey questions and enable their [`readOnly`](https://surveyjs.io/form-library/documentation/api-reference/question#readOnly) property.

1. Add comment fields.\
Call `PageModel`'s [`addNewQuestion(type, name)`](https://surveyjs.io/form-library/documentation/api-reference/page-model#addNewQuestion) method to add new questions of the [`"comment"` type](https://surveyjs.io/form-library/documentation/api-reference/comment-field-model).

For more information, view code listings for Angular, React, Vue, jQuery, or Vanilla JavaScript.

## Files

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

```ts
export const json = {
  "title": "Training Feedback Survey: Evaluation of Recent Training Program",
  "description": "Thank you for participating in this training program. Your feedback is essential in helping us enhance the quality of our training initiatives. Please take a moment to provide your insights on the training sessions you attended.",
  "elements": [
    {
      "type": "rating",
      "name": "relevance",
      "title": "How well did the training content align with the stated objectives?",
      "autoGenerate": false,
      "rateValues": [
        {
          "value": 5,
          "text": "Extremely Well"
        },
        {
          "value": 4,
          "text": "Very Well"
        },
        {
          "value": 3,
          "text": "Moderately Well"
        },
        {
          "value": 2,
          "text": "Slightly Well"
        },
        {
          "value": 1,
          "text": "Not Well at All"
        }
      ],
      "displayMode": "buttons"
    },
    {
      "type": "radiogroup",
      "name": "clarity",
      "title": "Did the training materials (presentation slides, handouts) support your understanding of the content?",
      "choices": [
        {
          "value": 5,
          "text": "Strongly Agree"
        },
        {
          "value": 4,
          "text": "Agree"
        },
        {
          "value": 3,
          "text": "Neutral"
        },
        {
          "value": 2,
          "text": "Disagree"
        },
        {
          "value": 1,
          "text": "Strongly Disagree"
        }
      ]
    },
    {
      "type": "checkbox",
      "name": "relevantTopics",
      "title": "Please select the training topics you found most relevant",
      "choices": [
        {
          "value": "communication",
          "text": "Communication Skills"
        },
        {
          "value": "timeManagement",
          "text": "Time Management"
        },
        {
          "value": "collaboration",
          "text": "Team Collaboration"
        },
        {
          "value": "stressManagement",
          "text": "Stress Management"
        }
      ],
      "showOtherItem": true
    },
    {
      "type": "comment",
      "name": "suggestions",
      "title": "What suggestions do you have for improving the training structure and content?",
      "maxLength": 500
    },
    {
      "type": "radiogroup",
      "name": "readyToRecommend",
      "title": "Would you recommend this training program to colleagues or peers?",
      "choices": [
        {
          "value": 5,
          "text": "Definitely"
        },
        {
          "value": 4,
          "text": "Likely"
        },
        {
          "value": 3,
          "text": "Neutral"
        },
        {
          "value": 2,
          "text": "Unlikely"
        },
        {
          "value": 1,
          "text": "Definitely Not"
        }
      ]
    }
  ]
};
```

### `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);
        // Assign a respondent's answers to a survey
        survey.data = {
          "relevance": 3,
          "clarity": 4,
          "relevantTopics": [
            "communication",
            "collaboration",
            "stressManagement"
          ],
          "suggestions": "I suggest incorporating more real-life examples to illustrate concepts and breaking down complex topics into smaller modules for better comprehension.",
          "readyToRecommend": 4
        };
        
        const allVisibleQuestions = survey.getAllQuestions(true);
        // Set all questions into read-only state
        allVisibleQuestions.forEach(q => q.readOnly = true);
        
        // Add comment fields to all survey questions
        function getFeedbackName (q) {
          return q.name + "_feedback";
        }
        
        allVisibleQuestions.forEach(q => {
          const index = q.parent.elements.indexOf(q) + 1;
          const comment = q.parent.addNewQuestion(
            "comment",
            getFeedbackName(q),
            index
          );
          comment.showNumber = false;
          comment.title = "Feedback for: " + q.title;
          comment.visible = true;
        });
        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/survey-review-mode/reactjs.md)
- [Vue 3](https://surveyjs.io/form-library/examples/survey-review-mode/vue3js.md)
- [jQuery](https://surveyjs.io/form-library/examples/survey-review-mode/jquery.md)
- [Vanilla JS](https://surveyjs.io/form-library/examples/survey-review-mode/vanillajs.md)
