11
11
import { animationFrame } from '@vaadin/component-base/src/async.js' ;
12
12
import { Debouncer } from '@vaadin/component-base/src/debounce.js' ;
13
13
import { get , set } from '@vaadin/component-base/src/path-utils.js' ;
14
+ import { iterateRowCells , updatePart } from '@vaadin/grid/src/vaadin-grid-helpers.js' ;
14
15
15
16
/**
16
17
* @polymerMixin
@@ -218,6 +219,10 @@ export const InlineEditingMixin = (superClass) =>
218
219
return ;
219
220
}
220
221
222
+ if ( ! this . _isCellEditable ( cell ) ) {
223
+ return ;
224
+ }
225
+
221
226
callback ( e ) ;
222
227
}
223
228
} ) ;
@@ -325,8 +330,10 @@ export const InlineEditingMixin = (superClass) =>
325
330
326
331
/** @private */
327
332
_startEdit ( cell , column ) {
333
+ const isCellEditable = this . _isCellEditable ( cell ) ;
334
+
328
335
// TODO: remove `_editingDisabled` after Flow counterpart is updated.
329
- if ( this . disabled || this . _editingDisabled ) {
336
+ if ( this . disabled || this . _editingDisabled || ! isCellEditable ) {
330
337
return ;
331
338
}
332
339
// Cancel debouncer enqueued on focusout
@@ -421,59 +428,67 @@ export const InlineEditingMixin = (superClass) =>
421
428
422
429
this . _cancelStopEdit ( ) ;
423
430
424
- const cols = this . _getEditColumns ( ) ;
425
-
431
+ const editableColumns = this . _getEditColumns ( ) ;
426
432
const { cell, column, model } = this . __edited ;
427
- const colIndex = cols . indexOf ( column ) ;
428
- const { index } = model ;
429
433
430
- let nextCol = null ;
431
- let nextIdx = index ;
432
-
433
- // Enter key
434
- if ( e . keyCode === 13 ) {
435
- nextCol = column ;
436
-
437
- // Move up / down
438
- if ( this . enterNextRow ) {
439
- nextIdx = e . shiftKey ? index - 1 : index + 1 ;
440
- }
434
+ this . _stopEdit ( ) ;
435
+ e . preventDefault ( ) ;
436
+ // Prevent vaadin-grid handler from being called
437
+ e . stopImmediatePropagation ( ) ;
438
+
439
+ // Try to find the next editable cell
440
+ let nextIndex = model . index ;
441
+ let nextColumn = column ;
442
+ let nextCell = cell ;
443
+ let directionX = 0 ;
444
+ let directionY = 0 ;
445
+
446
+ // Enter key: move up / down
447
+ if ( e . keyCode === 13 && this . enterNextRow ) {
448
+ directionY = e . shiftKey ? - 1 : 1 ;
441
449
}
442
450
443
451
// Tab: move right / left
444
452
if ( e . keyCode === 9 ) {
445
- if ( e . shiftKey ) {
446
- if ( cols [ colIndex - 1 ] ) {
447
- nextCol = cols [ colIndex - 1 ] ;
448
- } else if ( index > 0 ) {
449
- nextIdx = index - 1 ;
450
- nextCol = cols [ cols . length - 1 ] ;
453
+ directionX = e . shiftKey ? - 1 : 1 ;
454
+ }
455
+
456
+ if ( directionX || directionY ) {
457
+ while ( nextCell ) {
458
+ if ( directionX ) {
459
+ // Move horizontally
460
+ nextColumn = editableColumns [ editableColumns . indexOf ( nextColumn ) + directionX ] ;
461
+ if ( ! nextColumn ) {
462
+ // Wrap to the next or previous row
463
+ nextIndex += directionX ;
464
+ nextColumn = editableColumns [ directionX > 0 ? 0 : editableColumns . length - 1 ] ;
465
+ }
466
+ }
467
+ // Move vertically
468
+ if ( directionY ) {
469
+ nextIndex += directionY ;
470
+ }
471
+ // Stop looking if the next cell is editable
472
+ const nextRow = this . _getRowByIndex ( nextIndex ) ;
473
+ // eslint-disable-next-line @typescript-eslint/no-loop-func
474
+ nextCell = nextRow && Array . from ( nextRow . children ) . find ( ( cell ) => cell . _column === nextColumn ) ;
475
+ if ( nextCell && this . _isCellEditable ( nextCell ) ) {
476
+ break ;
451
477
}
452
- } else if ( cols [ colIndex + 1 ] ) {
453
- nextCol = cols [ colIndex + 1 ] ;
454
- } else {
455
- nextIdx = index + 1 ;
456
- nextCol = cols [ 0 ] ;
457
478
}
458
479
}
459
480
460
- const nextRow = nextIdx === index ? cell . parentNode : this . _getRowByIndex ( nextIdx ) || null ;
461
-
462
- this . _stopEdit ( ) ;
463
-
464
- if ( nextRow && nextCol ) {
465
- const nextCell = Array . from ( nextRow . children ) . find ( ( cell ) => cell . _column === nextCol ) ;
466
- e . preventDefault ( ) ;
467
-
468
- // Prevent vaadin-grid handler from being called
469
- e . stopImmediatePropagation ( ) ;
481
+ // Focus current cell as fallback
482
+ if ( ! nextCell ) {
483
+ nextCell = cell ;
484
+ nextIndex = model . index ;
485
+ }
470
486
471
- if ( ! this . singleCellEdit && nextCell !== cell ) {
472
- this . _startEdit ( nextCell , nextCol ) ;
473
- } else {
474
- this . _ensureScrolledToIndex ( nextIdx ) ;
475
- nextCell . focus ( ) ;
476
- }
487
+ if ( ! this . singleCellEdit && nextCell !== cell ) {
488
+ this . _startEdit ( nextCell , nextColumn ) ;
489
+ } else {
490
+ this . _ensureScrolledToIndex ( nextIndex ) ;
491
+ nextCell . focus ( ) ;
477
492
}
478
493
}
479
494
@@ -492,6 +507,38 @@ export const InlineEditingMixin = (superClass) =>
492
507
super . _updateItem ( row , item ) ;
493
508
}
494
509
510
+ /**
511
+ * Override method from `StylingMixin` to apply `editable-cell` part to the
512
+ * cells of edit columns.
513
+ *
514
+ * @override
515
+ */
516
+ _generateCellPartNames ( row , model ) {
517
+ super . _generateCellPartNames ( row , model ) ;
518
+
519
+ iterateRowCells ( row , ( cell ) => {
520
+ const isEditable = this . _isCellEditable ( cell ) ;
521
+ const target = cell . _focusButton || cell ;
522
+ updatePart ( target , isEditable , 'editable-cell' ) ;
523
+ } ) ;
524
+ }
525
+
526
+ /** @private */
527
+ _isCellEditable ( cell ) {
528
+ const column = cell . _column ;
529
+ // Not editable if the column is not an edit column
530
+ if ( ! this . _isEditColumn ( column ) ) {
531
+ return false ;
532
+ }
533
+ // Cell is editable by default if isCellEditable is not configured
534
+ if ( ! column . isCellEditable ) {
535
+ return true ;
536
+ }
537
+ // Otherwise, check isCellEditable function
538
+ const model = this . __getRowModel ( cell . parentElement ) ;
539
+ return column . isCellEditable ( model ) ;
540
+ }
541
+
495
542
/**
496
543
* Fired before exiting the cell edit mode, if the value has been changed.
497
544
* If the default is prevented, value change would not be applied.
0 commit comments