ag-grid-community 34.0.0 → 34.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7953,8 +7953,13 @@ function _addColumnDefaultAndTypes(beans, colDef, colId, isAutoCol) {
7953
7953
  if (columnType) {
7954
7954
  assignColumnTypes(beans, columnType, res);
7955
7955
  }
7956
+ const cellDataType = res.cellDataType;
7956
7957
  // merge properties from column definitions
7957
7958
  (0, object_1._mergeDeep)(res, colDef, false, true);
7959
+ if (cellDataType !== undefined) {
7960
+ // `cellDataType: true` in provided def will overwrite inferred result type otherwise
7961
+ res.cellDataType = cellDataType;
7962
+ }
7958
7963
  const autoGroupColDef = gos.get('autoGroupColumnDef');
7959
7964
  const isSortingCoupled = (0, gridOptionsUtils_1._isColumnsSortingCoupledToGroup)(gos);
7960
7965
  if (colDef.rowGroup && autoGroupColDef && isSortingCoupled) {
@@ -10836,7 +10841,7 @@ class DataTypeService extends beanStub_1.BeanStub {
10836
10841
  }
10837
10842
  postProcess(colDef) {
10838
10843
  const cellDataType = colDef.cellDataType;
10839
- if (!cellDataType) {
10844
+ if (!cellDataType || typeof cellDataType !== 'string') {
10840
10845
  return;
10841
10846
  }
10842
10847
  const { dataTypeDefinitions, beans, formatValueFuncs } = this;
@@ -16358,6 +16363,14 @@ function startEditingCell(beans, params) {
16358
16363
  rowPinned: rowPinned || null,
16359
16364
  column,
16360
16365
  };
16366
+ const rowNode = (0, positionUtils_1._getRowNode)(beans, cellPosition);
16367
+ if (!rowNode) {
16368
+ (0, logging_1._warn)(290, { rowIndex, rowPinned });
16369
+ return;
16370
+ }
16371
+ if (!column.isCellEditable(rowNode)) {
16372
+ return;
16373
+ }
16361
16374
  const notPinned = rowPinned == null;
16362
16375
  if (notPinned) {
16363
16376
  (0, scrollApi_1.ensureIndexVisible)(beans, rowIndex);
@@ -16476,6 +16489,9 @@ class EditModelService extends beanStub_1.BeanStub {
16476
16489
  return data;
16477
16490
  }
16478
16491
  getEdit(position) {
16492
+ return this._getEdit(position);
16493
+ }
16494
+ _getEdit(position) {
16479
16495
  if (this.suspendEdits) {
16480
16496
  return undefined;
16481
16497
  }
@@ -16507,13 +16523,21 @@ class EditModelService extends beanStub_1.BeanStub {
16507
16523
  }
16508
16524
  setEdit(position, edit) {
16509
16525
  (this.edits.size === 0 || !this.edits.has(position.rowNode)) && this.edits.set(position.rowNode, new Map());
16510
- this.getEditRow(position.rowNode).set(position.column, edit);
16526
+ const currentEdit = Object.assign({}, this._getEdit(position));
16527
+ Object.keys(edit).forEach((key) => {
16528
+ const value = edit[key];
16529
+ // don't copy unset keys
16530
+ if (value !== undefined) {
16531
+ currentEdit[key] = value;
16532
+ }
16533
+ });
16534
+ this.getEditRow(position.rowNode).set(position.column, currentEdit);
16511
16535
  }
16512
16536
  clearEditValue(position) {
16513
16537
  const { rowNode, column } = position;
16514
16538
  if (rowNode) {
16515
16539
  if (column) {
16516
- const edit = this.getEdit(position);
16540
+ const edit = this._getEdit(position);
16517
16541
  if (edit) {
16518
16542
  edit.newValue = edit.oldValue;
16519
16543
  edit.state = 'changed';
@@ -16552,7 +16576,7 @@ class EditModelService extends beanStub_1.BeanStub {
16552
16576
  return this.getEdit(position)?.state;
16553
16577
  }
16554
16578
  getEditPositions(editMap) {
16555
- if (this.suspendEdits || this.edits.size === 0) {
16579
+ if (this.suspendEdits || (editMap ?? this.edits).size === 0) {
16556
16580
  return [];
16557
16581
  }
16558
16582
  const positions = [];
@@ -16882,6 +16906,8 @@ const rowEditStyleFeature_1 = __webpack_require__(13536);
16882
16906
  const controllers_1 = __webpack_require__(1081);
16883
16907
  const editors_1 = __webpack_require__(78994);
16884
16908
  const refresh_1 = __webpack_require__(11539);
16909
+ // these are event sources for setDataValue that will not cause the editors to close
16910
+ const KEEP_EDITOR_SOURCES = new Set(['undo', 'redo']);
16885
16911
  // stop editing sources that we treat as UI-originated so we follow standard processing.
16886
16912
  const SOURCE_TRANSFORM = {
16887
16913
  paste: 'ui',
@@ -16936,7 +16962,6 @@ class EditService extends beanStub_1.BeanStub {
16936
16962
  rowGroupOpened: handler,
16937
16963
  pinnedRowsChanged: handler,
16938
16964
  displayedRowsChanged: handler,
16939
- rowDataUpdated: stopInvalidEdits,
16940
16965
  sortChanged: stopInvalidEdits,
16941
16966
  filterChanged: stopInvalidEdits,
16942
16967
  cellFocused: this.onCellFocused.bind(this),
@@ -17043,10 +17068,10 @@ class EditService extends beanStub_1.BeanStub {
17043
17068
  const willStop = !cancel && !!this.shouldStopEditing(position, event, source);
17044
17069
  const willCancel = cancel && !!this.shouldCancelEditing(position, event, source);
17045
17070
  if (willStop || willCancel) {
17046
- (0, editors_1._syncFromEditors)(beans);
17071
+ (0, editors_1._syncFromEditors)(beans, { event });
17047
17072
  const freshEdits = model.getEditMap();
17048
17073
  this.processEdits(freshEdits, cancel);
17049
- this.strategy?.stop(cancel);
17074
+ this.strategy?.stop(cancel, event);
17050
17075
  this.bulkRefresh(undefined, edits);
17051
17076
  edits = freshEdits;
17052
17077
  res || (res = willStop);
@@ -17060,20 +17085,25 @@ class EditService extends beanStub_1.BeanStub {
17060
17085
  const isEscape = key === keyCode_1.KeyCode.ESCAPE;
17061
17086
  if (isEnter || isEscape) {
17062
17087
  if (isEnter) {
17063
- (0, editors_1._syncFromEditors)(beans);
17088
+ (0, editors_1._syncFromEditors)(beans, { event });
17064
17089
  }
17065
17090
  else if (isEscape) {
17066
17091
  // only if ESC is pressed while in the editor for this cell
17067
17092
  this.revertSingleCellEdit(cellCtrl, false);
17068
17093
  }
17069
- (0, editors_1._destroyEditors)(beans, model.getEditPositions());
17094
+ if (this.isBatchEditing()) {
17095
+ this.strategy?.cleanupEditors();
17096
+ }
17097
+ else {
17098
+ (0, editors_1._destroyEditors)(beans, model.getEditPositions(), { event });
17099
+ }
17070
17100
  event.preventDefault();
17071
17101
  this.bulkRefresh(position, edits, { suppressFlash: true });
17072
17102
  edits = model.getEditMap();
17073
17103
  }
17074
17104
  }
17075
17105
  else {
17076
- (0, editors_1._syncFromEditors)(beans);
17106
+ (0, editors_1._syncFromEditors)(beans, { event });
17077
17107
  edits = model.getEditMap();
17078
17108
  }
17079
17109
  if (res && position) {
@@ -17112,6 +17142,7 @@ class EditService extends beanStub_1.BeanStub {
17112
17142
  const { beans } = this;
17113
17143
  const hasValidationErrors = this.model.getCellValidationModel().getCellValidationMap().size > 0 ||
17114
17144
  this.model.getRowValidationModel().getRowValidationMap().size > 0;
17145
+ const editsToDelete = [];
17115
17146
  for (const rowNode of rowNodes) {
17116
17147
  const editRow = edits.get(rowNode);
17117
17148
  for (const column of editRow.keys()) {
@@ -17119,22 +17150,38 @@ class EditService extends beanStub_1.BeanStub {
17119
17150
  const position = { rowNode, column };
17120
17151
  const cellCtrl = (0, controllers_1._getCellCtrl)(beans, position);
17121
17152
  const valueChanged = (0, editors_1._valuesDiffer)(editValue);
17122
- if (!cancel && valueChanged && !hasValidationErrors) {
17123
- // we suppressRefreshCell because the call to rowNode.setDataValue() results in change detection
17124
- // getting triggered, which results in all cells getting refreshed. we do not want this refresh
17125
- // to happen on this call as we want to call it explicitly below. otherwise refresh gets called twice.
17126
- // if we only did this refresh (and not the one below) then the cell would flash and not be forced.
17127
- if (cellCtrl) {
17128
- cellCtrl.suppressRefreshCell = true;
17129
- }
17130
- rowNode.setDataValue(column, editValue.newValue, 'commit');
17131
- if (cellCtrl) {
17132
- cellCtrl.suppressRefreshCell = false;
17153
+ const isCancelAfterEnd = cellCtrl?.comp?.getCellEditor()?.isCancelAfterEnd?.();
17154
+ if (!cancel && !isCancelAfterEnd && valueChanged && !hasValidationErrors) {
17155
+ const success = this.setNodeDataValue(rowNode, column, editValue.newValue);
17156
+ if (!success) {
17157
+ editsToDelete.push(position);
17133
17158
  }
17134
- cellCtrl?.refreshCell(FORCE_REFRESH);
17135
17159
  }
17160
+ cellCtrl?.refreshCell(FORCE_REFRESH);
17136
17161
  }
17137
17162
  }
17163
+ editsToDelete.forEach((position) => {
17164
+ this.model.clearEditValue(position);
17165
+ });
17166
+ }
17167
+ setNodeDataValue(rowNode, column, newValue, refreshCell) {
17168
+ const { beans } = this;
17169
+ const cellCtrl = (0, controllers_1._getCellCtrl)(beans, { rowNode, column });
17170
+ // we suppressRefreshCell because the call to rowNode.setDataValue() results in change detection
17171
+ // getting triggered, which results in all cells getting refreshed. we do not want this refresh
17172
+ // to happen on this call as we want to call it explicitly below. otherwise refresh gets called twice.
17173
+ // if we only did this refresh (and not the one below) then the cell would flash and not be forced.
17174
+ if (cellCtrl) {
17175
+ cellCtrl.suppressRefreshCell = true;
17176
+ }
17177
+ const success = rowNode.setDataValue(column, newValue, 'commit');
17178
+ if (cellCtrl) {
17179
+ cellCtrl.suppressRefreshCell = false;
17180
+ }
17181
+ if (refreshCell) {
17182
+ cellCtrl?.refreshCell(FORCE_REFRESH);
17183
+ }
17184
+ return success;
17138
17185
  }
17139
17186
  setEditMap(edits, params) {
17140
17187
  this.strategy ?? (this.strategy = this.createStrategy());
@@ -17258,8 +17305,8 @@ class EditService extends beanStub_1.BeanStub {
17258
17305
  return;
17259
17306
  }
17260
17307
  this.model.clearEditValue(cellPosition);
17261
- (0, editors_1._destroyEditors)(this.beans, [cellPosition]);
17262
- (0, editors_1._setupEditor)(this.beans, cellPosition);
17308
+ (0, editors_1._destroyEditors)(this.beans, [cellPosition], { silent: true });
17309
+ (0, editors_1._setupEditor)(this.beans, cellPosition, { silent: true });
17263
17310
  (0, editors_1._populateModelValidationErrors)(this.beans);
17264
17311
  cellCtrl?.refreshCell(FORCE_REFRESH);
17265
17312
  // refresh the styles directly rather than through refreshRow as that causes the group cell renderer to
@@ -17351,6 +17398,12 @@ class EditService extends beanStub_1.BeanStub {
17351
17398
  const { beans } = this;
17352
17399
  this.strategy ?? (this.strategy = this.createStrategy());
17353
17400
  const source = this.isBatchEditing() ? 'ui' : 'api';
17401
+ if (!eventSource || KEEP_EDITOR_SOURCES.has(eventSource)) {
17402
+ // editApi or undoRedoApi apply change without involving the editor
17403
+ (0, editors_1._syncFromEditor)(beans, position, newValue, eventSource);
17404
+ // a truthy return here indicates the operation succeeded, and if invoked from rowNode.setDataValue, will not result in a cell value change event
17405
+ return this.setNodeDataValue(position.rowNode, position.column, newValue, false);
17406
+ }
17354
17407
  const existing = this.model.getEdit(position);
17355
17408
  if (existing) {
17356
17409
  if (existing.newValue === newValue) {
@@ -17535,6 +17588,9 @@ class EditService extends beanStub_1.BeanStub {
17535
17588
  const label = translate('ariaPendingChange', 'Pending Change');
17536
17589
  this.beans.ariaAnnounce?.announceValue(label, 'pendingChange');
17537
17590
  }
17591
+ allowedFocusTargetOnValidation(cellPosition) {
17592
+ return (0, controllers_1._getCellCtrl)(this.beans, cellPosition);
17593
+ }
17538
17594
  }
17539
17595
  exports.EditService = EditService;
17540
17596
 
@@ -17568,6 +17624,7 @@ class BaseEditStrategy extends beanStub_1.BeanStub {
17568
17624
  let cellCtrl;
17569
17625
  const previous = event['previousParams'];
17570
17626
  const { editSvc, beans } = this;
17627
+ const sourceEvent = event.type === 'cellFocused' ? event.sourceEvent : null;
17571
17628
  if (previous) {
17572
17629
  cellCtrl = (0, controllers_1._getCellCtrl)(beans, previous);
17573
17630
  }
@@ -17575,9 +17632,6 @@ class BaseEditStrategy extends beanStub_1.BeanStub {
17575
17632
  const isFocusCleared = event.type === 'cellFocusCleared';
17576
17633
  // check if any editors open
17577
17634
  if (editSvc.isEditing(undefined, { withOpenEditor: true })) {
17578
- if (cellCtrl && !isFocusCleared && editSvc.checkNavWithValidation(cellCtrl, event) === 'block-stop') {
17579
- return;
17580
- }
17581
17635
  // if focus is clearing, we should stop editing
17582
17636
  // or cancel the editing if `block` and `hasErrors`
17583
17637
  const { column, rowIndex, rowPinned } = event;
@@ -17586,12 +17640,19 @@ class BaseEditStrategy extends beanStub_1.BeanStub {
17586
17640
  rowNode: (0, positionUtils_1._getRowNode)(beans, { rowIndex: rowIndex, rowPinned }),
17587
17641
  };
17588
17642
  const isBlock = gos.get('invalidEditValueMode') === 'block';
17589
- const hasError = isBlock && !!editModelSvc?.getCellValidationModel().hasCellValidation(cellPositionFromEvent);
17643
+ if (isBlock) {
17644
+ // if we are blocking on invalid edits, focus changes don't stop current editing
17645
+ return;
17646
+ }
17647
+ const shouldRevert = !isBlock;
17648
+ const hasError = !!editModelSvc?.getCellValidationModel().hasCellValidation(cellPositionFromEvent);
17649
+ const shouldCancel = shouldRevert && hasError;
17590
17650
  // if we don't have a previous cell, we don't need to force stopEditing
17591
17651
  const result = previous || isFocusCleared
17592
17652
  ? editSvc.stopEditing(undefined, {
17593
- cancel: hasError,
17594
- source: isFocusCleared ? 'api' : undefined,
17653
+ cancel: shouldCancel,
17654
+ source: isFocusCleared && shouldRevert ? 'api' : undefined,
17655
+ event: sourceEvent,
17595
17656
  })
17596
17657
  : true;
17597
17658
  // editSvc didn't handle the stopEditing, we need to do more ourselves
@@ -17611,7 +17672,7 @@ class BaseEditStrategy extends beanStub_1.BeanStub {
17611
17672
  isCellEditable({ rowNode, column }, _source = 'ui') {
17612
17673
  return column.isColumnFunc(rowNode, column.getColDef().editable);
17613
17674
  }
17614
- stop(cancel) {
17675
+ stop(cancel, event) {
17615
17676
  const editingCells = this.model.getEditPositions();
17616
17677
  const results = { all: [], pass: [], fail: [] };
17617
17678
  editingCells.forEach((cell) => {
@@ -17634,7 +17695,7 @@ class BaseEditStrategy extends beanStub_1.BeanStub {
17634
17695
  const actions = this.processValidationResults(results);
17635
17696
  if (actions.destroy.length > 0) {
17636
17697
  actions.destroy.forEach((cell) => {
17637
- (0, editors_1._destroyEditor)(this.beans, cell);
17698
+ (0, editors_1._destroyEditor)(this.beans, cell, { event });
17638
17699
  this.model.stop(cell);
17639
17700
  });
17640
17701
  }
@@ -17833,6 +17894,7 @@ class FullRowEditStrategy extends baseEditStrategy_1.BaseEditStrategy {
17833
17894
  constructor() {
17834
17895
  super(...arguments);
17835
17896
  this.beanName = 'fullRow';
17897
+ this.startedRows = [];
17836
17898
  }
17837
17899
  isCellEditable(position, source = 'ui') {
17838
17900
  const editable = super.isCellEditable(position, source);
@@ -17875,9 +17937,8 @@ class FullRowEditStrategy extends baseEditStrategy_1.BaseEditStrategy {
17875
17937
  if (this.rowNode !== rowNode) {
17876
17938
  super.cleanupEditors(position);
17877
17939
  }
17878
- if (!this.model.hasEdits({ rowNode })) {
17879
- this.dispatchRowEvent({ rowNode }, 'rowEditingStarted');
17880
- }
17940
+ this.dispatchRowEvent({ rowNode }, 'rowEditingStarted');
17941
+ this.startedRows.push(rowNode);
17881
17942
  const columns = this.beans.visibleCols.allCols;
17882
17943
  const cells = [];
17883
17944
  columns.forEach((column) => {
@@ -17911,31 +17972,34 @@ class FullRowEditStrategy extends baseEditStrategy_1.BaseEditStrategy {
17911
17972
  keep: [],
17912
17973
  };
17913
17974
  }
17914
- stop(cancel) {
17975
+ stop(cancel, event) {
17915
17976
  const { rowNode } = this;
17916
17977
  if (rowNode && !this.model.hasRowEdits(rowNode)) {
17917
17978
  return false;
17918
17979
  }
17919
- const rowEdits = this.model.getEditRow(rowNode);
17920
- let hadRowEdits = false;
17921
- for (const [, edit] of rowEdits) {
17922
- if ((0, editors_1._valuesDiffer)(edit)) {
17923
- hadRowEdits = true;
17924
- break;
17925
- }
17980
+ const changedRows = [];
17981
+ if (!cancel) {
17982
+ this.model.getEditMap().forEach((rowEdits, rowNode) => {
17983
+ if (!rowEdits || rowEdits.size === 0) {
17984
+ return;
17985
+ }
17986
+ for (const edit of rowEdits.values()) {
17987
+ if ((0, editors_1._valuesDiffer)(edit)) {
17988
+ changedRows.push(rowNode);
17989
+ // early return, we only need to know if there are any edits
17990
+ break;
17991
+ }
17992
+ }
17993
+ });
17926
17994
  }
17927
17995
  // rerun validation, new values might have triggered row validations
17928
17996
  (0, editors_1._populateModelValidationErrors)(this.beans);
17929
17997
  if (!cancel && this.editSvc?.checkNavWithValidation({ rowNode }) === 'block-stop') {
17930
17998
  return false;
17931
17999
  }
17932
- super.stop(cancel);
17933
- if (rowNode) {
17934
- if (hadRowEdits) {
17935
- this.dispatchRowEvent({ rowNode }, 'rowValueChanged');
17936
- }
17937
- this.dispatchRowEvent({ rowNode }, 'rowEditingStopped');
17938
- }
18000
+ super.stop(cancel, event);
18001
+ changedRows.forEach((rowNode) => this.dispatchRowEvent({ rowNode }, 'rowValueChanged'));
18002
+ this.cleanupEditors({ rowNode }, true);
17939
18003
  this.rowNode = undefined;
17940
18004
  return true;
17941
18005
  }
@@ -17945,20 +18009,20 @@ class FullRowEditStrategy extends baseEditStrategy_1.BaseEditStrategy {
17945
18009
  if (prev?.rowIndex === rowIndex || event.sourceEvent instanceof KeyboardEvent) {
17946
18010
  return;
17947
18011
  }
17948
- if (this.model.getRowValidationModel().getRowValidationMap().size > 0) {
18012
+ const prevCell = (0, controllers_1._getCellCtrl)(this.beans, prev);
18013
+ const isBlock = this.gos.get('invalidEditValueMode') === 'block';
18014
+ if (isBlock &&
18015
+ prevCell &&
18016
+ (this.model.getCellValidationModel().getCellValidation(prevCell) ||
18017
+ this.model.getRowValidationModel().getRowValidation(prevCell))) {
17949
18018
  return;
17950
18019
  }
17951
18020
  super.onCellFocusChanged(event);
17952
- const previous = event['previousParams'];
17953
- if (previous) {
17954
- (0, controllers_1._getRowCtrl)(this.beans, previous)?.refreshRow({ suppressFlash: true, force: true });
17955
- }
17956
18021
  }
17957
- cleanupEditors({ rowNode } = {}, includeEditing) {
17958
- super.cleanupEditors({ rowNode }, includeEditing);
17959
- if (rowNode) {
17960
- this.dispatchRowEvent({ rowNode: this.rowNode }, 'rowEditingStopped');
17961
- }
18022
+ cleanupEditors(position = {}, includeEditing) {
18023
+ super.cleanupEditors(position, includeEditing);
18024
+ this.startedRows.forEach((rowNode) => this.dispatchRowEvent({ rowNode }, 'rowEditingStopped'));
18025
+ this.startedRows.length = 0;
17962
18026
  }
17963
18027
  // returns null if no navigation should be performed
17964
18028
  moveToNextEditingCell(prevCell, backwards, event, source = 'ui') {
@@ -17989,38 +18053,19 @@ class FullRowEditStrategy extends baseEditStrategy_1.BaseEditStrategy {
17989
18053
  return null;
17990
18054
  }
17991
18055
  if (nextCell == null) {
17992
- return preventNavigation;
18056
+ return false;
17993
18057
  }
17994
18058
  const nextPos = nextCell.cellPosition;
17995
18059
  const prevEditable = prevCell.isCellEditable();
17996
18060
  const nextEditable = nextCell.isCellEditable();
17997
18061
  const rowsMatch = nextPos && prevPos.rowIndex === nextPos.rowIndex && prevPos.rowPinned === nextPos.rowPinned;
17998
- if (!rowsMatch) {
17999
- // run validation to gather row-level validation errors
18000
- (0, editors_1._populateModelValidationErrors)(this.beans);
18001
- if (this.model.getRowValidationModel().getRowValidationMap().size > 0) {
18002
- // if there was a previous row validation error, we need to check if that's still the case
18003
- if (this.editSvc.checkNavWithValidation(prevCell, event) === 'block-stop') {
18004
- return true;
18005
- }
18006
- }
18007
- else {
18008
- const rowPreventNavigation = this.editSvc.checkNavWithValidation(prevCell, event) === 'block-stop';
18009
- if (rowPreventNavigation) {
18010
- return true;
18011
- }
18012
- }
18013
- if (preventNavigation && this.model.getRowValidationModel().getRowValidation(prevCell)) {
18014
- return true;
18015
- }
18016
- }
18017
18062
  if (prevEditable) {
18018
18063
  this.setFocusOutOnEditor(prevCell);
18019
18064
  }
18020
18065
  if (nextEditable && !preventNavigation) {
18021
18066
  if (!nextCell.comp?.getCellEditor()) {
18022
18067
  // editor missing because it was outside the viewport during creating phase, attempt to create it now
18023
- (0, editors_1._setupEditor)(this.beans, nextCell, undefined, event, true);
18068
+ (0, editors_1._setupEditor)(this.beans, nextCell, { event, cellStartedEdit: true });
18024
18069
  }
18025
18070
  this.setFocusInOnEditor(nextCell);
18026
18071
  nextCell.focusCell(false, event);
@@ -18029,7 +18074,7 @@ class FullRowEditStrategy extends baseEditStrategy_1.BaseEditStrategy {
18029
18074
  nextCell.focusCell(true, event);
18030
18075
  }
18031
18076
  if (!rowsMatch && !preventNavigation) {
18032
- super.cleanupEditors(nextCell, true);
18077
+ this.cleanupEditors(nextCell, true);
18033
18078
  this.editSvc.startEditing(nextCell, { startedEdit: true, event, source, ignoreEventKey: true });
18034
18079
  }
18035
18080
  prevCell.rowCtrl?.refreshRow({ suppressFlash: true, force: true });
@@ -18038,6 +18083,7 @@ class FullRowEditStrategy extends baseEditStrategy_1.BaseEditStrategy {
18038
18083
  destroy() {
18039
18084
  super.destroy();
18040
18085
  this.rowNode = undefined;
18086
+ this.startedRows.length = 0;
18041
18087
  }
18042
18088
  }
18043
18089
  exports.FullRowEditStrategy = FullRowEditStrategy;
@@ -18086,8 +18132,8 @@ class SingleCellEditStrategy extends baseEditStrategy_1.BaseEditStrategy {
18086
18132
  dispatchRowEvent(_position, _type) {
18087
18133
  // NOP - single cell edit strategy does not dispatch row events
18088
18134
  }
18089
- stop(cancel) {
18090
- super.stop(cancel);
18135
+ stop(cancel, event) {
18136
+ super.stop(cancel, event);
18091
18137
  this.rowNode = undefined;
18092
18138
  this.column = undefined;
18093
18139
  return true;
@@ -18125,7 +18171,7 @@ class SingleCellEditStrategy extends baseEditStrategy_1.BaseEditStrategy {
18125
18171
  // undesirable so we suspend the model while we find the next cell.
18126
18172
  this.model.suspend(true);
18127
18173
  }
18128
- else {
18174
+ if (!preventNavigation) {
18129
18175
  // before we stop editing, we need to focus the cell element
18130
18176
  // so the grid doesn't detect that focus has left the grid
18131
18177
  prevCell.eGui.focus();
@@ -18156,7 +18202,7 @@ class SingleCellEditStrategy extends baseEditStrategy_1.BaseEditStrategy {
18156
18202
  return null;
18157
18203
  }
18158
18204
  if (nextCell == null) {
18159
- return preventNavigation;
18205
+ return false;
18160
18206
  }
18161
18207
  const nextPos = nextCell.cellPosition;
18162
18208
  const prevEditable = prevCell.isCellEditable();
@@ -18165,23 +18211,14 @@ class SingleCellEditStrategy extends baseEditStrategy_1.BaseEditStrategy {
18165
18211
  if (!rowsMatch) {
18166
18212
  // run validation to gather row-level validation errors
18167
18213
  (0, editors_1._populateModelValidationErrors)(this.beans);
18168
- if (this.model.getRowValidationModel().getRowValidationMap().size > 0) {
18169
- // if there was a previous row validation error, we need to check if that's still the case
18170
- if (this.editSvc.checkNavWithValidation(prevCell, event) === 'block-stop') {
18171
- return true;
18172
- }
18173
- }
18174
- else {
18214
+ if ((this.model.getRowValidationModel().getRowValidationMap().size ?? 0) === 0) {
18175
18215
  const rowPreventNavigation = this.editSvc.checkNavWithValidation(prevCell, event) === 'block-stop';
18176
18216
  if (rowPreventNavigation) {
18177
18217
  return true;
18178
18218
  }
18179
18219
  }
18180
- if (preventNavigation && this.model.getRowValidationModel().getRowValidation(prevCell)) {
18181
- return true;
18182
- }
18183
18220
  }
18184
- if (prevEditable) {
18221
+ if (prevEditable && !preventNavigation) {
18185
18222
  this.setFocusOutOnEditor(prevCell);
18186
18223
  }
18187
18224
  if (!rowsMatch && !preventNavigation) {
@@ -18193,14 +18230,11 @@ class SingleCellEditStrategy extends baseEditStrategy_1.BaseEditStrategy {
18193
18230
  nextCell.focusCell(false, event);
18194
18231
  if (!nextCell.comp?.getCellEditor()) {
18195
18232
  // editor missing because it was outside the viewport during creating phase, attempt to create it now
18196
- (0, editors_1._setupEditor)(this.beans, nextCell, undefined, event, true);
18233
+ (0, editors_1._setupEditor)(this.beans, nextCell, { event, cellStartedEdit: true });
18197
18234
  }
18198
18235
  this.setFocusInOnEditor(nextCell);
18199
18236
  }
18200
18237
  else {
18201
- if (preventNavigation && this.model.getCellValidationModel().getCellValidation(prevCell)) {
18202
- return true;
18203
- }
18204
18238
  nextCell.focusCell(true, event);
18205
18239
  }
18206
18240
  prevCell.rowCtrl?.refreshRow({ suppressFlash: true, force: true });
@@ -18394,7 +18428,14 @@ function _getRowCtrl(beans, inputs = {}) {
18394
18428
  }
18395
18429
  const { rowModel, rowRenderer } = beans;
18396
18430
  let { rowNode } = inputs;
18397
- rowNode ?? (rowNode = rowId ? (0, positionUtils_1._getRowById)(beans, rowId, rowPinned) : rowModel.getRow(rowIndex));
18431
+ if (!rowNode) {
18432
+ if (rowId) {
18433
+ rowNode = (0, positionUtils_1._getRowById)(beans, rowId, rowPinned);
18434
+ }
18435
+ else if (rowIndex != null) {
18436
+ rowNode = rowModel.getRow(rowIndex);
18437
+ }
18438
+ }
18398
18439
  return rowRenderer.getRowCtrls(rowNode ? [rowNode] : [])?.[0];
18399
18440
  }
18400
18441
  exports._getRowCtrl = _getRowCtrl;
@@ -18513,7 +18554,7 @@ const getCellEditorInstances = (beans, params = {}) => getCellEditorInstanceMap(
18513
18554
  exports.getCellEditorInstances = getCellEditorInstances;
18514
18555
  function _setupEditors(beans, editingCells, position, key, event, cellStartedEdit) {
18515
18556
  if (editingCells.length === 0 && position?.rowNode && position?.column) {
18516
- _setupEditor(beans, position, key, event, cellStartedEdit);
18557
+ _setupEditor(beans, position, { key, event, cellStartedEdit });
18517
18558
  }
18518
18559
  const { valueSvc, editSvc, editModelSvc } = beans;
18519
18560
  const { rowNode, column } = position ?? {};
@@ -18535,7 +18576,11 @@ function _setupEditors(beans, editingCells, position, key, event, cellStartedEdi
18535
18576
  continue;
18536
18577
  }
18537
18578
  const shouldStartEditing = cellStartedEdit && rowNode === curCellCtrl.rowNode && curCellCtrl.column === column;
18538
- _setupEditor(beans, { rowNode: rowNode, column: curCellCtrl.column }, shouldStartEditing ? key : null, shouldStartEditing ? event : null, shouldStartEditing);
18579
+ _setupEditor(beans, { rowNode: rowNode, column: curCellCtrl.column }, {
18580
+ key: shouldStartEditing ? key : null,
18581
+ event: shouldStartEditing ? event : null,
18582
+ cellStartedEdit: shouldStartEditing,
18583
+ });
18539
18584
  }
18540
18585
  return;
18541
18586
  }
@@ -18547,17 +18592,18 @@ function _valuesDiffer({ newValue, oldValue }) {
18547
18592
  return newValue !== oldValue;
18548
18593
  }
18549
18594
  exports._valuesDiffer = _valuesDiffer;
18550
- function _setupEditor(beans, position, key, event, cellStartedEdit) {
18595
+ function _setupEditor(beans, position, params) {
18596
+ const { key, event, cellStartedEdit, silent } = params ?? {};
18551
18597
  const cellCtrl = (0, controllers_1._getCellCtrl)(beans, position);
18552
18598
  const editorComp = cellCtrl?.comp?.getCellEditor();
18553
18599
  const editorParams = _createEditorParams(beans, position, key, cellStartedEdit);
18554
- const oldValue = beans.valueSvc.getValue(position.column, position.rowNode, undefined, 'api');
18600
+ const previousEdit = beans.editModelSvc?.getEdit(position);
18555
18601
  // if key is a single character, then we treat it as user input
18556
18602
  let newValue = key?.length === 1 ? key : editorParams.value;
18557
18603
  if (newValue === undefined) {
18558
- newValue = oldValue;
18604
+ newValue = previousEdit?.oldValue;
18559
18605
  }
18560
- beans.editModelSvc?.setEdit(position, { newValue: newValue ?? exports.UNEDITED, oldValue, state: 'editing' });
18606
+ beans.editModelSvc?.setEdit(position, { newValue: newValue ?? exports.UNEDITED, state: 'editing' });
18561
18607
  if (editorComp) {
18562
18608
  // don't reinitialise, just refresh if possible
18563
18609
  editorComp.refresh?.(editorParams);
@@ -18575,7 +18621,9 @@ function _setupEditor(beans, position, key, event, cellStartedEdit) {
18575
18621
  cellCtrl.editCompDetails = compDetails;
18576
18622
  cellCtrl.comp?.setEditDetails(compDetails, popup, popupLocation, beans.gos.get('reactiveCustomComponents'));
18577
18623
  cellCtrl?.rowCtrl?.refreshRow({ suppressFlash: true });
18578
- beans.editSvc?.dispatchCellEvent(position, null, 'cellEditingStarted');
18624
+ if (!silent) {
18625
+ beans.editSvc?.dispatchCellEvent(position, event, 'cellEditingStarted');
18626
+ }
18579
18627
  }
18580
18628
  return;
18581
18629
  }
@@ -18589,10 +18637,6 @@ function _valueFromEditor(cancel, cellComp) {
18589
18637
  if (!cellEditor) {
18590
18638
  return noValueResult;
18591
18639
  }
18592
- const userWantsToCancel = cellEditor.isCancelAfterEnd?.();
18593
- if (userWantsToCancel) {
18594
- return noValueResult;
18595
- }
18596
18640
  const validationErrors = cellEditor.getValidationErrors?.();
18597
18641
  if ((validationErrors?.length ?? 0) > 0) {
18598
18642
  return noValueResult;
@@ -18673,7 +18717,7 @@ function checkAndPreventDefault(params, event) {
18673
18717
  }
18674
18718
  return params;
18675
18719
  }
18676
- function _syncFromEditors(beans) {
18720
+ function _syncFromEditors(beans, params) {
18677
18721
  beans.editModelSvc?.getEditPositions().forEach((cellId) => {
18678
18722
  const cellCtrl = (0, controllers_1._getCellCtrl)(beans, cellId);
18679
18723
  if (!cellCtrl) {
@@ -18683,12 +18727,12 @@ function _syncFromEditors(beans) {
18683
18727
  if (!newValueExists) {
18684
18728
  return;
18685
18729
  }
18686
- _syncFromEditor(beans, cellId, newValue);
18730
+ _syncFromEditor(beans, cellId, newValue, undefined, params);
18687
18731
  });
18688
18732
  }
18689
18733
  exports._syncFromEditors = _syncFromEditors;
18690
- function _syncFromEditor(beans, position, newValue, source) {
18691
- const { editModelSvc, valueSvc, eventSvc } = beans;
18734
+ function _syncFromEditor(beans, position, newValue, _source, params) {
18735
+ const { editModelSvc, valueSvc } = beans;
18692
18736
  if (!editModelSvc) {
18693
18737
  return;
18694
18738
  }
@@ -18696,10 +18740,9 @@ function _syncFromEditor(beans, position, newValue, source) {
18696
18740
  if (!(rowNode && column)) {
18697
18741
  return;
18698
18742
  }
18699
- const oldValue = valueSvc.getValue(column, rowNode, undefined, 'api');
18743
+ const oldValue = editModelSvc.getEdit(position)?.oldValue ?? valueSvc.getValue(column, rowNode, undefined, 'api');
18700
18744
  const cellCtrl = (0, controllers_1._getCellCtrl)(beans, position);
18701
18745
  const hasEditor = !!cellCtrl?.comp?.getCellEditor();
18702
- const prevEditValue = editModelSvc?.getEdit(position)?.newValue;
18703
18746
  // Only handle undefined, null is used to indicate a cleared cell value
18704
18747
  if (newValue === undefined) {
18705
18748
  newValue = exports.UNEDITED;
@@ -18708,40 +18751,35 @@ function _syncFromEditor(beans, position, newValue, source) {
18708
18751
  editModelSvc.setEdit(position, { newValue, oldValue, state: hasEditor ? 'editing' : 'changed' });
18709
18752
  // re-read the value once it's been through all the formatting and parsing
18710
18753
  const { value } = valueSvc.getValueForDisplay(column, rowNode, true);
18711
- editModelSvc.getEdit(position).newValue = value;
18712
- if (prevEditValue === newValue || hasEditor) {
18754
+ newValue = value;
18755
+ // persist newly formatted value
18756
+ editModelSvc.setEdit(position, { newValue });
18757
+ if (newValue === oldValue || hasEditor) {
18713
18758
  // If the value hasn't changed or the editor is currently open, we don't need to dispatch an event
18714
18759
  return;
18715
18760
  }
18716
- const { rowIndex, rowPinned, data } = rowNode;
18717
- eventSvc.dispatchEvent({
18718
- type: 'cellEditValuesChanged',
18719
- value: newValue,
18720
- colDef: column.getColDef(),
18721
- newValue,
18722
- oldValue,
18723
- source,
18724
- column,
18725
- rowIndex,
18726
- rowPinned,
18727
- data,
18728
- node: rowNode,
18761
+ const edit = editModelSvc.getEdit(position);
18762
+ beans.editSvc?.dispatchCellEvent(position, params?.event, 'cellValueChanged', {
18763
+ valueChanged: edit && _valuesDiffer(edit),
18764
+ newValue: edit?.newValue,
18765
+ oldValue: edit?.oldValue,
18729
18766
  });
18730
18767
  }
18731
18768
  exports._syncFromEditor = _syncFromEditor;
18732
- function _destroyEditors(beans, edits) {
18769
+ function _destroyEditors(beans, edits, params) {
18733
18770
  if (!edits) {
18734
18771
  edits = beans.editModelSvc?.getEditPositions();
18735
18772
  }
18736
- edits.forEach((cellPosition) => _destroyEditor(beans, cellPosition));
18773
+ edits.forEach((cellPosition) => _destroyEditor(beans, cellPosition, params));
18737
18774
  }
18738
18775
  exports._destroyEditors = _destroyEditors;
18739
- function _destroyEditor(beans, position) {
18776
+ function _destroyEditor(beans, position, params) {
18777
+ const { editSvc, editModelSvc } = beans;
18740
18778
  const { rowNode, column } = position;
18741
18779
  const cellCtrl = (0, controllers_1._getCellCtrl)(beans, position);
18742
18780
  if (!cellCtrl) {
18743
- if (beans.editModelSvc?.hasEdits(position) && rowNode && column) {
18744
- beans.editModelSvc?.setState(position, 'changed');
18781
+ if (editModelSvc?.hasEdits(position) && rowNode && column) {
18782
+ editModelSvc?.setState(position, 'changed');
18745
18783
  }
18746
18784
  return;
18747
18785
  }
@@ -18751,23 +18789,28 @@ function _destroyEditor(beans, position) {
18751
18789
  return;
18752
18790
  }
18753
18791
  const errorMessages = comp?.getCellEditor()?.getValidationErrors?.();
18754
- const cellValidationModel = beans.editModelSvc?.getCellValidationModel();
18792
+ const cellValidationModel = editModelSvc?.getCellValidationModel();
18755
18793
  if (errorMessages?.length) {
18756
18794
  cellValidationModel?.setCellValidation(position, { errorMessages });
18757
18795
  }
18758
18796
  else {
18759
18797
  cellValidationModel?.clearCellValidation(position);
18760
18798
  }
18761
- comp?.setEditDetails(); // passing nothing stops editing
18762
- if (beans.editModelSvc?.hasEdits(position) && rowNode && column) {
18763
- beans.editModelSvc?.setState(position, 'changed');
18799
+ const wasEditing = editModelSvc?.getEdit(position)?.state === 'editing';
18800
+ if (editModelSvc?.hasEdits(position) && rowNode && column) {
18801
+ editModelSvc?.setState(position, 'changed');
18764
18802
  }
18803
+ comp?.setEditDetails(); // passing nothing stops editing
18765
18804
  comp?.refreshEditStyles(false, false);
18766
18805
  cellCtrl?.refreshCell({ force: true, suppressFlash: true });
18767
- const edit = beans.editModelSvc?.getEdit(position);
18768
- beans.editSvc?.dispatchCellEvent(position, null, 'cellEditingStopped', {
18769
- valueChanged: edit && _valuesDiffer(edit),
18770
- });
18806
+ const edit = editModelSvc?.getEdit(position);
18807
+ if (wasEditing && edit?.state === 'changed' && !params?.silent) {
18808
+ editSvc?.dispatchCellEvent(position, params?.event, 'cellEditingStopped', {
18809
+ valueChanged: edit && _valuesDiffer(edit),
18810
+ newValue: edit?.newValue,
18811
+ oldValue: edit?.oldValue,
18812
+ });
18813
+ }
18771
18814
  }
18772
18815
  exports._destroyEditor = _destroyEditor;
18773
18816
  function _populateModelValidationErrors(beans) {
@@ -20364,7 +20407,7 @@ class RowNode {
20364
20407
  if (!column) {
20365
20408
  return false;
20366
20409
  }
20367
- const oldValue = valueSvc.getValueForDisplay(column, this).value;
20410
+ const oldValue = valueSvc.getValueForDisplay(column, this, undefined, undefined, 'api').value;
20368
20411
  if (gos.get('readOnlyEdit')) {
20369
20412
  const { beans: { eventSvc }, data, rowIndex, rowPinned, } = this;
20370
20413
  eventSvc.dispatchEvent({
@@ -21284,9 +21327,10 @@ class BaseGridSerializingSession {
21284
21327
  return value ?? '';
21285
21328
  }
21286
21329
  extractRowCellValue(column, currentColumnIndex, accumulatedRowIndex, type, node) {
21330
+ const isFullWidthGroup = currentColumnIndex === 0 && (0, gridOptionsUtils_1._isFullWidthGroupRow)(this.gos, node, this.colModel.isPivotMode());
21287
21331
  if (this.processRowGroupCallback &&
21288
21332
  (this.gos.get('treeData') || node.group) &&
21289
- column.isRowGroupDisplayed(node.rowGroupColumn?.getColId() ?? '')) {
21333
+ (column.isRowGroupDisplayed(node.rowGroupColumn?.getColId() ?? '') || isFullWidthGroup)) {
21290
21334
  return { value: this.processRowGroupCallback((0, gridOptionsUtils_1._addGridCommonParams)(this.gos, { column, node })) ?? '' };
21291
21335
  }
21292
21336
  if (this.processCellCallback) {
@@ -21305,7 +21349,6 @@ class BaseGridSerializingSession {
21305
21349
  const isTreeData = this.gos.get('treeData');
21306
21350
  const valueService = this.valueSvc;
21307
21351
  const isGrandTotalRow = node.level === -1 && node.footer;
21308
- const isFullWidthGroup = currentColumnIndex === 0 && (0, gridOptionsUtils_1._isFullWidthGroupRow)(this.gos, node, this.colModel.isPivotMode());
21309
21352
  const isMultiAutoCol = column.colDef.showRowGroup === true && (node.group || isTreeData);
21310
21353
  // when using single auto group column or group row, create arrow separated string of group vals
21311
21354
  if (!isGrandTotalRow && (isFullWidthGroup || isMultiAutoCol)) {
@@ -27687,8 +27730,10 @@ class TextFilterHandler extends simpleFilterHandler_1.SimpleFilterHandler {
27687
27730
  }
27688
27731
  updateParams(params) {
27689
27732
  super.updateParams(params);
27690
- this.matcher = params.textMatcher ?? defaultMatcher;
27691
- this.formatter = params.textFormatter ?? (params.caseSensitive ? defaultFormatter : defaultLowercaseFormatter);
27733
+ const filterParams = params.filterParams;
27734
+ this.matcher = filterParams.textMatcher ?? defaultMatcher;
27735
+ this.formatter =
27736
+ filterParams.textFormatter ?? (filterParams.caseSensitive ? defaultFormatter : defaultLowercaseFormatter);
27692
27737
  }
27693
27738
  evaluateNullValue(filterType) {
27694
27739
  const filterTypesAllowNulls = ['notEqual', 'notContains', 'blank'];
@@ -29958,7 +30003,16 @@ class GridBodyScrollFeature extends beanStub_1.BeanStub {
29958
30003
  // adding and removing the grid from the DOM both resets the scroll position and
29959
30004
  // triggers a resize event, so notify listeners if the scroll position has changed
29960
30005
  checkScrollLeft() {
29961
- if (this.scrollLeft !== this.centerRowsCtrl.getCenterViewportScrollLeft()) {
30006
+ const scrollLeft = this.scrollLeft;
30007
+ let hasHorizontalScrollersOutOfSync = false;
30008
+ for (const source of HORIZONTAL_SOURCES) {
30009
+ const viewport = this.getViewportForSource(source);
30010
+ if (viewport.scrollLeft !== scrollLeft) {
30011
+ hasHorizontalScrollersOutOfSync = true;
30012
+ break;
30013
+ }
30014
+ }
30015
+ if (hasHorizontalScrollersOutOfSync) {
29962
30016
  this.onHScroll(VIEWPORT);
29963
30017
  }
29964
30018
  }
@@ -45011,7 +45065,7 @@ class CellCtrl extends beanStub_1.BeanStub {
45011
45065
  }
45012
45066
  onPopupEditorClosed() {
45013
45067
  const { editSvc } = this.beans;
45014
- if (!editSvc?.isEditing(this)) {
45068
+ if (!editSvc?.isEditing(this, { withOpenEditor: true })) {
45015
45069
  return;
45016
45070
  }
45017
45071
  // note: this happens because of a click outside of the grid or if the popupEditor
@@ -45792,6 +45846,15 @@ class CellKeyboardListenerFeature extends beanStub_1.BeanStub {
45792
45846
  }
45793
45847
  onF2KeyDown(event) {
45794
45848
  const { cellCtrl, beans: { editSvc }, } = this;
45849
+ const editing = editSvc?.isEditing();
45850
+ if (editing) {
45851
+ // re-run ALL validations, F2 is used to initiate a new edit. If we have one already in progress,
45852
+ // we want to ensure it's valid before initiating a new edit cycle
45853
+ (0, editors_1._populateModelValidationErrors)(this.beans);
45854
+ if (editSvc?.checkNavWithValidation(undefined, event) === 'block-stop') {
45855
+ return;
45856
+ }
45857
+ }
45795
45858
  editSvc?.startEditing(cellCtrl, { startedEdit: true, event });
45796
45859
  }
45797
45860
  onEscapeKeyDown(event) {
@@ -61277,6 +61340,7 @@ exports.AG_GRID_ERRORS = {
61277
61340
  287: () => '`api.doFilterAction()` requires `enableFilterHandlers = true',
61278
61341
  288: () => '`api.getColumnFilterModel(key, true)` requires `enableFilterHandlers = true',
61279
61342
  289: ({ rowModelType }) => `Row Model '${rowModelType}' is not supported with Batch Editing`,
61343
+ 290: ({ rowIndex, rowPinned }) => `Row with index '${rowIndex}' and pinned state '${rowPinned}' not found`,
61280
61344
  };
61281
61345
  function getError(errorId, args) {
61282
61346
  const msgOrFunc = exports.AG_GRID_ERRORS[errorId];
@@ -63781,7 +63845,7 @@ exports.VanillaFrameworkOverrides = VanillaFrameworkOverrides;
63781
63845
  Object.defineProperty(exports, "__esModule", ({ value: true }));
63782
63846
  exports.VERSION = void 0;
63783
63847
  // DO NOT UPDATE MANUALLY: Generated from script during build time
63784
- exports.VERSION = '34.0.0';
63848
+ exports.VERSION = '34.0.2';
63785
63849
 
63786
63850
 
63787
63851
  /***/ }),