Skip to content

Commit

Permalink
Merge pull request #2804 from infor-design/2726-dropdown-editor-befor…
Browse files Browse the repository at this point in the history
…ecelledit

2726 - IdsDataGrid dropdown editor async beforecelledit
  • Loading branch information
ericangeles committed Sep 9, 2024
2 parents 5111626 + 9191ef6 commit 8381360
Show file tree
Hide file tree
Showing 6 changed files with 252 additions and 9 deletions.
1 change: 1 addition & 0 deletions doc/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

- `[Card]` Adds `draggable` attribute to ids-card which allows card to be used in drag and drop scenarios. ([#2423](https://github.com/infor-design/enterprise-wc/issues/2423))
- `[Datagrid]` Fix Clear Row / Eraser button so that changes persist throughout pagination. ([#2615]https://github.com/infor-design/enterprise-wc/issues/2615)
- `[Datagrid]` Added async/await to beforecelledit. ([#2726]https://github.com/infor-design/enterprise-wc/issues/2726)
- `[NotificationBanner]` Added a notification service which can be used to manage notification banners on a page. ([#2160]https://github.com/infor-design/enterprise-wc/issues/2160)
- `[Datagrid]` Fix Clear Row / Eraser button so that changes persist throughout pagination. ([#2615](https://github.com/infor-design/enterprise-wc/issues/2615))
- `[LoadingIndicator]` Added a setting `contained` which confines the loading indicator within it's nearest parent. ([#2256](https://github.com/infor-design/enterprise-wc/issues/2256))
Expand Down
10 changes: 10 additions & 0 deletions src/components/ids-data-grid/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,16 @@ To cancel editing based on some condition or if editing is not allowed you can v
});
```

If the callback for the `beforecelledit` event requires async operations, the user can pass an `async function` or a `Promise<boolean>`.
```js
dataGrid.addEventListener('beforecelledit', (e: Event) => {
(<CustomEvent>e).detail.response(async () => {
const dbResponse: boolean = await fetchDbResponse;
return dbResponse;
});
});
```

There are a few utility functions for editing the data grid mentioned in the Methods section.

### Grouped Rows (Groupable)
Expand Down
28 changes: 28 additions & 0 deletions src/components/ids-data-grid/demos/beforecelledit-async.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title><%= htmlWebpackPlugin.options.title %></title>
<%= htmlWebpackPlugin.options.font %>
</head>
<body>
<ids-container role="main" padding="8" hidden>
<ids-theme-switcher mode="light"></ids-theme-switcher>
<ids-layout-grid auto-fit="true" padding="md">
<ids-text font-size="12" type="h1">Data Grid (Async Dropdown Options)</ids-text>
</ids-layout-grid>
<ids-layout-grid auto-fit="true" padding-x="md">
<ids-layout-grid-cell>
<ids-data-grid
id="data-grid-editable"
suppress-row-click-selection="true"
row-selection="multiple"
label="Books"
editable="true"
edit-next-on-enter-press="true"
add-new-at-end="true">
</ids-data-grid>
</ids-layout-grid-cell>
</ids-layout-grid>
</ids-container>
</body>
</html>
187 changes: 187 additions & 0 deletions src/components/ids-data-grid/demos/beforecelledit-async.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
import '../ids-data-grid';
import type IdsDataGrid from '../ids-data-grid';
import type { IdsDataGridColumn } from '../ids-data-grid-column';
import booksJSON from '../../../assets/data/books.json';

// Example for populating the DataGrid
const dataGrid = document.querySelector<IdsDataGrid>('#data-grid-editable')!;

(async function init() {
// Do an ajax request
const url: any = booksJSON;
const columns: IdsDataGridColumn[] = [];

// Set up columns
columns.push({
id: 'selectionCheckbox',
name: 'selection',
sortable: false,
resizable: false,
formatter: dataGrid.formatters.selectionCheckbox,
align: 'center'
});
columns.push({
id: 'description',
name: 'Description',
field: 'description',
sortable: true,
resizable: true,
reorderable: true,
formatter: dataGrid.formatters.text,
editor: {
type: 'input',
editorSettings: {
autoselect: true,
dirtyTracker: true,
validate: 'required',
}
},
readonly(row: number) {
return row % 2 === 0;
},
});
columns.push({
id: 'ledger',
name: 'Ledger',
field: 'ledger',
resizable: true,
reorderable: true,
formatter: dataGrid.formatters.text,
uppercase: true,
editor: {
type: 'input',
editorSettings: {
autoselect: true,
dirtyTracker: true,
maxlength: 2,
uppercase: true
}
},
});
columns.push({
id: 'bookCurrency',
name: 'Currency',
field: 'bookCurrency',
resizable: true,
reorderable: true,
uppercase: true,
formatter: dataGrid.formatters.dropdown,
editor: {
type: 'dropdown',
editorSettings: {
dirtyTracker: true,
validate: 'required'
}
}
});
columns.push({
id: 'transactionCurrency',
name: 'Transaction Currency',
field: 'transactionCurrency',
formatter: dataGrid.formatters.text
});
columns.push({
id: 'integer',
name: 'Price (Int)',
field: 'price',
formatter: dataGrid.formatters.integer,
formatOptions: { locale: 'en-US' }, // Data Values are in en-US
editor: {
type: 'input',
editorSettings: {
autoselect: true,
dirtyTracker: true,
mask: 'number',
maskOptions: {
allowDecimal: false,
integerLimit: 3
},
validate: 'required'
}
},
});
columns.push({
id: 'postHistory',
name: 'Post History',
field: 'postHistory',
formatter: dataGrid.formatters.checkbox,
align: 'center',
editor: {
type: 'checkbox',
editorSettings: {
dirtyTracker: true,
}
},
});

dataGrid.columns = columns;
dataGrid.idColumn = 'book';

const setData = async () => {
const res = await fetch(url);
const data = await res.json();
dataGrid.data = data;
};

await setData();

type Currency = {
id: string,
label: string,
value: string
};

// simulate the delay of the options coming from the server
const fetchCurrencies = new Promise<Array<Currency>>((resolve) => {
setTimeout(() => {
resolve([
{
id: 'usd',
label: 'USD',
value: 'usd'
},
{
id: 'eur',
label: 'EUR',
value: 'eur'
},
{
id: 'yen',
label: 'YEN',
value: 'yen'
},
{
id: 'cad',
label: 'CAD',
value: 'cad'
},
{
id: 'gbp',
label: 'GBP',
value: 'gbp'
},
{
id: 'ars',
label: 'ARS',
value: 'ars'
}
]);
}, 200);
});

// Event Handlers
dataGrid.addEventListener('beforecelledit', ((evt: CustomEvent) => {
// Can be vetoed (<CustomEvent>e).detail.response(false);
console.info(`Edit Started`, evt.detail);
const colId = evt.detail.column.id;
const editor = evt.detail.column.editor;

if (editor && colId === 'bookCurrency' && !editor.editorSettings.options?.length) {
evt.detail.response(async () => {
const currencies = await fetchCurrencies;
editor.editorSettings.options = currencies;
return true;
});
}
}) as EventListener);
}());
3 changes: 3 additions & 0 deletions src/components/ids-data-grid/demos/index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
- link: auto-fit.html
type: Example
description: Shows a data grid that sizes to the size of the parent container
- link: beforecelledit-async.html
type: Example
description: Shows usage of async beforecelledit event
- link: columns-auto.html
type: Example
description: Shows auto column widths
Expand Down
32 changes: 23 additions & 9 deletions src/components/ids-data-grid/ids-data-grid-cell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,24 +263,38 @@ export default class IdsDataGridCell extends IdsElement {
if (!columnEditor || !columnEditor.editor || this.isEditing) return;

// Init Editor
let canEdit = !(this.classList.contains('is-readonly') || this.classList.contains('is-disabled'));
let canEdit: any = !(this.classList.contains('is-readonly') || this.classList.contains('is-disabled'));
if (!canEdit) {
return;
}

const response = (veto: any) => {
canEdit = !!veto;
};

this.dataGrid.triggerEvent('beforecelledit', this.dataGrid, {
detail: {
elem: this, editor: this.editor, column, data: this.dataGrid.data[this.dataGrid.activeCell.row], response
elem: this,
editor: this.editor,
column,
data: this.dataGrid.data[this.dataGrid.activeCell.row],
response: (veto: boolean | Promise<void | boolean>) => {
canEdit = veto;
}
}
});

if (!canEdit) {
return;
if (canEdit instanceof Promise || canEdit?.constructor?.name === 'AsyncFunction') {
(canEdit instanceof Promise ? canEdit : canEdit())
.then((veto?: boolean) => { if (veto !== false) this.#startCellEdit(column, columnEditor, clickEvent); })
.catch(() => { /** ignore if promise rejected */ });
} else if (canEdit !== false) {
this.#startCellEdit(column, columnEditor, clickEvent);
}
}

#startCellEdit(
column: IdsDataGridColumn,
columnEditor: { type: string, editor?: IdsDataGridEditor },
clickEvent?: MouseEvent
) {
if (!columnEditor || !columnEditor.editor || this.isEditing) return;

this.originalValue = this.value;
this.editor = columnEditor.editor;
Expand All @@ -300,7 +314,7 @@ export default class IdsDataGridCell extends IdsElement {
this.classList.remove('is-invalid');
this.isInValid = true;
}
if (column.editor.inline) this.classList.add('is-inline');
if (column.editor?.inline) this.classList.add('is-inline');
this.isEditing = true;

// Pass column text alignment rules into the cell editor
Expand Down

0 comments on commit 8381360

Please sign in to comment.