---
title: Runtime Toolbox Customization
product: Survey Creator
description: Enable your end users to customize the toolbox by adding and removing its elements, e.g., question and panel types. View a free demo for JavaScript.
framework: Vanilla JS
source: https://surveyjs.io/survey-creator/examples/customize-toolbox-at-runtime/vanillajs
index: https://surveyjs.io/survey-creator/examples/overview.md
---

# Runtime Toolbox Customization (Vanilla JS)

Survey Creator users can change the collection of available toolbox items and add new ones at runtime. In this demo, questions on the design surface have a **Save to Toolbox** button. Clicking it saves the current question configuration as a new toolbox item. To manage toolbox items, click the **Customize Toolbox** button in the toolbar. This button opens a pop-up window where you can show and hide any toolbox items and delete unnecessary custom items. Please note that runtime toolbox customization is not supported out of the box and requires implementation by your development team, as shown in this example.

## Save Custom Items to the Toolbox

Perform the following steps to let users save custom question configurations to the Toolbox:

1. Create a toolbox item configuration object.          
A toolbox item configuration object should implement the [`IQuestionToolboxItem`](/survey-creator/documentation/api-reference/iquestiontoolboxitem) interface.

1. Add the custom item to the Toolbox.          
Access the [`QuestionToolbox`](/survey-creator/documentation/api-reference/questiontoolbox) instance using Survey Creator's [`toolbox`](/survey-creator/documentation/api-reference/survey-creator#toolbox) property and call the [`addItem(item, index)`](/survey-creator/documentation/api-reference/questiontoolbox#addItem) method on this instance.

1. Add a UI element that saves custom toolbox items.
You can use any UI element that suits your use case. This demo uses the [`onElementGetActions`](/survey-creator/documentation/api-reference/survey-creator#onElementGetActions) event to add a custom button ([adorner](/survey-creator/documentation/end-user-guide/user-interface#adorners)) to each question on the design surface. A click on this button call a `saveCustomItem` function that creates a `IQuestionToolboxItem` object and adds it to the Toolbox.

Refer to the Code tab for a code example. Code lines that implement the steps above are marked with comments.

## Manage Toolbox Items

If you want to let users add and remove items from the Toolbox, follow the instructions below:

1. Create a survey that displays the dialog content.        
A pop-up dialog is built upon a regular survey from [SurveyJS Form Library](/form-library/documentation/overview). The survey displays a list of predefined toolbox items using a [Checkboxes](/form-library/examples/create-checkboxes-question-in-javascript/) question and allows users to delete unnecessary custom toolbox items using a [Dynamic Matrix](/form-library/examples/dynamic-matrix-add-new-rows/) question. Implement a function that returns the survey JSON schema (view the `createToolboxSetupSurveyJson()` function in code listings).

1. Populate the survey with lists of predefined and custom toolbox items.       
Access an array of toolbox [`items`](/survey-creator/documentation/api-reference/questiontoolbox#items), use it to prepare data arrays for the Checkboxes and Dynamic Matrix questions, and assign these arrays to the questions' [`value`](/form-library/documentation/api-reference/question#value) property (view the `populateToolboxSetupSurvey()` function).

1. Add a custom button that opens the dialog window.           
Configure the button by defining an [`IAction`](https://surveyjs.io/form-library/documentation/api-reference/iaction) object and passing it the `Action` constructor. This button can be added to the Survey Creator toolbar.

1. Apply the changes made in the dialog window.         
When users click Apply in the dialog window, you need to clear the Toolbox, collect selected toolbox items, and add them to the Toolbox anew (view the `showToolboxSetupPopup()` function).

## 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
.sv_main .sv_custom_header {
    display: none;
}

.setup-toolbox-popup .sd-root-modern {
    min-width: 640px;
}
```

### `src/index.js`

```js
import { SurveyCreator } from "survey-creator-js";
import "survey-core/survey.i18n";
import "survey-creator-core/survey-creator-core.i18n";
import { Model, settings, Action, JsonObject, ComputedUpdater } from "survey-core";
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();

const toolbox = creator.toolbox;
toolbox.forceCompact = false;
// #region Save Custom Items to the Toolbox 
var customItems = {};
const customCategoryName = "Custom Questions";

function saveCustomItem (element) {
  const json = new JsonObject().toJsonObject(element);
  json.type = element.getType();

  if (!!customItems[element.name]) {
    creator.notify("A toolbox item with the same name already exists", "error");
    return;
  };

  // Step 1: Prepare a toolbox item configuration object
  const item = {
      name: element.name,
      iconName: "icon-" + element.getType(),
      title: element.title,
      json: json,
      category: customCategoryName
  };
  customItems[item.name] = item;
  // Step 2: Add the custom toolbox item to the top
  toolbox.addItem(item, 0);
}

// Step 3: Add a custom adorner that saves a question configuration as a toolbox item
creator.onElementGetActions.add((_, options) => {
    if (options.element["isPage"]) return;
    const elemToAdd = options.element;
    options.actions.unshift({
        id: "save-to-toolbox",
        title: "Save to Toolbox",
        iconName: "icon-toolbox",        
        action: () => {
            saveCustomItem(elemToAdd);
        }
    });
});
// #endregion

// #region Manage Toolbox Items
const predefinedItems = {};

const defaultToolboxItems = [].concat(toolbox.items);

// Step 1: Create a survey that displays the dialog content
function createToolboxSetupSurveyJson () {
    const choices = [];
    const value = [];
    defaultToolboxItems.forEach(({ name, title, iconName, json, tooltip, category }) => {
        choices.push({ value: name, text: title });
        value.push(name);
        predefinedItems[name] = {
            name: name,
            iconName: iconName,
            json: json,
            title: title,
            tooltip: tooltip,
            category: category
        };
    });
    return {
      "showNavigationButtons": false,
      "elements": [{
        "type": "checkbox",
        "name": "predefinedItems",
        "title": "Standard questions",
        "choices": choices,
        "defaultValue": value
      }, {
        "type": "matrixdynamic",
        "name": "customItems",
        "title": "Custom Questions",
        "showHeader": false,
        "columns": [{
          "name": "enabled",
          "cellType": "boolean",
          "defaultValue": true,
          "renderAs": "checkbox",
          "width": "15px",
          "minWidth": "15px",
        }, {
          "name": "question-name",
          "cellType": "dropdown",
          "readOnly": true
        }],
        "rowCount": 0,
        "allowAddRows": false,
        "hideColumnsIfEmpty": true,
        "noRowsText": "There are no custom questions."
      }]
    };
}

function isItemUsed (name) {
  return !!toolbox.getItemByName(name);
}

// Step 2: Populate the survey with lists of predefined and custom toolbox items
function populateToolboxSetupSurvey (survey) {
    const selectedPredefinedItems = [];
    toolbox.items.forEach((item) => {
        selectedPredefinedItems.push(item.name);
    });
    const qPredefinedItems = survey.getQuestionByName("predefinedItems");
    qPredefinedItems.value = selectedPredefinedItems;

    const availableCustomItems = [];
    const selectedCustomItems = [];
    Object.keys(customItems).forEach((key) => {
        const item = customItems[key];
        availableCustomItems.push({ value: item.name, text: item.title });
        selectedCustomItems.push({
            enabled: isItemUsed(item.name),
            "question-name": item.name
        });
    });
    const qCustomItems = survey.getQuestionByName("customItems");
    qCustomItems.visible = availableCustomItems.length > 0;
    qCustomItems.choices = availableCustomItems;
    qCustomItems.value = selectedCustomItems;
    return [ qPredefinedItems, qCustomItems ];
}

// Step 3: Add a custom button that opens the dialog window with toolbox customization options
const toolboxCustomizationAction = new Action({
    id: "toolbox-customization",
    iconName: "icon-toolbox",
    tooltip: "Customize Toolbox",
    visible: new ComputedUpdater(() => {
        return creator.activeTab === "designer";
    }),
    enabled: true,
    action: () => {
        showToolboxSetupPopup();
    }
});
// Add the custom button to the top toolbar
creator.toolbarItems.push(toolboxCustomizationAction);
// Add the custom button to the bottom toolbar (visible only on mobile devices)
creator.footerToolbar.actions.push(toolboxCustomizationAction);

function showToolboxSetupPopup () {
    const toolboxSetupSurvey = new Model(createToolboxSetupSurveyJson());

    const [ qPredefinedItems, qCustomItems ] = populateToolboxSetupSurvey(toolboxSetupSurvey);

    const popupOptions = {
        title: "Configure Toolbox Items",
        componentName: "survey",
        data: { model: toolboxSetupSurvey, survey: toolboxSetupSurvey },
        cssClass: "setup-toolbox-popup",
        // Step 4: Apply the changes made in the dialog window
        onApply: () => {
            const items = [];

            // Clear the Toolbox
            toolbox.clearItems();

            // Collect selected custom toolbox items
            if (Array.isArray(qCustomItems.value)) {
                const updatedCustomQuestions = {};
                qCustomItems.value.forEach((obj) => {
                    const qName = obj["question-name"];
                    const customItem = customItems[qName];
                    updatedCustomQuestions[qName] = customItem;
                    if (obj.enabled) {
                        items.push(customItem);
                    }
                });
                customItems = updatedCustomQuestions; 
            }

            // Collect selected predefined toolbox items
            for (let key in predefinedItems) {
              if (Array.isArray(qPredefinedItems.value) && qPredefinedItems.value.indexOf(key) > -1) {
                  items.push(predefinedItems[key]);
              }
            }

            // Add the selected items to the Toolbox
            items.forEach((item) => {
                toolbox.addItem(item);
            });
            return true;
        }
    };
    settings.showDialog(popupOptions);
}
// #endregion

creator.JSON = {
  "elements": [{
    "type": "text",
    "name": "question1",
    "title": "Question 1"
  }]
}
creator.render("surveyCreatorContainer");
```

### `package.json`

```json
{
  "dependencies": {
    "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/customize-toolbox-at-runtime/angular.md)
- [React](https://surveyjs.io/survey-creator/examples/customize-toolbox-at-runtime/reactjs.md)
- [Vue 3](https://surveyjs.io/survey-creator/examples/customize-toolbox-at-runtime/vue3js.md)
- [jQuery](https://surveyjs.io/survey-creator/examples/customize-toolbox-at-runtime/jquery.md)
