Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 6 additions & 76 deletions packages/common/src/editors/autocompleterEditor.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,25 @@
import { BindingEventService } from '@slickgrid-universal/binding';
import { classNameToList, createDomElement, isObject, isPrimitiveValue, setDeepValue, toKebabCase } from '@slickgrid-universal/utils';
import autocompleter from 'autocompleter';
import type { AutocompleteItem, AutocompleteResult, AutocompleteSettings } from 'autocompleter';
import { addAutocompleteLoadingByOverridingFetch } from '../commonEditorFilter/commonEditorFilterUtils.js';
import { applyHtmlToElement, SlickEventData, type SlickGrid } from '../core/index.js';
import { applyHtmlToElement } from '../core/index.js';
import { textValidator } from '../editorValidators/textValidator.js';
import type {
AutocompleterOption,
AutocompleteSearchItem,
CollectionCustomStructure,
CollectionOverrideArgs,
Column,
ColumnEditor,
CompositeEditorOption,
Editor,
EditorArguments,
EditorValidationResult,
EditorValidator,
GridOption,
Locale,
ValidateOption,
} from '../interfaces/index.js';
import type { TranslaterService } from '../services/translater.service.js';
import { findOrDefault, getDescendantProperty } from '../services/utilities.js';
import { Constants } from './../constants.js';
import { BaseEditorClass } from './baseEditorClass.js';

// minimum length of chars to type before starting to start querying
const MIN_LENGTH = 3;
Expand All @@ -32,9 +28,8 @@ const MIN_LENGTH = 3;
* An example of a 'detached' editor.
* KeyDown events are also handled to provide handling for Tab, Shift-Tab, Esc and Ctrl-Enter.
*/
export class AutocompleterEditor<T extends AutocompleteItem = any> implements Editor {
export class AutocompleterEditor<T extends AutocompleteItem = any> extends BaseEditorClass implements Editor {
protected _autocompleterOptions!: Partial<AutocompleterOption<T>>;
protected _bindEventService: BindingEventService;
protected _currentValue: any;
protected _defaultTextValue!: string;
protected _originalValue: any;
Expand All @@ -56,12 +51,6 @@ export class AutocompleterEditor<T extends AutocompleteItem = any> implements Ed
/** The translate library */
protected _translater?: TranslaterService;

/** is the Editor disabled? */
disabled = false;

/** SlickGrid Grid object */
grid: SlickGrid;

/** The property name for labels in the collection */
labelName!: string;

Expand All @@ -80,15 +69,13 @@ export class AutocompleterEditor<T extends AutocompleteItem = any> implements Ed
finalCollection: T[] = [];

constructor(protected readonly args: EditorArguments) {
this.grid = args.grid;
this._bindEventService = new BindingEventService();
super(args);
if (this.gridOptions?.translater) {
this._translater = this.gridOptions.translater;
}

// get locales provided by user in forRoot or else use default English locales via the Constants
this._locales = this.gridOptions?.locales || Constants.locales;

this.init();
}

Expand All @@ -112,16 +99,6 @@ export class AutocompleterEditor<T extends AutocompleteItem = any> implements Ed
return this._elementCollection;
}

/** Get Column Definition object */
get columnDef(): Column {
return this.args.column;
}

/** Get Column Editor object */
get columnEditor(): ColumnEditor {
return this.columnDef?.editor || ({} as ColumnEditor);
}

/** Getter for the Custom Structure if exist */
get customStructure(): CollectionCustomStructure | undefined {
let customStructure = this.columnEditor?.customStructure;
Expand All @@ -144,25 +121,11 @@ export class AutocompleterEditor<T extends AutocompleteItem = any> implements Ed
return { ...this.gridOptions.defaultEditorOptions?.autocompleter, ...this.columnEditor?.options };
}

/** Getter for the Grid Options pulled through the Grid Object */
get gridOptions(): GridOption {
return this.grid?.getOptions() ?? {};
}

/** Kraaden AutoComplete instance */
get instance(): AutocompleteResult | undefined {
return this._instance;
}

get hasAutoCommitEdit(): boolean {
return this.gridOptions.autoCommitEdit ?? false;
}

/** Get the Validator function, can be passed in Editor property or Column Definition */
get validator(): EditorValidator | undefined {
return this.columnEditor?.validator ?? this.columnDef?.validator;
}

init(): void {
this.labelName = this.customStructure?.label ?? 'label';
this.valueName = this.customStructure?.value ?? 'value';
Expand Down Expand Up @@ -441,17 +404,7 @@ export class AutocompleterEditor<T extends AutocompleteItem = any> implements Ed

/** when it's a Composite Editor, we'll check if the Editor is editable (by checking onBeforeEditCell) and if not Editable we'll disable the Editor */
protected applyInputUsabilityState(): void {
const activeCell = this.grid.getActiveCell();
const isCellEditable = this.grid.onBeforeEditCell
.notify({
...activeCell,
item: this.dataContext,
column: this.args.column,
grid: this.grid,
target: 'composite',
compositeEditorOptions: this.args.compositeEditorOptions,
})
.getReturnValue();
const isCellEditable = super.checkInputUsabilityState();
this.disable(isCellEditable === false);
}

Expand All @@ -461,11 +414,6 @@ export class AutocompleterEditor<T extends AutocompleteItem = any> implements Ed
triggeredBy: 'user' | 'system' = 'user',
isCalledByClearValue = false
): void {
const activeCell = this.grid.getActiveCell();
const column = this.args.column;
const columnId = this.columnDef?.id ?? '';
const item = this.dataContext;
const grid = this.grid;
const newValue = this.serializeValue();

// when valid, we'll also apply the new value to the dataContext item object
Expand All @@ -474,25 +422,7 @@ export class AutocompleterEditor<T extends AutocompleteItem = any> implements Ed
}
this.applyValue(compositeEditorOptions.formValues, newValue);

const isExcludeDisabledFieldFormValues = this.gridOptions?.compositeEditorOptions?.excludeDisabledFieldFormValues ?? false;
if (
isCalledByClearValue ||
(this.disabled && isExcludeDisabledFieldFormValues && compositeEditorOptions.formValues.hasOwnProperty(columnId))
) {
delete compositeEditorOptions.formValues[columnId]; // when the input is disabled we won't include it in the form result object
}
grid.onCompositeEditorChange.notify(
{
...activeCell,
item,
grid,
column,
formValues: compositeEditorOptions.formValues,
editors: compositeEditorOptions.editors,
triggeredBy,
},
new SlickEventData(event)
);
super.handleChangeOnCompositeEditor(event, compositeEditorOptions, triggeredBy, isCalledByClearValue);
}

// this function should be protected but for unit tests purposes we'll make it public until a better solution is found
Expand Down
102 changes: 102 additions & 0 deletions packages/common/src/editors/baseEditorClass.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import { BindingEventService } from '@slickgrid-universal/binding';
import { SlickEventData, type SlickGrid } from '../core/index.js';
import type { Column, ColumnEditor, CompositeEditorOption, EditorArguments, EditorValidator, GridOption } from './../interfaces/index.js';

/*
* An example of a 'detached' editor.
* KeyDown events are also handled to provide handling for Tab, Shift-Tab, Esc and Ctrl-Enter.
*/
export class BaseEditorClass {
protected _bindEventService: BindingEventService;
/** is the Editor disabled? */
disabled = false;

/** SlickGrid Grid object */
protected grid: SlickGrid;

/** Grid options */
protected gridOptions: GridOption;

constructor(protected readonly args: EditorArguments) {
this.grid = args.grid;
this.gridOptions = (this.grid.getOptions() || {}) as GridOption;
this._bindEventService = new BindingEventService();
}

/** Get Column Definition object */
get columnDef(): Column {
return this.args.column;
}

/** Get Column Editor object */
get columnEditor(): ColumnEditor {
return this.columnDef?.editor || ({} as ColumnEditor);
}

/** Getter for the item data context object */
get dataContext(): any {
return this.args.item;
}

get hasAutoCommitEdit(): boolean {
return this.gridOptions.autoCommitEdit ?? false;
}

/** Get the Validator function, can be passed in Editor property or Column Definition */
get validator(): EditorValidator | undefined {
return this.columnEditor?.validator ?? this.columnDef?.validator;
}

// --
// protected functions
// ------------------

/** when it's a Composite Editor, we'll check if the Editor is editable (by checking onBeforeEditCell) and if not Editable we'll disable the Editor */
protected checkInputUsabilityState(): boolean {
const activeCell = this.grid.getActiveCell();
const isCellEditable = this.grid.onBeforeEditCell
.notify({
...activeCell,
item: this.dataContext,
column: this.args.column,
grid: this.grid,
target: 'composite',
compositeEditorOptions: this.args.compositeEditorOptions,
})
.getReturnValue();
return isCellEditable;
}

protected handleChangeOnCompositeEditor(
event: Event | null,
compositeEditorOptions: CompositeEditorOption,
triggeredBy: 'user' | 'system' = 'user',
isCalledByClearValue = false
): void {
const activeCell = this.grid.getActiveCell();
const column = this.args.column;
const columnId = this.columnDef?.id ?? '';
const item = this.dataContext;
const grid = this.grid;

const isExcludeDisabledFieldFormValues = this.gridOptions?.compositeEditorOptions?.excludeDisabledFieldFormValues ?? false;
if (
isCalledByClearValue ||
(this.disabled && isExcludeDisabledFieldFormValues && compositeEditorOptions.formValues.hasOwnProperty(columnId))
) {
delete compositeEditorOptions.formValues[columnId]; // when the input is disabled we won't include it in the form result object
}
grid.onCompositeEditorChange.notify(
{
...activeCell,
item,
grid,
column,
formValues: compositeEditorOptions.formValues,
editors: compositeEditorOptions.editors,
triggeredBy,
},
new SlickEventData(event)
);
}
}
Loading
Loading