I'm using DevExtreme components for my Vue3 app. Based on this sample ( docs / code sample ) I want to create multi level headers based on a configuration. I think I will have to use a recursive loop for that.
First I created a component GridColumn acting as a node in a tree which is able to render itself with or without its nested children
<template>
<!-- If there are no children use the data-field prop -->
<dx-column
v-if="gridColumn.children === undefined"
:caption="gridColumn.caption"
:data-field="gridColumn.dataField"
/>
<!-- If there are children nest them inside -->
<dx-column v-else :caption="gridColumn.caption">
<grid-column
v-for="childGridColumn in gridColumn.children"
:key="childGridColumn.caption"
:gridColumn="childGridColumn"
/>
</dx-column>
</template>
<script lang="ts">
import { DxColumn } from "devextreme-vue/data-grid";
import { defineComponent } from "vue";
export default defineComponent({
name: "grid-column",
components: {
"dx-column": DxColumn,
},
props: {
gridColumn: Object,
},
});
</script>
Now I can use this component inside the Home view
<template>
<dx-data-grid :data-source="data" :show-borders="true">
<grid-column
v-for="columnDefinition in columnDefinitions"
:key="columnDefinition.caption"
:gridColumn="columnDefinition"
/>
</dx-data-grid>
</template>
<script lang="ts">
import DxDataGrid from "devextreme-vue/data-grid";
import { defineComponent, ref } from "vue";
import GridColumn from "../components/GridColumn.vue";
export default defineComponent({
components: {
"dx-data-grid": DxDataGrid,
"grid-column": GridColumn,
},
setup() {
const columnDefinitions = ref([
{
caption: "Col 1",
dataField: "fieldOne",
},
{
caption: "Col 2",
children: [
{
caption: "Col 2.1",
dataField: "fieldTwo",
},
{
caption: "Col 2.2",
dataField: "fieldThree",
},
],
},
{
caption: "Col 3",
children: [
{
caption: "We need to go deeper",
children: [
{
caption: "... deeper ...",
children: [
{
caption: "... almost ...",
children: [
{
caption: "GO FOR IT",
dataField: "fieldFour",
},
],
},
],
},
],
},
],
},
]);
const data = ref([
{
fieldOne: "foo",
fieldTwo: 2,
fieldThree: new Date(),
fieldFour: { x: "y" },
},
{
fieldOne: "some more text",
fieldTwo: 123,
fieldThree: new Date(),
fieldFour: { a: "b" },
},
]);
return { columnDefinitions, data };
},
});
</script>
The rendered result will be
which is not what I wanted, the captions are wrong and the parent headers are missing. You can checkout a sandbox demo here
Just to show what I want to achieve
with a working sandbox demo
Does someone know how what is wrong with my implementation? And maybe there are even simpler solutions for that?
I didn't find a solution for the recursive element, but you can use the columns
property on the data-table itself.
Your data-table would look like this
<dx-data-grid
:data-source="data"
:show-borders="true"
:columns="columnDefinitions">
</dx-data-grid>
Now you only have to rename the children
array to columns
.
const columnDefinitions = ref([
{
caption: "Col 1",
dataField: "fieldOne",
},
{
caption: "Col 2",
columns: [
{
caption: "Col 2.1",
dataField: "fieldTwo",
},
{
caption: "Col 2.2",
dataField: "fieldThree",
},
],
},
{
caption: "Col 3",
columns: [
{
caption: "We need to go deeper",
columns: [
{
caption: "... deeper ...",
columns: [
{
caption: "... almost ...",
columns: [
{
caption: "GO FOR IT",
dataField: "fieldFour",
},
],
},
],
},
],
},
],
},
]);
The only documentation mentioning a columns
property I could find was here. It's not very explicit on how to use that with vue though.