Skip to content

Commit 713d670

Browse files
authored
feat(data-grid): column width calculation and overflow scroll (#504)
* feat(data-grid): column width calculation and overflow scroll * refactor: code
1 parent 4164a88 commit 713d670

File tree

1 file changed

+58
-4
lines changed

1 file changed

+58
-4
lines changed

src/views/dashboard/modules/data-view/components/data-grid.vue

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ a-card.data-grid(:bordered="false")
1111
size="mini"
1212
:data="gridData"
1313
:pagination="pagination"
14-
:scroll="{ y: '100%', x: '100%' }"
14+
:scroll="{ y: '100%', x: tableWidth }"
1515
:bordered="{ headerCell: true }"
1616
)
1717
template(#empty)
@@ -20,6 +20,7 @@ a-card.data-grid(:bordered="false")
2020
template(v-for="column in gridColumns" :key="column.title")
2121
template(v-if="timeColumnNames.includes(column.title)")
2222
a-table-column(
23+
:width="getColumnWidth(column)"
2324
:data-index="timeColumnFormatMap[column.dataIndex] ? `${column.dataIndex}${formatSuffix}` : column.dataIndex"
2425
)
2526
template(#title)
@@ -41,6 +42,7 @@ a-card.data-grid(:bordered="false")
4142
:title="column.title"
4243
:data-index="column.dataIndex"
4344
:ellipsis="column.ellipsis"
45+
:width="getColumnWidth(column)"
4446
)
4547
template(#cell="{ record }")
4648
| {{ record[column.dataIndex] }}
@@ -64,6 +66,13 @@ a-card.data-grid(:bordered="false")
6466
}
6567
)
6668
69+
const timeColumnWidth = 140
70+
71+
const MIN_COLUMN_WIDTHS = {
72+
timestamp: timeColumnWidth,
73+
boolean: 80,
74+
}
75+
6776
const pagination = ref({
6877
'total': props.data?.records.rows.length,
6978
'show-page-size': true,
@@ -122,6 +131,54 @@ a-card.data-grid(:bordered="false")
122131
})
123132
})
124133
134+
const calculateTextWidth = (text) => {
135+
if (!text) return 0
136+
137+
const charWidths = {
138+
default: 7.2, // average character width
139+
narrow: 5.4, // narrow characters: i, l, j, t, f, r
140+
wide: 10.8, // m, w, etc.
141+
uppercase: 9, // A-Z
142+
}
143+
144+
let width = 0
145+
for (let i = 0; i < text.length; i += 1) {
146+
const char = text[i]
147+
if (char.match(/[A-Z]/)) {
148+
width += charWidths.uppercase
149+
} else if (char.match(/[iljtfr]/)) {
150+
width += charWidths.narrow
151+
} else if (char.match(/[mw]/)) {
152+
width += charWidths.wide
153+
} else {
154+
width += charWidths.default
155+
}
156+
}
157+
const PADDING = 16 * 2
158+
return Math.ceil(width) + PADDING
159+
}
160+
161+
const getColumnWidth = (column) => {
162+
const titleWidth = calculateTextWidth(column.title)
163+
164+
if (timeColumnNames.value.includes(column.title)) {
165+
return Math.max(titleWidth, MIN_COLUMN_WIDTHS.timestamp)
166+
}
167+
if (column.dataType && column.dataType.toLowerCase() === 'boolean') {
168+
return Math.max(titleWidth, MIN_COLUMN_WIDTHS.boolean)
169+
}
170+
171+
return Math.max(titleWidth, 80)
172+
}
173+
174+
const tableWidth = computed(() => {
175+
if (!gridColumns.value.length) return '100%'
176+
177+
const calculatedWidth = gridColumns.value.reduce((total, column) => total + getColumnWidth(column), 0)
178+
179+
return `${calculatedWidth}px`
180+
})
181+
125182
/**
126183
* use an extra state to store which time column is formatted
127184
* key is data-index instead of column name
@@ -146,9 +203,6 @@ a-card.data-grid(:bordered="false")
146203
}
147204
}
148205
149-
/** use a fixed width for the time column to prevent the width from changing automatically after formatting */
150-
const timeColumnWidth = 180
151-
152206
onUpdated(() => {
153207
pagination.value.total = props.data?.records.rows.length
154208
})

0 commit comments

Comments
 (0)