Skip to content

Commit 5fc1a1b

Browse files
Vue: Migrate to Composition API with TypeScript
- Converted Options API → Composition API with <script setup lang="ts"> - Used ref() for component references: ref<DxDataGrid | null>(null) - Added proper DevExtreme Vue types: DxDataGridTypes, DxPivotGridTypes - Implemented typed event handlers with DevExtreme Vue event types - Added early return pattern for null-safe instance access - Used v-model:visible for popup two-way binding - Created data.ts with Sale interface and typed sales array - Updated HomeView.vue to use PivotGrid drill-down component - Removed orig_ reference files
1 parent 6ce68a1 commit 5fc1a1b

File tree

5 files changed

+5322
-37
lines changed

5 files changed

+5322
-37
lines changed

Vue/package-lock.json

Lines changed: 0 additions & 16 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Vue/src/assets/main.css

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
-webkit-font-smoothing: antialiased;
44
-moz-osx-font-smoothing: grayscale;
55
color: #2c3e50;
6-
margin: 50px 50px;
7-
width: 90vh;
6+
margin: 50px;
7+
width: 90vw;
88
}

Vue/src/components/HomeContent.vue

Lines changed: 180 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,190 @@
11
<script setup lang="ts">
2-
import { computed, ref } from 'vue';
3-
2+
import { ref } from 'vue';
43
import 'devextreme/dist/css/dx.material.blue.light.compact.css';
5-
import DxButton from 'devextreme-vue/button';
4+
import {
5+
DxPivotGrid,
6+
type DxPivotGridTypes,
7+
} from 'devextreme-vue/pivot-grid';
8+
import { DxFieldChooser } from 'devextreme-vue/pivot-grid';
9+
import { DxPopup } from 'devextreme-vue/popup';
10+
import {
11+
DxDataGrid,
12+
type DxDataGridTypes,
13+
} from 'devextreme-vue/data-grid';
14+
import { DxColumn, DxEditing } from 'devextreme-vue/data-grid';
15+
import PivotGridDataSource from 'devextreme/ui/pivot_grid/data_source';
16+
import { ArrayStore, DataSource, isItemsArray, type LoadResult } from 'devextreme-vue/common/data';
17+
import notify from 'devextreme/ui/notify';
18+
import { sales, type Sale } from '../data';
19+
20+
const pivotGridRef = ref<DxPivotGrid | null>(null);
21+
const dataGridRef = ref<DxDataGrid | null>(null);
22+
23+
const data = new ArrayStore({
24+
data: sales,
25+
key: 'id',
26+
});
627
7-
const props = defineProps({
8-
text: {
9-
type: String,
10-
default: 'count',
11-
},
28+
const pivotGridDataSource = new PivotGridDataSource({
29+
fields: [
30+
{
31+
caption: 'Region',
32+
width: 120,
33+
dataField: 'region',
34+
area: 'row',
35+
},
36+
{
37+
caption: 'City',
38+
dataField: 'city',
39+
width: 150,
40+
area: 'row',
41+
},
42+
{
43+
dataField: 'date',
44+
dataType: 'date',
45+
area: 'column',
46+
},
47+
{
48+
caption: 'Total',
49+
dataField: 'amount',
50+
dataType: 'number',
51+
summaryType: 'sum',
52+
format: 'currency',
53+
area: 'data',
54+
},
55+
],
56+
store: data,
1257
});
13-
const count = ref(0);
14-
const buttonText = computed<string>(
15-
() => `Click ${props.text}: ${count.value}`
16-
);
17-
function clickHandler() {
18-
count.value += 1;
58+
59+
const drillDownDataSource = ref<DataSource<Sale, number> | null>(null);
60+
const popupTitle = ref('');
61+
const popupVisible = ref(false);
62+
63+
function onCellClick(e: DxPivotGridTypes.CellClickEvent): void {
64+
if (e.area === 'data' && e.cell && e.cell.rowPath) {
65+
const pivotDataSource = e.component.getDataSource();
66+
const rowPathLength = e.cell.rowPath.length;
67+
const rowPathName = e.cell.rowPath[rowPathLength - 1];
68+
const title = `${rowPathName ? rowPathName : 'Total'} Drill Down Data`;
69+
70+
drillDownDataSource.value = pivotDataSource.createDrillDownDataSource(
71+
e.cell
72+
);
73+
74+
popupTitle.value = title;
75+
popupVisible.value = true;
76+
}
77+
}
78+
79+
function onShowing(): void {
80+
const gridInstance = dataGridRef.value?.instance;
81+
if (!gridInstance) return;
82+
83+
drillDownDataSource.value?.store().load().then((items: LoadResult<Sale>) => {
84+
if(isItemsArray(items)) {
85+
gridInstance.option('dataSource', {
86+
store: new ArrayStore({
87+
key: data.key(),
88+
data: items,
89+
}),
90+
});
91+
}
92+
});
93+
}
94+
95+
function onHiding(): void {
96+
const pivotInstance = pivotGridRef.value?.instance;
97+
if (!pivotInstance) return;
98+
99+
pivotInstance.getDataSource().reload().catch(() => {
100+
notify('Failed to reload data', 'error', 1000);
101+
});
102+
}
103+
104+
function onShown(): void {
105+
const gridInstance = dataGridRef.value?.instance;
106+
if (!gridInstance) return;
107+
108+
gridInstance.updateDimensions();
109+
}
110+
111+
function onRowInserting(e: DxDataGridTypes.RowInsertingEvent<Sale, number>): void {
112+
data.insert(e.data).catch(() => {
113+
notify('Failed to add data', 'error', 1000);
114+
});
115+
}
116+
117+
function onRowUpdating(e: DxDataGridTypes.RowUpdatingEvent<Sale, number>): void {
118+
data.update(e.key, e.newData).catch(() => {
119+
notify('Failed to update data', 'error', 1000);
120+
});
121+
}
122+
123+
function onRowRemoving(e: DxDataGridTypes.RowRemovingEvent<Sale, number>): void {
124+
data.remove(e.key).catch(() => {
125+
notify('Failed to remove data', 'error', 1000);
126+
});
19127
}
20128
</script>
129+
21130
<template>
22131
<div>
23-
<DxButton
24-
:text="buttonText"
25-
@click="clickHandler"
26-
/>
132+
<div class="long-title">
133+
<h3>Sales Amount by Region</h3>
134+
</div>
135+
<DxPivotGrid
136+
ref="pivotGridRef"
137+
:allow-sorting-by-summary="true"
138+
:allow-sorting="true"
139+
:allow-filtering="true"
140+
:allow-expand-all="true"
141+
:show-borders="true"
142+
:data-source="pivotGridDataSource"
143+
@cell-click="onCellClick"
144+
>
145+
<DxFieldChooser :enabled="false"/>
146+
</DxPivotGrid>
147+
<DxPopup
148+
:width="600"
149+
:height="400"
150+
v-model:visible="popupVisible"
151+
:title="popupTitle"
152+
:show-close-button="true"
153+
@showing="onShowing"
154+
@hiding="onHiding"
155+
@shown="onShown"
156+
>
157+
<DxDataGrid
158+
ref="dataGridRef"
159+
:width="560"
160+
:height="300"
161+
@row-inserting="onRowInserting"
162+
@row-updating="onRowUpdating"
163+
@row-removing="onRowRemoving"
164+
>
165+
<DxEditing
166+
:allow-updating="true"
167+
:allow-deleting="true"
168+
:allow-adding="true"
169+
/>
170+
<DxColumn data-field="region"/>
171+
<DxColumn data-field="city"/>
172+
<DxColumn
173+
data-field="amount"
174+
data-type="number"
175+
/>
176+
<DxColumn
177+
data-field="date"
178+
data-type="date"
179+
/>
180+
</DxDataGrid>
181+
</DxPopup>
27182
</div>
28183
</template>
184+
185+
<style scoped>
186+
.long-title {
187+
margin: 20px 0;
188+
}
189+
</style>
190+

0 commit comments

Comments
 (0)