@@ -11,7 +11,7 @@ a-card.data-grid(:bordered="false")
11
11
size ="mini"
12
12
:data ="gridData"
13
13
:pagination ="pagination"
14
- :scroll ="{ y: '100%', x: '100%' }"
14
+ :scroll ="{ y: '100%', x: tableWidth }"
15
15
:bordered ="{ headerCell: true }"
16
16
)
17
17
template( #empty )
@@ -20,6 +20,7 @@ a-card.data-grid(:bordered="false")
20
20
template( v-for ="column in gridColumns" : key= "column.title" )
21
21
template( v-if ="timeColumnNames.includes(column.title)" )
22
22
a-table-column(
23
+ :width ="getColumnWidth(column)"
23
24
:data-index ="timeColumnFormatMap[column.dataIndex] ? `${column.dataIndex}${formatSuffix}` : column.dataIndex"
24
25
)
25
26
template( #title )
@@ -41,6 +42,7 @@ a-card.data-grid(:bordered="false")
41
42
:title ="column.title"
42
43
:data-index ="column.dataIndex"
43
44
:ellipsis ="column.ellipsis"
45
+ :width ="getColumnWidth(column)"
44
46
)
45
47
template( #cell ="{ record }" )
46
48
| {{ record[column.dataIndex] }}
@@ -64,6 +66,13 @@ a-card.data-grid(:bordered="false")
64
66
}
65
67
)
66
68
69
+ const timeColumnWidth = 140
70
+
71
+ const MIN_COLUMN_WIDTHS = {
72
+ timestamp: timeColumnWidth ,
73
+ boolean: 80 ,
74
+ }
75
+
67
76
const pagination = ref ({
68
77
' total' : props .data ?.records .rows .length ,
69
78
' show-page-size' : true ,
@@ -122,6 +131,54 @@ a-card.data-grid(:bordered="false")
122
131
})
123
132
})
124
133
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
+
125
182
/**
126
183
* use an extra state to store which time column is formatted
127
184
* key is data-index instead of column name
@@ -146,9 +203,6 @@ a-card.data-grid(:bordered="false")
146
203
}
147
204
}
148
205
149
- /** use a fixed width for the time column to prevent the width from changing automatically after formatting */
150
- const timeColumnWidth = 180
151
-
152
206
onUpdated (() => {
153
207
pagination .value .total = props .data ?.records .rows .length
154
208
})
0 commit comments