@@ -93,48 +93,23 @@ export default {
93
93
} ,
94
94
data ( ) {
95
95
return {
96
- localSortBy : [ '' ] ,
97
- localSortDesc : [ false ]
96
+ // Array of sort Objects: [{ sortBy: 'field', sortDesc: false }, ... ]
97
+ // Will be an empty array if no sorting
98
+ localSortInfo : [ ]
98
99
}
99
100
} ,
100
101
computed : {
101
102
localSorting ( ) {
102
103
return this . hasProvider ? ! ! this . noProviderSorting : ! this . noLocalSorting
103
104
} ,
104
105
isSortable ( ) {
105
- return this . computedFields . some ( f => f . sortable )
106
+ return this . computedFields . some ( field => field . sortable )
106
107
} ,
107
108
computedSortBy ( ) {
108
- return this . sortMulti ? this . localSortBy : this . localSortBy . slice ( 0 , 1 )
109
+ return this . localSortInfo . map ( info => info . sortBy )
109
110
} ,
110
111
computedSortDesc ( ) {
111
- // Ensure values are tri-state (true, false, null), and same length as localSortBy array
112
- const sortDesc = this . localSortBy . map (
113
- ( _ , idx ) => ( isBoolean ( this . localSortDesc [ idx ] ) ? this . localSortDesc [ idx ] : null )
114
- )
115
- return this . sortMulti ? sortDesc : sortDesc . slice ( 0 , 1 )
116
- } ,
117
- computedSortInfo ( ) {
118
- // TODO in this PR:
119
- // Make sortInfo a data property which we update
120
- // via watchers on sortBy/SortDesc and event handlers.
121
- // When a column is no longer sorted (null) we remove it from the array
122
- const computedSortDesc = this . computedSortDesc
123
- const computedFieldsObj = this . computedFieldsObj
124
- return this . localSortBy
125
- . map ( ( key , idx ) => {
126
- const field = computedFieldsObj [ key ] || { }
127
- return {
128
- sortBy : key ,
129
- sortDesc : computedSortDesc [ idx ] ,
130
- formatter : isFunction ( field . formatter )
131
- ? field . formatter
132
- : field . formatter
133
- ? this . getFieldFormatter ( key )
134
- : undefined
135
- }
136
- } )
137
- . filter ( x => x . sortBy && isBoolean ( x . sortDesc ) )
112
+ return this . localSortInfo . map ( info => info . sortDesc )
138
113
} ,
139
114
sortedItems ( ) {
140
115
// Sorts the filtered items and returns a new array of the sorted items
@@ -190,47 +165,64 @@ export default {
190
165
this . $off ( 'head-clicked' , this . handleSort )
191
166
}
192
167
} ,
193
- sortBy ( newVal , oldVal ) {
194
- if ( looseEqual ( newVal , this . localSortBy ) ) {
195
- /* istanbul ignore next */
196
- return
168
+ sortBy ( newVal ) {
169
+ // Update localSortInfo object
170
+ if ( ! looseEqual ( newVal , this . computedSortBy ) ) {
171
+ // Update localSortInfo object
172
+ this . updateLocalSortInfo ( newVal , this . sortDesc )
197
173
}
198
- // TODO in this PR:
199
- // Update sortInfo object
200
- this . localSortBy = newVal ? concat ( newVal ) : [ ]
201
174
} ,
202
- sortDesc ( newVal , oldVal ) {
203
- if ( looseEqual ( newVal , this . localSortDesc ) ) {
204
- /* istanbul ignore next */
205
- return
175
+ sortDesc ( newVal ) {
176
+ // Update localSortInfo object
177
+ if ( ! looseEqual ( newVal , this . computedSortDesc ) ) {
178
+ this . updateLocalSortInfo ( this . sortBy , newVal )
206
179
}
207
- // TODO in this PR:
208
- // Update sortInfo object
209
- newVal = isUndefined ( newVal ) ? [ ] : concat ( newVal )
210
- this . localSortDesc = newVal . map ( d => ( isBoolean ( d ) ? d : null ) )
211
180
} ,
212
181
// Update .sync props
213
- // TODO in this PR:
214
- // Instead watch the sortInfo array, and emit the apropriate
215
- // updated values as needed
216
- localSortDesc ( newVal , oldVal ) {
217
- // Emit update to sort-desc.sync
218
- if ( ! looseEqual ( newVal , oldVal ) ) {
219
- this . $emit ( 'update:sortDesc' , this . sortMulti ? newVal : newVal [ 0 ] )
182
+ computedSortBy ( newSortBy = [ ] , oldSortBy = [ ] ) {
183
+ if ( ! looseEqual ( newSortBy , oldSortBy ) ) {
184
+ // Emit update to sort-by.sync
185
+ this . $emit ( 'update:sortBy' , this . sortMulti ? newSortBy : newSortBy [ 0 ] || '' )
220
186
}
221
187
} ,
222
- localSortBy ( newVal , oldVal ) {
223
- if ( ! looseEqual ( newVal , oldVal ) ) {
224
- this . $emit ( 'update:sortBy' , this . sortMulti ? newVal : newVal [ 0 ] )
188
+ computedSortDesc ( newSortDesc = [ ] , oldSortDesc = [ ] ) {
189
+ if ( ! looseEqual ( newSortDesc , oldSortDesc ) ) {
190
+ // Emit update to sort-desc.sync
191
+ this . $emit ( 'update:sortBy' , this . sortMulti ? newSortDesc : newSortDesc [ 0 ] || '' )
225
192
}
226
193
}
227
194
} ,
228
195
created ( ) {
229
196
if ( this . isSortable ) {
230
197
this . $on ( 'head-clicked' , this . handleSort )
198
+ // Update sortInfo object
199
+ this . updateLocalSortInfo ( this . sortBy , newVal )
231
200
}
232
201
} ,
233
202
methods : {
203
+ updateLocalSortInfo ( sortBy , sortDesc ) {
204
+ if ( this . isSortable ) {
205
+ // Updates localSortInfo array with the given values
206
+ const sortByArr = concat ( sortBy ) . filter ( s => ! isUndefinedOrNull ( s ) )
207
+ const sortDescArr = concat ( sortDesc )
208
+ const computedFieldsObj = this . computedFieldsObj
209
+ this . localSortInfo = sortByArr . map ( ( key , idx ) => {
210
+ const field = computedFieldsObj [ key ] || { }
211
+ return {
212
+ sortBy : String ( key ) ,
213
+ sortDesc : Boolean ( sortDescArr [ idx ] ) ,
214
+ formatter : isFunction ( field . formatter )
215
+ ? field . formatter
216
+ : field . formatter
217
+ ? this . getFieldFormatter ( key )
218
+ : undefined
219
+ }
220
+ } )
221
+ } else {
222
+ // Not sortable so reset the localSortInfo array
223
+ this . localSortInfo = [ ]
224
+ }
225
+ } ,
234
226
// Handlers
235
227
handleSort ( key , field , evt , isFoot ) {
236
228
if ( ! this . isSortable ) {
@@ -246,53 +238,45 @@ export default {
246
238
// const sequence = this.sortDirection === 'desc' ? [true, false, null] : [false, true, null]
247
239
// TODO in this PR:
248
240
// Handle this via lookup
249
- const sortBy = this . localSortBy [ 0 ]
250
- // TODO: make this tri-state sorting (for multi-sort only)
251
- // cycle desc => asc => none => desc => ...
241
+ const sortMulti = this . sortMulti
242
+ const sortInfo = this . localSortInfo
243
+ const sortIndex = this . computedSortBy . indexOf ( key )
252
244
let sortChanged = false
253
- const toggleLocalSortDesc = ( ) => {
254
- const sortDirection = field . sortDirection || this . sortDirection
255
- if ( sortDirection === 'asc' ) {
256
- this . localSortDesc = [ false ]
257
- } else if ( sortDirection === 'desc' ) {
258
- this . localSortDesc = [ true ]
259
- } else {
260
- // sortDirection === 'last'
261
- // Leave at last sort direction from previous column
262
- // TODO in this PR:
263
- // If multi-sort, then use sort sequence
264
- }
265
- }
245
+ // Get the initial sort Direction
246
+ const intialDirection = sortMulti
247
+ ? this . sortDirection
248
+ : field . sortDirection || this . sortDirection
249
+ const intialSortDesc = intialDirection === 'asc'
250
+ ? false
251
+ : intialDirection === 'desc'
252
+ ? true
253
+ : sortMulti
254
+ ? false
255
+ : ( sortInfo [ 0 ] || { } ) . sortDesc || false
266
256
if ( field . sortable ) {
267
- // TODO in this PR:
268
- // handle toggling on the index
269
- if ( key === sortBy ) {
270
- // Change sorting direction on current column
271
- // this.localSortDesc[0] = !this.localSortDesc[0]
272
- this . localSortDesc = [ ! this . localSortDesc [ 0 ] ]
273
- // TODO in this PR:
274
- // Check if sort is clearing (third click), and
275
- // if so remove the sort item from both localSortBy/localSortDesc
257
+ if ( sortIndex === - 1 ) {
258
+ // Field not sorted currently
259
+ this . localSortInfo . push ( {
260
+ sortBy : key ,
261
+ sortDesc : intialSortDesc
262
+ } )
276
263
} else {
277
- // Start sorting this column ascending
278
- this . localSortBy [ 0 ] = key
279
- // this.localSortDesc = false
280
- toggleLocalSortDesc ( )
264
+ // Field is currently sorted
265
+ if ( sortInfo [ sortIndex ] . sortDesc === intialSortDesc ) {
266
+ // If transitioning from true<=>false, toggle the direction
267
+ sortInfo [ sortIndex ] . sortDesc = ! sortInfo [ sortIndex ] . sortDesc
268
+ } else {
269
+ // Else transitoning to unsorted, so remove from sort info
270
+ this . localSortInfo . splice ( sortIndex , 1 )
271
+ }
281
272
}
282
273
sortChanged = true
283
274
} else if ( this . computedSortInfo . length > 0 && ! this . noSortReset ) {
284
- this . localSortBy = [ ]
285
- if ( this . sortMulti ) {
286
- this . localSortDesc = [ ]
287
- } else {
288
- toggleLocalSortDesc ( )
289
- }
275
+ this . localSortInfo = [ ]
290
276
sortChanged = true
291
- // } else {
292
- // sortChanged = false
293
277
}
294
278
if ( sortChanged ) {
295
- // Sorting parameters changed
279
+ // Sorting parameters changed via user interaction
296
280
this . $emit ( 'sort-changed' , this . context )
297
281
}
298
282
} ,
@@ -310,18 +294,10 @@ export default {
310
294
return { }
311
295
}
312
296
const sortable = field . sortable
313
- // TODO in this PR:
314
- // This is just temporary. Will need to lookup the index of this
315
- // key in this.localSortBy or this.localSortInfo
316
- const sortOrder = 1
317
- // TODO for this PR:
318
- // Find index of key in this.computedSortBy (or this.computedSortInfo),
319
- // and then grab the sorting value
320
- const sortDesc = this . localSortDesc [ 0 ]
321
- // TODO in this PR:
322
- // This is just temporary. Will need to lookup if this column key is
323
- // in this.localSortBy
324
- const sortBy = this . localSortBy [ 0 ]
297
+ const sortIndex = this . computedSortBy . indexOf ( key )
298
+ const sortOrder = sortIndex + 1
299
+ const sortBy = this . computedSortBy [ sortIndex ]
300
+ const sortDesc = this . computedSortDesc [ sortIndex ] || false
325
301
// Now we get down to business determining the aria-label value
326
302
let ariaLabel = ''
327
303
if ( ( ! field . label || ! field . label . trim ( ) ) && ! field . headerTitle ) {
@@ -345,7 +321,9 @@ export default {
345
321
// Default for ariaLabel
346
322
ariaLabelSorting = sortDesc ? this . labelSortDesc : this . labelSortAsc
347
323
// Handle sortDirection setting
348
- const sortDirection = this . sortDirection || field . sortDirection
324
+ const sortDirection = this . sortMulti
325
+ ? this . sortDirection
326
+ : this . sortDirection || field . sortDirection
349
327
if ( sortDirection === 'asc' ) {
350
328
ariaLabelSorting = this . labelSortAsc
351
329
} else if ( sortDirection === 'desc' ) {
@@ -354,7 +332,7 @@ export default {
354
332
}
355
333
} else if ( ! this . noSortReset ) {
356
334
// Non sortable column
357
- ariaLabelSorting = this . localSortBy ? this . labelSortClear : ''
335
+ ariaLabelSorting = sortInfo . length > 0 ? this . labelSortClear : ''
358
336
}
359
337
// Assemble the aria-label attribute value
360
338
ariaLabel = [ ariaLabel . trim ( ) , ariaLabelSorting . trim ( ) ] . filter ( Boolean ) . join ( ': ' )
@@ -380,7 +358,7 @@ export default {
380
358
// And figure out how to set a variant for this badge
381
359
// May require additiona CSS generation. or we just make 2 options: dark and light
382
360
// Or use the column text variant (currentColor) to make an outline badge
383
- 'data-sort-order' : this . sortMulti ? String ( sortOrder ) : null
361
+ 'data-sort-order' : this . sortMulti && sortOrder ? String ( sortOrder ) : null
384
362
}
385
363
}
386
364
}
0 commit comments