---
title: Tabbed Interface for Duplicate Group of Fields
product: Form Library
description: With SurveyJS, you can set up dynamic forms with groups of fields that repeat. Enable tabs render mode to display tabs for each duplicate group entry. Check our this free JavaScript demo showcasing the duplicate group option to learn more.
framework: React
source: https://surveyjs.io/form-library/examples/tabbed-interface-for-duplicate-group-option/reactjs
index: https://surveyjs.io/form-library/examples/overview.md
---

# Tabbed Interface for Duplicate Group of Fields (React)

A Dynamic Panel displays a group of repeating form fields that respondents can duplicate on the fly. Dynamic Panels support a tabbed interface, where users can switch between duplicate groups using tabs. This demo shows how to enable and configure the tabbed UI.

## Create a Dynamic Panel

For information on how to create and configure a Dynamic Panel, refer to the following demo:

[Dynamic Panel with Repeating Group of Fields](/form-library/examples/duplicate-group-of-fields-in-form/ (linkStyle))

## Enable the Tab View and Configure Tab Titles

To enable the tab view, set the [`displayMode`](https://surveyjs.io/form-library/documentation/api-reference/dynamic-panel-model#displayMode) property to `"tab"`. Once the tabbed UI is activated, specify a custom template for tab titles using the [`templateTabTitle`](/form-library/documentation/api-reference/dynamic-panel-model#templateTabTitle) property. Your template can include the `{panelIndex}` and `{visiblePanelIndex}` placeholders that contain panel indices within the collections of all or only visible panels, respectively. These indices start with 1. If you do not specify the `templateTabTitle` property, tab titles are constructed according to the following pattern: Panel 1, Panel 2, Panel 3, and so on.

In this demo, tab titles display selected countries. Until you select a country, a new tab displays the "New Vacation" title. This logic is implemented using an invisible [Expression](https://surveyjs.io/form-library/examples/expression-question-for-dynamic-form-calculations/) form field. The `templateTabTitle` property is bound to this Expression. If you want to customize an individual tab title, handle [`SurveyModel`](/form-library/documentation/api-reference/survey-data-model)'s [`onGetDynamicPanelTabTitle`](/form-library/documentation/api-reference/survey-data-model#onGetDynamicPanelTabTitle) event (not used in this demo).

## 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";

function SurveyComponent() {
    const survey = new Model(json);
    survey.onComplete.add((sender, options) => {
        console.log(JSON.stringify(sender.data, null, 3));
    });
    survey.onGetDynamicPanelTabTitle.add((_, options) => {
        if (options.title) {
            // Customize a tab title here
        }
    });
    return (<Survey model={survey} />);
}

export default SurveyComponent;
```

### `src/index.css`

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

### `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": "paneldynamic",
      "name": "vacation-info",
      "title": "Enter information about your vacations",
      "displayMode": "tab",
      "templateTabTitle": "{panel.tabTitle}",
      "panelCount": 1,
      "maxPanelCount": 10,
      "confirmDelete": true,
      "templateElements": [
        {
          "type": "expression",
          "name": "tabTitle",
          "visible": false,
          "expression": "iif({panel.country} empty, 'New Vacation', {panel.country})"
        },
        {
          "type": "dropdown",
          "name": "country",
          "title": "Select a country",
          "choicesByUrl": {
            "url": "https://surveyjs.io/api/CountriesExample",
            "valueName": "name"
          }
        },
        {
          "type": "text",
          "name": "start-date",
          "visibleIf": "{panel.country} notempty",
          "title": "Select a vacation start date",
          "defaultValueExpression": "today(-10)",
          "inputType": "date"
        },
        {
          "type": "text",
          "name": "end-date",
          "visibleIf": "{panel.country} notempty",
          "startWithNewLine": false,
          "title": "Select a vacation end date",
          "defaultValueExpression": "today()",
          "validators": [
            {
              "type": "expression",
              "text": "End date should be greater than start date",
              "expression": "{panel.start-date} < {panel.end-date}"
            }
          ],
          "inputType": "date"
        },
        {
          "type": "html",
          "name": "days-spent",
          "visibleIf": "{panel.country} notempty and {panel.start-date} notempty and {panel.end-date} notempty and {panel.start-date} < {panel.end-date}",
          "titleLocation": "left",
          "readOnly": true,
          "html": "<b>Days spent in {panel.country}</b>: {panel.diffdays}"
        },
        {
          "type": "expression",
          "name": "diffdays",
          "visible": false,
          "expression": "iif({panel.start-date} < {panel.end-date}, diffDays({panel.start-date}, {panel.end-date}), 0)"
        }
      ]
    }
  ]
};
```

### `src/theme.js`

```js
export const themeJson = {};
```

### `package.json`

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

## Other Frameworks

- [Angular](https://surveyjs.io/form-library/examples/tabbed-interface-for-duplicate-group-option/angular.md)
- [Vue 3](https://surveyjs.io/form-library/examples/tabbed-interface-for-duplicate-group-option/vue3js.md)
- [jQuery](https://surveyjs.io/form-library/examples/tabbed-interface-for-duplicate-group-option/jquery.md)
- [Vanilla JS](https://surveyjs.io/form-library/examples/tabbed-interface-for-duplicate-group-option/vanillajs.md)
