---
title: Single- and Multi-Select Questions with Custom Item Template
product: Form Library
description: Make your single- or multi-select question stand out with custom choice options. Implement a custom component that renders item markup to style question items. Refer to this free demo for JavaScript to learn more.
framework: React
source: https://surveyjs.io/form-library/examples/add-custom-items-to-single-and-multi-select-questions/reactjs
index: https://surveyjs.io/form-library/examples/overview.md
---

# Single- and Multi-Select Questions with Custom Item Template (React)

SurveyJS Form Library supports the usage of custom templates to change the appearance of choice options in Checkboxes, Radio Button Group, and other single- or multi-select question types. This demo shows how to customize choice options using a custom template component. 

To create and apply a custom option template, follow the steps below:

1. Implement a component that renders option markup.          
    The component accepts the option configuration object as a prop. You can use its `value` and `text` properties to access the option's value to be saved in survey results and display text. 

2. Register the component so that it can be accessed by name.         
    In HTML/CSS/JavaScript projects, register the component in `ReactElementFactory` as shown in the `index.js` file.           
    In React, register the component in `ReactElementFactory` as shown in the `SurveyComponent.jsx` file.          
    In Angular, register the component in `AngularComponentFactory` as shown in the `custom-choice-item.component.ts` file.          
    In Vue.js, use [techniques native to this framework](https://vuejs.org/guide/components/registration).

3. Assign the component name to the question's [`itemComponent`](https://surveyjs.io/form-library/documentation/api-reference/questionselectbase#itemComponent) property in the survey JSON schema.

## Files

### `public/index.html`

```html
<div id="surveyElement" style="position: absolute; top: 0; left: 0; right: 0; bottom: 0; min-height: 100%; height:100%"></div>
```

### `src/SurveyComponent.jsx`

```js
import React from "react";
import { Model } from "survey-core";
import { Survey } from "survey-react-ui";
import "survey-core/survey-core.min.css";
import "./index.css";
import { json } from "./json";
import { SvgRegistry } from "survey-core";
import { ReactElementFactory, SurveyQuestionCheckboxItem, SurveyQuestionRadioItem, SurveyElementBase } from "survey-react-ui";

class CustomCheckboxItem extends SurveyQuestionCheckboxItem {    
    get item() {
        return this.props.item;
    }
    get question() {
        return this.props.question;
    }
    renderElementContent() {
        const question = this.question;
        const item = this.item;
        const itemClass = "item-label" + (question.isItemSelected(item) ? " item-label--selected" : "");
        const optionType = "checkbox";
        const icon = question.isItemSelected(item) ? "#icon-plus" : "#icon-minus";
        const handleOnChange = (event) => { question.clickItemHandler(item, event.currentTarget.checked); };
        const handleOnMouseDown = () => {
            question.onMouseDown();
        }                       
        return (
        <div role="presentation" className="item-root">
            <label className={itemClass} onMouseDown={handleOnMouseDown}>
            <input
                role="option"
                className="item-input"
                id={question.getItemId(item)}
                type={optionType}
                name={question.questionName}
                checked={this.isChecked}
                value={item.value}
                onChange={handleOnChange}
            />
            <span className="item-image">
                <svg className="item-svg">
                <use xlinkHref={icon}></use>
                </svg>
            </span>
            {SurveyElementBase.renderLocString(item.locText)}
            </label>
        </div>
        );
    }
}
class CustomRadioItem extends SurveyQuestionRadioItem {    
    get item() {
        return this.props.item;
    }   
    renderElementContent() {
        const question = this.question;
        const item = this.item;
        const itemClass = "item-label" + (question.isItemSelected(item) ? " item-label--selected" : "");
        const optionType = "radio";
        const icon = question.isItemSelected(item) ? "#icon-plus" : "#icon-minus";
        const handleOnChange = (event) => { question.clickItemHandler(item, event.currentTarget.checked); };
        const handleOnMouseDown = () => {
            question.onMouseDown();
        }                      
        return (
        <div role="presentation" className="item-root">
            <label className={itemClass} onMouseDown={handleOnMouseDown}>
            <input
                role="option"
                className="item-input"
                id={question.getItemId(item)}
                type={optionType}
                name={question.questionName}
                checked={this.isChecked}
                value={item.value}
                onChange={handleOnChange}
            />
            <span className="item-image">
                <svg className="item-svg">
                <use xlinkHref={icon}></use>
                </svg>
            </span>
            {SurveyElementBase.renderLocString(item.locText)}
            </label>
        </div>
        );
    }
}


ReactElementFactory.Instance.registerElement(
    "custom-checkbox-item",
    (props) => {
        return React.createElement(CustomCheckboxItem, props);
    }
);
ReactElementFactory.Instance.registerElement(
    "custom-radio-item",
    (props) => {
        return React.createElement(CustomRadioItem, props);
    }
);

const svgPlus = '<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M30 16H17V3H16V16H3V17H16V30H17V17H30V16Z" fill="#19B394"/></svg>';
const svgMinus = '<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M30 16H3V17H30V16Z" fill="#FF9814"/></svg>';
SvgRegistry.registerIcon("icon-plus", svgPlus);
SvgRegistry.registerIcon("icon-minus", svgMinus);
function SurveyComponent() {
    const survey = new Model(json);
    survey.onComplete.add((sender, options) => {
        console.log(JSON.stringify(sender.data, null, 3));
    });
    return (<Survey model={survey} />);
}

export default SurveyComponent;
```

### `src/index.css`

```css
.item-input {
    display: none;
}

.item-root {
    margin-bottom: 8px;
}

.item-svg {
    padding: 4px;
    width: 32px;
    height: 32px;
}

.item-image {
    display: flex;
    flex-direction: row;
    align-items: center;
}

.item-text {
    height: 24px;
    font-family: 'Open Sans';
    font-style: normal;
    font-weight: 400;
    font-size: 16px;
    line-height: 24px;
    color: #161616;
    user-select: none;
}

.item-label {
    box-sizing: border-box;
    display: flex;
    flex-direction: row;
    align-items: center;
    padding: 4px 32px 4px 16px;
    gap: 12px;
    height: 48px;
    width: fit-content;
    background: rgba(255, 152, 20, 0.1);
    border: 1px solid #ff9814;
    border-radius: 100px;
    margin-bottom: 12px;
}

.item-label.item-label--selected {
    background: rgba(25, 179, 148, 0.1);
    border: 1px solid #19b394;
    border-radius: 100px;
}

.question-note {
    white-space: initial;
}
```

### `src/index.js`

```js
import React from "react";
import { createRoot } from "react-dom/client";
import SurveyComponent from "./SurveyComponent";

const root = createRoot(document.getElementById("surveyElement"));
root.render(<SurveyComponent />);
```

### `src/json.js`

```js
export const json = {
  "elements": [
    {
      "type": "radiogroup",
      "name": "singleselect",
      "title": "Single-select question with a custom item template",
      "itemComponent": "custom-radio-item",
      "showOtherItem": true,
      "choices": [ "Item 1", "Item 2", "Item 3" ]
    },
    {
      "type": "checkbox",
      "name": "multiselect",
      "title": "Multi-select question with a custom item template",
      "itemComponent": "custom-checkbox-item",
      "showOtherItem": true,
      "showSelectAllItem": true,
      "choices": [ "Item 1", "Item 2", "Item 3" ]
    }
  ]
};
```

### `package.json`

```json
{
  "dependencies": {
    "react": "latest",
    "react-dom": "latest",
    "babel": "latest",
    "survey-core": "latest",
    "survey-react-ui": "latest"
  },
  "devDependencies": {
    "react-scripts": "latest"
  }
}
```

## Other Frameworks

- [Angular](https://surveyjs.io/form-library/examples/add-custom-items-to-single-and-multi-select-questions/angular.md)
- [Vue 3](https://surveyjs.io/form-library/examples/add-custom-items-to-single-and-multi-select-questions/vue3js.md)
- [Vanilla JS](https://surveyjs.io/form-library/examples/add-custom-items-to-single-and-multi-select-questions/vanillajs.md)
