DevExtreme v24.2 is now available.

Explore our newest features/capabilities and share your thoughts with us.

Your search did not match any results.

Vue Accordion

The Accordion component contains several panels displayed one under another. Users can expand or collapse these panels, which makes this component useful to present information in a limited amount of space.

DevExtreme Accessibility Compliance
DevExtreme component libraries meet a variety of WCAG and Section 508 compliance standards. To assess this demo’s accessibility level, click the Run AXE® Validation button to launch the AXE® web accessibility evaluation tool.
All trademarks or registered trademarks are property of their respective owners. AXE® Terms of Use
The overall accessibility level of your application depends on the Accordion features used.
Backend API
<template> <div id="accordion"> <DxAccordion :data-source="companies" :collapsible="collapsible" :multiple="multiple" :animation-duration="animationDuration" v-model:selected-items="selectedItems" id="accordion-container" item-title-template="itemTitle" > <template #itemTitle="{ data }"> <CustomTitle :item-data="data"/> </template> <template #item="{ data }"> <CustomItem :item-data="data"/> </template> </DxAccordion> <div class="options"> <div class="caption">Options</div> <div class="option"> <DxCheckBox v-model:value="multiple" text="Multiple enabled" /> </div> <div class="option"> <DxCheckBox v-model:value="collapsible" text="Collapsible enabled" /> </div> <div class="option"> <span>Animation duration</span> <DxSlider :min="0" :max="1000" v-model:value="animationDuration" > <DxTooltip :enabled="true" position="bottom" /> <DxLabel :visible="true"/> </DxSlider> </div> <div class="option"> <span class="caption">Selected Items</span> <DxTagBox :data-source="companies" v-model:value="selectedItems" :input-attr="{ 'aria-label': 'Company' }" :disabled="!multiple" display-expr="CompanyName" /> </div> </div> </div> </template> <script setup lang="ts"> import { ref } from 'vue'; import DxAccordion from 'devextreme-vue/accordion'; import DxTagBox from 'devextreme-vue/tag-box'; import DxCheckBox from 'devextreme-vue/check-box'; import DxSlider, { DxTooltip, DxLabel } from 'devextreme-vue/slider'; import CustomTitle from './CustomTitle.vue'; import CustomItem from './CustomItem.vue'; import service from './data.js'; const companies = service.getCompanies(); const selectedItems = ref([companies[0]]); const multiple = ref(false); const collapsible = ref(false); const animationDuration = ref(300); </script> <style scoped> #accordion { height: 700px; } #accordion .header { font-size: 20px; } #accordion .header, #accordion p { margin: 0; } #accordion-container { margin-right: 400px; } .dx-theme-material #accordion .dx-accordion-item-title { display: flex; } .dx-theme-material #accordion .header { align-self: center; } .options { padding: 20px; position: absolute; bottom: 0; right: 0; width: 340px; top: 0; background-color: rgba(191, 191, 191, 0.15); } .options > .caption { font-weight: 500; font-size: 18px; } .option { margin-top: 10px; } .option > .caption { margin-top: 10px; display: inline-block; } .option > .dx-tagbox { margin-top: 2px; } </style>
<template> <div> <div> <p> <b>{{ itemData.City }}</b> (<span>{{ itemData.State }}</span>) </p> <p> <span>{{ itemData.Zipcode }}&nbsp;</span> <span>{{ itemData.Address }}</span> </p> </div> <div> <p> Phone: <b>{{ itemData.Phone }}</b> </p> <p> Fax: <b>{{ itemData.Fax }}</b> </p> <p> Website: <a :href="itemData.Website" target="_blank" > {{ itemData.Website }} </a> </p> </div> </div> </template> <script setup lang="ts"> withDefaults(defineProps<{ itemData?: Record<string, any> }>(), { itemData: () => ({}), }); </script>
<template> <div class="header">{{ itemData.CompanyName }}</div> </template> <script setup lang="ts"> withDefaults(defineProps<{ itemData?: Record<string, any> }>(), { itemData: () => ({}), }); </script>
const companies = [{ ID: 1, CompanyName: 'Super Mart of the West', Address: '702 SW 8th Street', City: 'Bentonville', State: 'Arkansas', Zipcode: 72716, Phone: '(800) 555-2797', Fax: '(800) 555-2171', Website: 'http://www.nowebsitesupermart.dx', }, { ID: 2, CompanyName: 'Electronics Depot', Address: '2455 Paces Ferry Road NW', City: 'Atlanta', State: 'Georgia', Zipcode: 30339, Phone: '(800) 595-3232', Fax: '(800) 595-3231', Website: 'http://www.nowebsitedepot.dx', }, { ID: 3, CompanyName: 'K&S Music', Address: '1000 Nicllet Mall', City: 'Minneapolis', State: 'Minnesota', Zipcode: 55403, Phone: '(612) 304-6073', Fax: '(612) 304-6074', Website: 'http://www.nowebsitemusic.dx', }, { ID: 4, CompanyName: "Tom's Club", Address: '999 Lake Drive', City: 'Issaquah', State: 'Washington', Zipcode: 98027, Phone: '(800) 955-2292', Fax: '(800) 955-2293', Website: 'http://www.nowebsitetomsclub.dx', }]; export default { getCompanies() { return companies; }, };
window.exports = window.exports || {}; window.config = { transpiler: 'plugin-babel', meta: { '*.vue': { loader: 'vue-loader', }, '*.ts': { loader: 'demo-ts-loader', }, '*.svg': { loader: 'svg-loader', }, 'devextreme/time_zone_utils.js': { 'esModule': true, }, 'devextreme/localization.js': { 'esModule': true, }, 'devextreme/viz/palette.js': { 'esModule': true, }, 'openai': { 'esModule': true, }, }, paths: { 'project:': '../../../../', 'npm:': 'https://unpkg.com/', 'bundles:': '../../../../bundles/', 'externals:': '../../../../bundles/externals/', }, map: { 'vue': 'npm:vue@3.4.27/dist/vue.esm-browser.js', '@vue/shared': 'npm:@vue/shared@3.4.27/dist/shared.cjs.prod.js', 'vue-loader': 'npm:dx-systemjs-vue-browser@1.1.1/index.js', 'demo-ts-loader': 'project:utils/demo-ts-loader.js', 'jszip': 'npm:jszip@3.10.1/dist/jszip.min.js', 'svg-loader': 'project:utils/svg-loader.js', 'mitt': 'npm:mitt/dist/mitt.umd.js', 'rrule': 'npm:rrule@2.6.4/dist/es5/rrule.js', 'luxon': 'npm:luxon@3.4.4/build/global/luxon.min.js', 'es6-object-assign': 'npm:es6-object-assign', 'devextreme': 'npm:devextreme@link:../../packages/devextreme/artifacts/npm/devextreme/cjs', 'devextreme-vue': 'npm:devextreme-vue@link:../../packages/devextreme-vue/npm/cjs', 'devextreme-quill': 'npm:devextreme-quill@1.7.1/dist/dx-quill.min.js', 'devexpress-diagram': 'npm:devexpress-diagram@2.2.5/dist/dx-diagram.js', 'devexpress-gantt': 'npm:devexpress-gantt@4.1.54/dist/dx-gantt.js', '@devextreme/runtime': 'npm:@devextreme/runtime@3.0.12', 'inferno': 'npm:inferno@7.4.11/dist/inferno.min.js', 'inferno-compat': 'npm:inferno-compat/dist/inferno-compat.min.js', 'inferno-create-element': 'npm:inferno-create-element@7.4.11/dist/inferno-create-element.min.js', 'inferno-dom': 'npm:inferno-dom/dist/inferno-dom.min.js', 'inferno-hydrate': 'npm:inferno-hydrate/dist/inferno-hydrate.min.js', 'inferno-clone-vnode': 'npm:inferno-clone-vnode/dist/inferno-clone-vnode.min.js', 'inferno-create-class': 'npm:inferno-create-class/dist/inferno-create-class.min.js', 'inferno-extras': 'npm:inferno-extras/dist/inferno-extras.min.js', 'plugin-babel': 'npm:systemjs-plugin-babel@0.0.25/plugin-babel.js', 'systemjs-babel-build': 'npm:systemjs-plugin-babel@0.0.25/systemjs-babel-browser.js', // Prettier 'prettier/standalone': 'npm:prettier@2.8.8/standalone.js', 'prettier/parser-html': 'npm:prettier@2.8.8/parser-html.js', }, packages: { 'devextreme-vue': { main: 'index.js', }, 'devextreme': { defaultExtension: 'js', }, 'devextreme/events/utils': { main: 'index', }, 'devextreme/events': { main: 'index', }, 'es6-object-assign': { main: './index.js', defaultExtension: 'js', }, }, packageConfigPaths: [ 'npm:@devextreme/*/package.json', 'npm:@devextreme/runtime@3.0.12/inferno/package.json', ], babelOptions: { sourceMaps: false, stage0: true, }, }; System.config(window.config);
import { createApp } from 'vue'; import App from './App.vue'; createApp(App).mount('#app');
<!DOCTYPE html> <html lang="en"> <head> <title>DevExtreme Demo</title> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0" /> <link rel="stylesheet" type="text/css" href="https://cdn3.devexpress.com/jslib/24.2.3/css/dx.light.css" /> <script src="https://unpkg.com/typescript@5.4.5/lib/typescript.js"></script> <script type="module"> import * as vueCompilerSFC from "https://unpkg.com/@vue/compiler-sfc@3.4.27/dist/compiler-sfc.esm-browser.js"; window.vueCompilerSFC = vueCompilerSFC; </script> <script src="https://unpkg.com/core-js@2.6.12/client/shim.min.js"></script> <script src="https://unpkg.com/systemjs@0.21.3/dist/system.js"></script> <script type="text/javascript" src="config.js"></script> <script type="text/javascript"> System.import("./index.js"); </script> </head> <body class="dx-viewport"> <div class="demo-container"> <div id="app"> </div> </div> </body> </html>

Bind Accordion to Data

You can display Accordion items from the items array or a dataSource. If you use the items array, specify the title and text properties.

Configure Item Selection and Collapsibility

Enable the multiple property to allow users to select multiple panels. Use the selectedItems array to store selected items. Toggle the "Multiple enabled" checkbox in the Options demo section to see how it affects the selection.

If you want to allow users to close panels on click, set the collapsible property to true. Check the "Collapsible enabled" checkbox in the Options demo section to enable this feature.

Configure Animation

The animationDuration property allows you to specify the animation duration when users expand/collapse a panel. Use the "Animation duration" slider in the Options demo section to see how it affects the animation.

Customize Item Appearance

Use the itemTemplate and itemTitleTemplate properties to customize the panel appearance. If you use the items array, you can also specify the icon property.