---
title: Context Actions in Element Titles
product: Form Library
description: Add a button to a question, panel, or page title to provide your respondents with extra details on how to fill out a form or answer certain questions. View this free demo for JavaScript to learn more.
framework: Angular
source: https://surveyjs.io/form-library/examples/modify-titles-of-survey-elements/angular
index: https://surveyjs.io/form-library/examples/overview.md
---

# Context Actions in Element Titles (Angular)

In SurveyJS, the titles of questions, panels, and pages can display buttons that allow your respondents to perform custom actions. For instance, this demo shows how to add a custom action button that changes the visibility of question descriptions. Click the question mark icon to see this functionality in action.

## Add Title Actions

To add title actions to a question, panel, or page, handle one of the following [`SurveyModel`](https://surveyjs.io/form-library/documentation/api-reference/survey-data-model) events:

- [`onGetQuestionTitleActions`](https://surveyjs.io/form-library/documentation/api-reference/survey-data-model#onGetQuestionTitleActions)
- [`onGetPanelTitleActions`](https://surveyjs.io/form-library/documentation/api-reference/survey-data-model#onGetPanelTitleActions)
- [`onGetPageTitleActions`](https://surveyjs.io/form-library/documentation/api-reference/survey-data-model#onGetPageTitleActions)

Each event has the `options.actions` parameter that accepts an array of [`IAction`](https://surveyjs.io/form-library/documentation/api-reference/iaction) objects. Within these objects, you can specify an action's unique [`id`](https://surveyjs.io/form-library/documentation/api-reference/iaction#id), button text ([`title`](https://surveyjs.io/form-library/documentation/api-reference/iaction#title)) or icon ([`iconName`](https://surveyjs.io/form-library/documentation/api-reference/iaction#iconName)), a function to execute when users click the button ([`action`](https://surveyjs.io/form-library/documentation/api-reference/iaction#action)), and other properties. This example demonstrates the `onGetQuestionTitleActions` event. The other two events are handled in the same manner.

## Files

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

```ts
export const json = {
  "elements": [
    {
      "type": "checkbox",
      "name": "os",
      "title": "What operating system(s) do you use on your work computer(s)?",
      "description": "Please select all that apply.",
      "descriptionLocation": "hidden",
      "choices": [ "Windows", "Linux", "Macintosh OSX" ],
      "showOtherItem": true,
      "otherText": "Other (specify)"
    },
    {
      "type": "checkbox",
      "name": "languages",
      "title": "What programming language(s) do you use at work?",
      "description": "Please select all that apply but no more than three languages.",
      "descriptionLocation": "hidden",
      "choices": [
        "JavaScript", "Java", "Python", "CSS",
        "PHP", "Ruby", "C++", "C",
        "Shell", "C#", "Objective-C", "R",
        "VimL", "Go", "Perl", "CoffeeScript",
        "TeX", "Swift", "Scala", "Emacs Lisp",
        "Haskell", "Lua", "Clojure", "MATLAB",
        "Arduino", "Makefile", "Groovy", "Puppet",
        "Rust", "PowerShell"
      ],
      "showOtherItem": true,
      "otherText": "Other (specify)",
      "colCount": 4,
      "maxSelectedChoices": 3
    }
  ]
};
```

### `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/icons.js`

```js
export const iconDescriptionShowSvg = '<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 1C5.9 1 1 5.9 1 12C1 18.1 5.9 23 12 23C18.1 23 23 18.1 23 12C23 5.9 18.1 1 12 1ZM12 21C7 21 3 17 3 12C3 7 7 3 12 3C17 3 21 7 21 12C21 17 17 21 12 21ZM13.3 16.8C13.4 17 13.4 17.2 13.4 17.4C13.4 17.8 13.2 18.2 13 18.5C12.7 18.8 12.3 18.9 11.9 18.9C11.5 18.9 11.1 18.7 10.8 18.5C10.5 18.2 10.4 17.8 10.4 17.4C10.4 17 10.6 16.6 10.8 16.3C11.1 16 11.5 15.8 11.9 15.8C12.5 15.9 13 16.2 13.3 16.8ZM16 9.3C16 10.4 15.5 11.2 14.6 11.9C14.4 12.1 14.1 12.2 13.9 12.4L13.3 12.8C13 13 12.9 13.1 12.9 13.1C12.8 13.2 12.8 13.3 12.8 13.4C12.8 13.6 12.7 13.8 12.7 14.1V14.4V14.5C12.6 14.7 12.4 14.9 12.2 15C12 15.1 11.9 15.1 11.8 15.1H11.7C11.6 15.1 11.6 15.1 11.5 15.1C11.3 15 11.1 14.9 11 14.8C10.9 14.6 10.7 14.4 10.7 14.1C10.6 13.8 10.5 13.6 10.5 13.3C10.5 13 10.6 12.7 10.7 12.5C10.8 12.3 11 12.1 11.2 11.9C11.4 11.7 11.6 11.6 11.8 11.5L12.4 11.2C13 10.9 13.2 10.7 13.3 10.6C13.6 10.3 13.7 9.9 13.7 9.5C13.7 9.1 13.6 8.7 13.3 8.5C12.8 8 12.4 7.9 12 7.9C10.9 7.9 10.6 8.4 10.6 8.8C10.4 9.3 10.4 9.4 10.4 9.4V9.6C10.4 9.7 10.4 9.7 10.4 9.8L10.5 10.2L10.2 10.3C9.6 10.6 9.1 10.6 8.7 10.4C8.6 10.3 8.4 10.1 8.3 10C8.1 9.7 8 9.4 8 9C8 8.6 8.1 8.3 8.2 8C8.3 7.7 8.5 7.5 8.7 7.3C8.9 7.1 9.1 6.9 9.4 6.7C9.7 6.6 10 6.4 10.3 6.3C11.5 5.9 12.7 5.9 13.6 6.1C14.1 6.2 14.5 6.4 14.9 6.6C15.6 7.3 16 8.1 16 9.3Z" /></svg>';

export const iconDescriptionHideSvg = '<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M2.3 3.7L3.6 5C2 6.9 1 9.3 1 12C1 18.1 5.9 23 12 23C14.7 23 17.1 22 19 20.4L20.3 21.7L21.7 20.3L3.7 2.3L2.3 3.7ZM12 21C7 21 3 17 3 12C3 9.9 3.7 7.9 5 6.4L10.8 12.2C10.7 12.3 10.6 12.4 10.6 12.5C10.5 12.7 10.4 13 10.4 13.3C10.4 13.6 10.5 13.9 10.6 14.1C10.7 14.3 10.8 14.5 10.9 14.8C11 15 11.2 15.1 11.4 15.1C11.5 15.1 11.5 15.1 11.6 15.1H11.7C11.8 15.1 11.9 15.1 12.1 15C12.4 14.9 12.6 14.7 12.6 14.5V14.4V14.1L17.5 19C16.1 20.3 14.1 21 12 21ZM7.8 4.1L6.3 2.6C8 1.6 9.9 1 12 1C18.1 1 23 5.9 23 12C23 14.1 22.4 16 21.4 17.7L19.9 16.2C20.6 15 21 13.5 21 12C21 7 17 3 12 3C10.5 3 9 3.4 7.8 4.1ZM13.5 9.8C13.5 9.7 13.6 9.6 13.6 9.4C13.6 9 13.5 8.6 13.2 8.4C12.8 8 12.4 7.9 12 7.9C11.9 7.9 11.8 7.9 11.6 7.9L10.1 6.4C10.2 6.4 10.2 6.3 10.3 6.3C11.5 5.9 12.7 5.9 13.6 6.1C14.1 6.2 14.5 6.4 14.9 6.6C15.6 7.3 16 8.1 16 9.3C16 10.1 15.7 10.8 15.2 11.4L13.5 9.8ZM11.8 15.9C12.5 15.9 13 16.2 13.3 16.8C13.4 17 13.4 17.2 13.4 17.4C13.4 17.8 13.2 18.2 13 18.5C12.7 18.8 12.3 18.9 11.9 18.9C11.5 18.9 11.1 18.7 10.8 18.5C10.5 18.2 10.4 17.8 10.4 17.4C10.4 17 10.6 16.6 10.8 16.3C11 16 11.4 15.9 11.8 15.9Z" /></svg>';
```

### `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";
import { SvgRegistry } from "survey-core";
import { iconDescriptionShowSvg, iconDescriptionHideSvg } from "./icons";

// Register custom icons
SvgRegistry.registerIcon("icon-description-show", iconDescriptionShowSvg);
SvgRegistry.registerIcon("icon-description-hide", iconDescriptionHideSvg);
@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.onGetQuestionTitleActions.add((_, options) => {
            options.actions = [{
                id: "show-description",
                tooltip: "Show description",
                iconName: "icon-description-show",
                action: (action) => {
                    const q = options.question;
                    q.descriptionLocation = q.descriptionLocation !== "hidden" ? "hidden" : "underTitle";
                    action.iconName = q.descriptionLocation !== "hidden" ? "icon-description-hide" : "icon-description-show";
                }
            }];
        });
        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/modify-titles-of-survey-elements/reactjs.md)
- [Vue 3](https://surveyjs.io/form-library/examples/modify-titles-of-survey-elements/vue3js.md)
- [jQuery](https://surveyjs.io/form-library/examples/modify-titles-of-survey-elements/jquery.md)
- [Vanilla JS](https://surveyjs.io/form-library/examples/modify-titles-of-survey-elements/vanillajs.md)
