diff --git a/src/models/column.interface.ts b/src/models/column.interface.ts index 7b45aa11..30e0c149 100644 --- a/src/models/column.interface.ts +++ b/src/models/column.interface.ts @@ -3,6 +3,7 @@ import type { CellMenuOption, CustomTooltipOption, Editor, + EditorConstructor, EditorValidator, Formatter, FormatterResultWithHtml, @@ -84,7 +85,7 @@ export interface Column { disableTooltip?: boolean; /** Any inline editor function that implements Editor for the cell value or ColumnEditor */ - editor?: Editor | { model?: Editor; } | null; + editor?: Editor | EditorConstructor | null; /** Editor number fixed decimal places */ editorFixedDecimalPlaces?: number; diff --git a/src/models/editor.interface.ts b/src/models/editor.interface.ts index 84358de5..07ba4515 100644 --- a/src/models/editor.interface.ts +++ b/src/models/editor.interface.ts @@ -1,6 +1,4 @@ -import type { EditorArguments } from './editorArguments.interface'; -import type { EditorValidationResult } from './editorValidationResult.interface'; - +import type { Column, EditorArguments, EditorValidationResult, GridOption } from './index'; /** * SlickGrid Editor interface, more info can be found on the SlickGrid repo * https://github.com/6pac/SlickGrid/wiki/Writing-custom-cell-editors @@ -77,8 +75,7 @@ export interface Editor { /** Update the Editor DOM element value with a provided value, we can optionally apply the value to the item dataContext object */ setValue?: (value: any, isApplyingValue?: boolean, triggerOnCompositeEditorChange?: boolean) => void; - - suppressClearOnEdit?: boolean; + /** * Validate user input and return the result along with the validation message. * if the input is valid then the validation result output would be returning { valid:true, msg:null } @@ -86,3 +83,10 @@ export interface Editor { */ validate: (targetElm?: HTMLElement, options?: any) => EditorValidationResult; } + +export type EditorConstructor = { + new = Column, O extends GridOption = GridOption>(args?: EditorArguments): Editor; + + /** Static flag used in makeActiveCellEditable. */ + suppressClearOnEdit?: boolean; +}; \ No newline at end of file diff --git a/src/models/editorArguments.interface.ts b/src/models/editorArguments.interface.ts index b3b28c2d..f8120719 100644 --- a/src/models/editorArguments.interface.ts +++ b/src/models/editorArguments.interface.ts @@ -1,9 +1,8 @@ - -import { Column, ElementPosition, PositionMethod } from './index'; import type { SlickDataView } from '../slick.dataview'; import type { SlickGrid } from '../slick.grid'; +import type { Column, ElementPosition, GridOption, PositionMethod } from './index'; -export interface EditorArguments { +export interface EditorArguments = Column, O extends GridOption = GridOption> { /** Column Definition */ column: Column; @@ -17,13 +16,13 @@ export interface EditorArguments { container: HTMLDivElement; /** Slick DataView */ - dataView: SlickDataView; + dataView?: SlickDataView; /** Event that was triggered */ event: Event; /** Slick Grid object */ - grid: SlickGrid; + grid: SlickGrid; /** Grid Position */ gridPosition: ElementPosition; diff --git a/src/models/gridOption.interface.ts b/src/models/gridOption.interface.ts index 5642a0e0..a1967440 100644 --- a/src/models/gridOption.interface.ts +++ b/src/models/gridOption.interface.ts @@ -1,4 +1,4 @@ -import type { Column as BaseColumn, CellMenuOption, ColumnPickerOption, ColumnReorderFunction, ContextMenuOption, CustomTooltipOption, EditCommand, Editor, ExcelCopyBufferOption, Formatter, GridMenuOption, ItemMetadata, } from './index'; +import type { Column as BaseColumn, CellMenuOption, ColumnPickerOption, ColumnReorderFunction, ContextMenuOption, CustomTooltipOption, EditCommand, EditorConstructor, ExcelCopyBufferOption, Formatter, GridMenuOption, ItemMetadata, } from './index'; import type { SlickEditorLock } from '../slick.core'; export interface CellViewportRange { @@ -121,7 +121,7 @@ export interface GridOption { editCommandHandler?: (item: any, column: C, command: EditCommand) => void; /** Editor classes factory */ - editorFactory?: null | { getEditor: (col: C) => Editor; }; + editorFactory?: null | { getEditor: (col: C) => EditorConstructor; }; /** a global singleton editor lock. */ editorLock?: SlickEditorLock; diff --git a/src/slick.grid.ts b/src/slick.grid.ts index d4a9cf52..a1244dfb 100644 --- a/src/slick.grid.ts +++ b/src/slick.grid.ts @@ -13,7 +13,9 @@ import type { DragPosition, DragRowMove, Editor, - EditController, + EditorArguments, + EditorConstructor, + EditController, Formatter, FormatterOverrideCallback, FormatterResultObject, @@ -3841,19 +3843,19 @@ export class SlickGrid = Column, O e this._options.defaultFormatter) as Formatter; } - protected getEditor(row: number, cell: number): Editor | undefined { + protected getEditor(row: number, cell: number): Editor | EditorConstructor | null | undefined { const column = this.columns[cell]; const rowMetadata = (this.data as CustomDataView)?.getItemMetadata?.(row); const columnMetadata = rowMetadata?.columns; if (columnMetadata?.[column.id]?.editor !== undefined) { - return columnMetadata[column.id].editor as Editor; + return columnMetadata[column.id].editor; } if (columnMetadata?.[cell]?.editor !== undefined) { - return columnMetadata[cell].editor as Editor; + return columnMetadata[cell].editor; } - return (column.editor || (this._options?.editorFactory?.getEditor(column))) as Editor; + return (column.editor || (this._options?.editorFactory?.getEditor(column))); } protected getDataItemValueForColumn(item: TData, columnDef: C) { @@ -5901,11 +5903,11 @@ export class SlickGrid = Column, O e } - editActiveCell(editor: Editor, preClickModeOn?: boolean | null, e?: Event) { + editActiveCell(editor: EditorConstructor, preClickModeOn?: boolean | null, e?: Event) { this.makeActiveCellEditable(editor, preClickModeOn, e); } - protected makeActiveCellEditable(editor?: Editor, preClickModeOn?: boolean | null, e?: Event | SlickEvent_) { + protected makeActiveCellEditable(editor?: EditorConstructor, preClickModeOn?: boolean | null, e?: Event | SlickEvent_) { if (!this.activeCellNode) { return; } @@ -5931,7 +5933,12 @@ export class SlickGrid = Column, O e this.getEditorLock()?.activate(this.editController as EditController); this.activeCellNode.classList.add('editable'); - const useEditor: any = editor || this.getEditor(this.activeRow, this.activeCell); + const useEditor = editor || this.getEditor(this.activeRow, this.activeCell); + // editor was null and columnMetadata and editorFactory returned null or undefined + // the editor must be constructable. Also makes sure that useEditor is of type EditorConstructor + if (!useEditor || typeof useEditor !== 'function') { + return; + } // don't clear the cell if a custom editor is passed through if (!editor && !useEditor.suppressClearOnEdit) { @@ -5942,7 +5949,8 @@ export class SlickGrid = Column, O e metadata = metadata?.columns as any; const columnMetaData = metadata && (metadata[columnDef.id as keyof ItemMetadata] || (metadata as any)[this.activeCell]); - this.currentEditor = new useEditor({ + + const editorArgs: EditorArguments = { grid: this, gridPosition: this.absBox(this._container), position: this.absBox(this.activeCellNode), @@ -5950,10 +5958,12 @@ export class SlickGrid = Column, O e column: columnDef, columnMetaData, item: item || {}, - event: e, + event: e as Event, commitChanges: this.commitEditAndSetFocus.bind(this), cancelChanges: this.cancelEditAndSetFocus.bind(this) - }); + }; + + this.currentEditor = new useEditor(editorArgs); if (item && this.currentEditor) { this.currentEditor.loadValue(item);