---
title: Create Custom Adorners
product: Survey Creator
description: Custom adorner actions ensure even easier management of your survey elements right on the design surface. View a free demo example for JavaScript to learn more.
framework: jQuery
source: https://surveyjs.io/survey-creator/examples/create-custom-adorners/jquery
index: https://surveyjs.io/survey-creator/examples/overview.md
---

# Create Custom Adorners (jQuery)

Adorners are interactive design-surface controls placed within a question area. Adorners allow users to quickly execute the most common actions: duplicate a question, mark a question as required, or delete it. This demo shows how to customize built-in adorners and create custom adorners.

## Create a Button Adorner

A button adorner executes a simple action on click. To create a button adorner, follow the steps below:

1. Handle the [`onElementGetActions`](https://surveyjs.io/survey-creator/documentation/api-reference/survey-creator#onElementGetActions) event.        
This event is raised when Survey Creator renders adorners on the design surface.

2. Create an `Action` instance.        
Pass an [`IAction`](https://surveyjs.io/form-library/documentation/api-reference/iaction) configuration object to the `Action` constructor. This object describes an action item rendered as a button adorner.

3. Add the `Action` instance to the `options.actions` array.       

This demo shows how to create a custom Read-Only button adorner. Refer to the code listing for more information. 

## Create a Drop-Down Adorner

A drop-down adorner opens a drop-down menu on click. The following instructions describe how to create a drop-down adorner:

1. Handle the [`onElementGetActions`](https://surveyjs.io/survey-creator/documentation/api-reference/survey-creator#onElementGetActions) event.

2. Create an `Action` instance.     
Drop-down adorners have a dedicated `createDropdownActionModel()` helper function that generates `Action` instances based on [`IAction`](https://surveyjs.io/form-library/documentation/api-reference/iaction) and `IActionDropdownPopupOptions` configuration objects. Import this function from `survey-core` and pass `IAction` and `IActionDropdownPopupOptions` objects to it.

3. Add the `Action` instance to the `options.actions` array.

In this demo, a custom Sort Order drop-down adorner lets users specify the order of items in choice-based questions. For details about implementation, view code listings for Angular, React, Vue, jQuery, or Vanilla JavaScript.

## Files

### `public/index.html`

```html
<!-- Uncomment the following lines to enable Ace Editor in the JSON Editor tab -->
<!-- 
<script src="https://unpkg.com/ace-builds/src-min-noconflict/ace.js"></script>
<script src="https://unpkg.com/ace-builds/src-min-noconflict/ext-searchbox.js"></script>
<script src="https://unpkg.com/ace-builds/src-min-noconflict/theme-clouds_midnight.js"></script>
-->

<div id="surveyCreatorContainer" style="position: absolute; height: 100%; width: 100%"></div>
```

### `src/index.css`

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

### `src/survey_json.js`

```js
export const surveyJSON = {
  "elements": [
    {
      "type": "text",
      "name": "Single-Line Input"
    },
    {
      "type": "checkbox",
      "name": "Checkboxes",
      "choices": [
        "Item 1",
        "Item 2",
        "Item 3"
      ]
    }
  ]
};
```

### `src/index.js`

```js
import { SurveyCreator } from "survey-creator-js";
import "survey-core/survey.i18n";
import "survey-creator-core/survey-creator-core.i18n";
import { Serializer, Action, ComputedUpdater, createDropdownActionModel, QuestionSelectBase } from "survey-core";
import { surveyJSON } from "./survey_json";
import "survey-core/survey-core.css";
import "survey-creator-core/survey-creator-core.css";
import "./index.css";

import SurveyTheme from "survey-core/themes";
import { registerCreatorTheme } from "survey-creator-core";

registerCreatorTheme(SurveyTheme); // Add predefined Survey Creator UI themes

const creator = new SurveyCreator();
function createReadOnlyAction(question) {
    return new Action({
        id: "readOnly",
        active: new ComputedUpdater(() => question.readOnly),
        title: "Read-Only",
        iconName: "icon-editing-finish",        
        action: () => {
            question.readOnly = !question.readOnly;
        },
        // Place Read-Only before the Duplicate adorner whose `visibleIndex` is 10
        visibleIndex: 9
    });
}
function createSortOrderAction(selectBaseQuestion) {
    const sortOrderOptions = [
        { id: "none", title: "None" },
        { id: "asc", title: "Ascending" },
        { id: "desc", title: "Descending" },
        { id: "random", title: "Random" }
    ];
    function getTitle(selectBaseQuestion) {
        return sortOrderOptions.filter(
          (order) => order.id === selectBaseQuestion.choicesOrder
        )[0].title;
    }
    return createDropdownActionModel(
        {
            id: "sortOrder",   
            // Update a title caption to display the currently selected choice order
            title: new ComputedUpdater(() => {
                return getTitle(selectBaseQuestion);

            }),
            // Place Sort Order before the custom Read-Only adorner
            visibleIndex: 8,
            // With the `sv-action--convertTo` class, a drop-down adorner
            // displays the selected value instead of the title
            css: "sv-action--convertTo sv-action-bar-item--secondary"            
        },
        {
            items: sortOrderOptions,
            allowSelection: true,
            onSelectionChanged: (item) => {
                selectBaseQuestion.choicesOrder = item.id;
            },
            verticalPosition: "top",
            horizontalPosition: "center"
        }
    );
}
creator.onElementGetActions.add((_, options) => {
    const question = options.element;
    // Hide the titles of built-in adorners, except for "Element Type" and "Input Type"
    options.actions.forEach((action) => {
        if (["convertTo", "convertInputType"].indexOf(action.id) < 0) {
            action.showTitle = false;
        }
    });
    // Create a "Read-only" adorner for all question types
    const readOnlyAdorner = createReadOnlyAction(question);
    options.actions.push(readOnlyAdorner);

    // Create a "Sort Order" adorner for all choice-based questions
    if (question instanceof QuestionSelectBase) {
        const sortOrderAdorner = createSortOrderAction(question);
        options.actions.push(sortOrderAdorner);
    }
});

creator.JSON = surveyJSON;
creator.render("surveyCreatorContainer");
```

### `package.json`

```json
{
  "dependencies": {
    "jquery": "latest",
    "survey-core": "latest",
    "survey-js-ui": "latest",
    "survey-creator-core": "latest",
    "survey-creator-js": "latest"
  },
  "devDependencies": {
    "react-scripts": "latest"
  }
}
```

## Other Frameworks

- [Angular](https://surveyjs.io/survey-creator/examples/create-custom-adorners/angular.md)
- [React](https://surveyjs.io/survey-creator/examples/create-custom-adorners/reactjs.md)
- [Vue 3](https://surveyjs.io/survey-creator/examples/create-custom-adorners/vue3js.md)
- [Vanilla JS](https://surveyjs.io/survey-creator/examples/create-custom-adorners/vanillajs.md)
