Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add column reorderable option to optionally lock a column #1357

Merged
merged 2 commits into from
Jan 20, 2024
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
12 changes: 12 additions & 0 deletions packages/common/src/core/__tests__/slickGrid.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,16 @@ describe('SlickGrid core file', () => {
expect(renderSpy).toHaveBeenCalled();
});

it('should be able to disable column reorderable', () => {
const columns = [{ id: 'firstName', field: 'firstName', name: 'First Name', reorderable: false }] as Column[];
const data = [{ id: 0, firstName: 'John' }, { id: 1, firstName: 'Jane' }];

grid = new SlickGrid<any, Column>(container, data, columns, defaultOptions);
const headerElms = container.querySelectorAll('.slick-header-column');

expect(headerElms[0].classList.contains('unorderable')).toBeTruthy();
});

it('should be able to edit when editable grid option is enabled and invalidate some rows', () => {
const columns = [{ id: 'firstName', field: 'firstName', name: 'First Name', editor: InputEditor }] as Column[];
const data = [{ id: 0, firstName: 'John' }, { id: 1, firstName: 'Jane' }];
Expand Down Expand Up @@ -1920,12 +1930,14 @@ describe('SlickGrid core file', () => {
const dragEvent = new CustomEvent('DragEvent');
jest.spyOn(viewportTopLeft, 'getBoundingClientRect').mockReturnValue({ left: 25, top: 10, right: 0, bottom: 0 } as DOMRect);
Object.defineProperty(dragEvent, 'originalEvent', { writable: true, value: { pageX: 20 } });
Object.defineProperty(dragEvent, 'related', { writable: true, value: headerColumnElms[0] });
Object.defineProperty(dragEvent, 'item', { writable: true, value: headerColumnElms[0] });
Object.defineProperty(headerColumnElms[0], 'clientLeft', { writable: true, value: 25 });
Object.defineProperty(viewportTopLeft, 'clientLeft', { writable: true, value: 25 });

expect(sortInstance).toBeTruthy();
sortInstance.options.onStart(dragEvent);
sortInstance.options.onMove(dragEvent);
expect(viewportTopLeft.scrollLeft).toBe(0);

jest.advanceTimersByTime(100);
Expand Down
22 changes: 16 additions & 6 deletions packages/common/src/core/slickGrid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ export class SlickGrid<TData = any, C extends Column<TData> = Column<TData>, O e
suppressActiveCellChangeOnEdit: false,
enableCellNavigation: true,
enableColumnReorder: true,
unorderableColumnCssClass: 'unorderable',
asyncEditorLoading: false,
asyncEditorLoadDelay: 100,
forceFitColumns: false,
Expand Down Expand Up @@ -268,16 +269,17 @@ export class SlickGrid<TData = any, C extends Column<TData> = Column<TData>, O e

protected _columnDefaults = {
name: '',
resizable: true,
sortable: false,
minWidth: 30,
maxWidth: undefined,
rerenderOnResize: false,
headerCssClass: null,
defaultSortAsc: true,
focusable: true,
hidden: false,
minWidth: 30,
maxWidth: undefined,
rerenderOnResize: false,
reorderable: true,
resizable: true,
sortable: false,
selectable: true,
hidden: false
} as Partial<C>;

protected _columnResizeTimer?: NodeJS.Timeout;
Expand Down Expand Up @@ -1589,6 +1591,9 @@ export class SlickGrid<TData = any, C extends Column<TData> = Column<TData>, O e
if (m.toolTip) {
header.title = m.toolTip;
}
if (!m.reorderable) {
header.classList.add(this._options.unorderableColumnCssClass!);
}
const colNameElm = createDomElement('span', { className: 'slick-column-name' }, header);
this.applyHtmlCode(colNameElm, m.name as string);

Expand Down Expand Up @@ -1790,6 +1795,11 @@ export class SlickGrid<TData = any, C extends Column<TData> = Column<TData>, O e
dragoverBubble: false,
revertClone: true,
scroll: !this.hasFrozenColumns(), // enable auto-scroll
// lock unorderable columns by using a combo of filter + onMove
filter: `.${this._options.unorderableColumnCssClass}`,
onMove: (event) => {
return !event.related.classList.contains(this._options.unorderableColumnCssClass as string);
},
onStart: (e: SortableEvent) => {
canDragScroll = !this.hasFrozenColumns() ||
getOffset(e.item)!.left > getOffset(this._viewportScrollContainerX)!.left;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ describe('SlickCheckboxSelectColumn Plugin', () => {
field: '_checkbox_selector',
hideSelectAllCheckbox: false,
name: '',
reorderable: false,
toolTip: 'Select/Deselect All',
width: 30,
hideInColumnTitleRow: false,
Expand All @@ -139,6 +140,7 @@ describe('SlickCheckboxSelectColumn Plugin', () => {
field: '_checkbox_selector',
hideSelectAllCheckbox: true,
name: '',
reorderable: false,
toolTip: 'Select/Deselect All',
width: 30,
hideInColumnTitleRow: true,
Expand Down Expand Up @@ -394,6 +396,7 @@ describe('SlickCheckboxSelectColumn Plugin', () => {
excludeFromColumnPicker: true,
excludeFromGridMenu: true,
excludeFromQuery: true,
reorderable: false,
excludeFromHeaderMenu: true,
hideSelectAllCheckbox: false,
resizable: false,
Expand Down Expand Up @@ -431,6 +434,7 @@ describe('SlickCheckboxSelectColumn Plugin', () => {
excludeFromGridMenu: true,
excludeFromHeaderMenu: true,
excludeFromQuery: true,
reorderable: false,
field: 'chk-id',
hideSelectAllCheckbox: false,
id: 'chk-id',
Expand Down Expand Up @@ -465,6 +469,7 @@ describe('SlickCheckboxSelectColumn Plugin', () => {
excludeFromGridMenu: true,
excludeFromHeaderMenu: true,
excludeFromQuery: true,
reorderable: false,
field: '_checkbox_selector',
formatter: expect.toBeFunction(),
hideSelectAllCheckbox: false,
Expand All @@ -490,6 +495,7 @@ describe('SlickCheckboxSelectColumn Plugin', () => {
excludeFromGridMenu: true,
excludeFromHeaderMenu: true,
excludeFromQuery: true,
reorderable: false,
field: '_checkbox_selector',
formatter: expect.toBeFunction(),
hideSelectAllCheckbox: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ describe('SlickRowMoveManager Plugin', () => {
cssClass: 'slick-row-move-column',
disableRowSelection: false,
hideRowMoveShadow: true,
reorderable: false,
rowMoveShadowMarginLeft: 0,
rowMoveShadowMarginTop: 0,
rowMoveShadowOpacity: 0.9,
Expand All @@ -149,6 +150,7 @@ describe('SlickRowMoveManager Plugin', () => {
id: 'move-id',
name: '',
behavior: 'selectAndMove',
reorderable: false,
resizable: false,
selectable: false,
width: 40,
Expand All @@ -172,6 +174,7 @@ describe('SlickRowMoveManager Plugin', () => {
cssClass: 'some-class',
disableRowSelection: false,
hideRowMoveShadow: false,
reorderable: false,
rowMoveShadowMarginLeft: 2,
rowMoveShadowMarginTop: 5,
rowMoveShadowOpacity: 1,
Expand All @@ -196,6 +199,7 @@ describe('SlickRowMoveManager Plugin', () => {
formatter: expect.toBeFunction(),
id: 'move-id',
name: '',
reorderable: false,
resizable: false,
selectable: false,
width: 40,
Expand Down
2 changes: 2 additions & 0 deletions packages/common/src/extensions/slickCheckboxSelectColumn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export class SlickCheckboxSelectColumn<T = any> {
name: '',
toolTip: 'Select/Deselect All',
width: 30,
reorderable: false,
applySelectOnAllPages: true, // when that is enabled the "Select All" will be applied to all pages (when using Pagination)
hideInColumnTitleRow: false,
hideInFilterHeaderRow: true
Expand Down Expand Up @@ -239,6 +240,7 @@ export class SlickCheckboxSelectColumn<T = any> {
excludeFromHeaderMenu: true,
hideSelectAllCheckbox: this._addonOptions.hideSelectAllCheckbox,
resizable: false,
reorderable: this._addonOptions.reorderable,
sortable: false,
width: this._addonOptions.width || 30,
formatter: this.checkboxSelectionFormatter.bind(this),
Expand Down
2 changes: 2 additions & 0 deletions packages/common/src/extensions/slickRowBasedEdit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export class SlickRowBasedEdit {
allowMultipleRows: false,
columnId: '_slick_rowbasededit_action',
columnIndexPosition: -1,
reorderable: false,
} as RowBasedEditOptions;
protected _editedRows: Map<string, EditedRowDetails> = new Map();

Expand Down Expand Up @@ -185,6 +186,7 @@ export class SlickRowBasedEdit {
width: 75,
maxWidth: 75,
excludeFromExport: true,
reorderable: this._addonOptions?.reorderable,
formatter: this.actionColumnFormatter.bind(this),
onCellClick: this.onCellClickHandler.bind(this),
...(this._addonOptions?.actionColumnConfig ?? {}),
Expand Down
2 changes: 2 additions & 0 deletions packages/common/src/extensions/slickRowMoveManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export class SlickRowMoveManager {
cancelEditOnDrag: false,
disableRowSelection: false,
hideRowMoveShadow: true,
reorderable: false,
rowMoveShadowMarginTop: 0,
rowMoveShadowMarginLeft: 0,
rowMoveShadowOpacity: 0.9,
Expand Down Expand Up @@ -136,6 +137,7 @@ export class SlickRowMoveManager {
excludeFromQuery: true,
excludeFromHeaderMenu: true,
field: columnId,
reorderable: this._addonOptions.reorderable,
resizable: false,
selectable: false,
width: this._addonOptions.width || 40,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ export interface CheckboxSelectorOption {
*/
name?: string;

/** Defaults to false, makes the column reorderable to another position in the grid. */
reorderable?: boolean;

/** Defaults to "Select/Deselect All", provide a tooltip that will be shown over the "Select All" checkbox */
toolTip?: string;

Expand Down
6 changes: 6 additions & 0 deletions packages/common/src/interfaces/column.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,12 @@ export interface Column<T = any> {
*/
queryFieldSorter?: string;

/**
* Defaults to true, makes the column reorderable to another position in the grid.
* NOTE: Works best when used as first or last columns of the grid (e.g.: row selection checkbox as first column).
*/
reorderable?: boolean;

/** Is the column resizable, can we make it wider/thinner? A resize cursor icon will show on the right side of the column when enabled. */
resizable?: boolean;

Expand Down
3 changes: 3 additions & 0 deletions packages/common/src/interfaces/gridOption.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,9 @@ export interface GridOption<C extends Column = Column> {
*/
enableColumnReorder?: boolean | ColumnReorderFunction;

/** Defaults to "unorderable", a CSS class name that will be added to the column classes when the column cannot be reordered. */
unorderableColumnCssClass?: string;

/**
* Defaults to true, when doing a double-click in the column resize section (top right of a column when the mouse resize icon shows up),
* do we want to automatically resize the column by its cell content?
Expand Down
23 changes: 13 additions & 10 deletions packages/common/src/interfaces/rowBasedEditOption.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,6 @@ export interface RowBasedEditOptions {
/** whether multiple rows can be toggled into edit mode at the same itme (default: false) */
allowMultipleRows?: boolean;

/** Defaults to "_slick_rowbasededit_action", Row Detail column Id */
columnId?: string;

/**
* Defaults to -1, the column index position in the grid by default it will show as the last column.
* Also note that the index position might vary if you use other extensions, after each extension is created,
* it will add an offset to take into consideration (1.CheckboxSelector, 2.RowDetail, 3.RowMove)
*/
columnIndexPosition?: number;

/**
* additional column configurations for the action column. You can override the defaults by passing your own Column definition.
*/
Expand Down Expand Up @@ -61,6 +51,19 @@ export interface RowBasedEditOptions {
updateButtonPrompt?: string;
};

/** Defaults to "_slick_rowbasededit_action", Row Detail column Id */
columnId?: string;

/**
* Defaults to -1, the column index position in the grid by default it will show as the last column.
* Also note that the index position might vary if you use other extensions, after each extension is created,
* it will add an offset to take into consideration (1.CheckboxSelector, 2.RowDetail, 3.RowMove)
*/
columnIndexPosition?: number;

/** Defaults to false, makes the column reorderable to another position in the grid. */
reorderable?: boolean;

// --
// Available Callbacks

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,18 @@ export interface RowDetailViewOption {
*/
parent?: any;

/** Defaults to false, when True will open the row detail on a row click (from any column) */
useRowClick?: boolean;
/** Defaults to false, makes the column reorderable to another position in the grid. */
reorderable?: boolean;

/** Defaults to true, which will save the row detail view in a cache when it detects that it will become out of the viewport buffer */
saveDetailViewOnScroll?: boolean;

/** Defaults to false, which will limit expanded row to only 1 at a time (it will close all other rows before opening new one). */
singleRowExpand?: boolean;

/** Defaults to false, when True will open the row detail on a row click (from any column) */
useRowClick?: boolean;

/**
* Defaults to false, which will use a simpler way of calculating when rows become out (or back) of viewport range.
* It is recommended to enable this flag since it seems to work correctly with Slickgrid-Universal while the inverse is misbehaving
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ export interface RowMoveManagerOption {
/** Defaults to True, do we want to hide the row move shadow of what we're dragging? */
hideRowMoveShadow?: boolean;

/** Defaults to false, makes the column reorderable to another position in the grid. */
reorderable?: boolean;

/** Defaults to 0, optional left margin of the row move shadown element when enabled */
rowMoveShadowMarginLeft?: number | string;

Expand Down
1 change: 1 addition & 0 deletions packages/common/src/styles/_variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ $slick-container-border-left: 0 none !default;
$slick-grid-border-color: fade(black, 3%) !default;
$slick-grid-border-style: solid !default;
$slick-grid-header-background: rgba(255, 255, 255, .6) !default;
$slick-grid-header-unorderable-bg-color: darken($slick-grid-header-background, 4%) !default;
$slick-grid-cell-color: rgb(255, 255, 255) !default;
$slick-gray-dark: #333 !default;
$slick-link-color: #08c !default;
Expand Down
3 changes: 3 additions & 0 deletions packages/common/src/styles/slick-bootstrap.scss
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,9 @@
top: var(--slick-header-resizable-hover-top, $slick-header-resizable-hover-top);
opacity: var(--slick-header-resizable-hover-opacity, $slick-header-resizable-hover-opacity);
}
&.unorderable {
background-color: var(--slick-grid-header-unorderable-bg-color, $slick-grid-header-unorderable-bg-color);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ describe('SlickRowDetailView plugin', () => {
keyPrefix: '::',
loadOnce: true,
collapseAllOnSort: true,
reorderable: false,
saveDetailViewOnScroll: true,
singleRowExpand: true,
useSimpleViewportCalc: true,
Expand Down Expand Up @@ -203,7 +204,7 @@ describe('SlickRowDetailView plugin', () => {
id: '_detail_', field: '_detail_', name: '', alwaysRenderColumn: true, cssClass: 'some-class',
excludeFromExport: true, excludeFromColumnPicker: true, excludeFromGridMenu: true, excludeFromQuery: true, excludeFromHeaderMenu: true,
formatter: expect.anything(),
resizable: false, sortable: false, toolTip: 'title', width: 30,
reorderable: false, resizable: false, sortable: false, toolTip: 'title', width: 30,
};

const output = plugin.create(mockColumns, { rowDetailView: { process: processMock, expandableOverride: overrideMock, panelRows: 4, columnId: '_detail_', cssClass: 'some-class', toolTip: 'title' } });
Expand All @@ -223,7 +224,7 @@ describe('SlickRowDetailView plugin', () => {
id: '_detail_', field: '_detail_', name: '', alwaysRenderColumn: true, cssClass: 'some-class',
excludeFromExport: true, excludeFromColumnPicker: true, excludeFromGridMenu: true, excludeFromQuery: true, excludeFromHeaderMenu: true,
formatter: expect.anything(),
resizable: false, sortable: false, toolTip: 'title', width: 30,
reorderable: false, resizable: false, sortable: false, toolTip: 'title', width: 30,
});
expect(plugin.getExpandableOverride()).toBeFalsy();
expect(output instanceof SlickRowDetailView).toBeTruthy();
Expand Down
2 changes: 2 additions & 0 deletions packages/row-detail-view-plugin/src/slickRowDetailView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ export class SlickRowDetailView implements ExternalResource, UniversalRowDetailV
keyPrefix: '_',
loadOnce: false,
maxRows: undefined,
reorderable: false,
saveDetailViewOnScroll: true,
singleRowExpand: false,
useSimpleViewportCalc: false,
Expand Down Expand Up @@ -388,6 +389,7 @@ export class SlickRowDetailView implements ExternalResource, UniversalRowDetailV
excludeFromQuery: true,
excludeFromHeaderMenu: true,
formatter: this.detailSelectionFormatter.bind(this),
reorderable: this._addonOptions.reorderable,
resizable: false,
sortable: false,
toolTip: this._addonOptions.toolTip,
Expand Down