diff --git a/data-grid/react-samples/react-poc-sample/index.html b/data-grid/react-samples/react-poc-sample/index.html
index bdf3c1b..dc2a95b 100644
--- a/data-grid/react-samples/react-poc-sample/index.html
+++ b/data-grid/react-samples/react-poc-sample/index.html
@@ -4,6 +4,7 @@
+
-
-
Name
+const createDecoratedHeader = (iconClass, label, accentColor = '#2563eb') => {
+ return () => (
+
+
+
+ {label}
+
+
);
+};
+
+const customerNameHeaderTemplate = createDecoratedHeader('e-icons e-people', 'Customer', '#7c3aed');
+const orderDateHeaderTemplate = createDecoratedHeader('e-icons e-timeline-today', 'Order Date', '#2563eb');
+const shippedDateHeaderTemplate = createDecoratedHeader('e-icons e-timeline-today', 'Ship Date', '#0ea5e9');
+
+function createDateFilterTemplate(filterDate) {
+ let dateElement;
+
+ return {
+ create: () => {
+ dateElement = document.createElement('input');
+ return dateElement;
+ },
+ write: (args) => {
+ const datePicker = new DatePicker({
+ value: args.value,
+ change: (changeArgs) => filterDate(args.column.field, changeArgs.value),
+ });
+ datePicker.appendTo(dateElement);
+ },
+ };
}
-function orderDateHeaderTemplate() {
- return (
-
-
- Order Date
-
- );
+function createDropdownFilterTemplate(filterValue, options) {
+ let dropdownElement;
+
+ return {
+ create: () => {
+ dropdownElement = document.createElement('input');
+ return dropdownElement;
+ },
+ write: (args) => {
+ const dropdown = new DropDownList({
+ dataSource: ['All', ...options],
+ value: args.value || 'All',
+ change: (changeArgs) => {
+ filterValue(args.column.field, changeArgs.value);
+ },
+ });
+ dropdown.appendTo(dropdownElement);
+ },
+ };
}
-function shippedDateHeaderTemplate() {
- return (
-
-
- Shipped Date
-
- );
+function parseExcelSheet(sheet) {
+ const rows = XLSX.utils.sheet_to_json(sheet, { header: 1, defval: null });
+ const headerRowIndex = rows.findIndex((row) => row.includes('OrderID'));
+ if (headerRowIndex < 0) return [];
+
+ const fieldMap = {
+ OrderID: 'OrderID',
+ 'Order Status': 'OrderStatus',
+ OrderDate: 'OrderDate',
+ Name: 'CustomerName',
+ Phone: 'Phone',
+ 'Ship Details': 'ShipDetails',
+ 'Ship Country': 'ShipCountry',
+ 'Ship Date': 'ShipDate',
+ 'Ship Fee': 'ShipFee',
+ };
+ const headers = rows[headerRowIndex].map((header) => fieldMap[header] || header);
+
+ return rows.slice(headerRowIndex + 1).filter((row) => row.some(Boolean)).map((row) => {
+ return headers.reduce((record, field, index) => {
+ if (field) record[field] = row[index];
+ return record;
+ }, {});
+ });
}
export default function Home() {
const gridRef = useRef(null);
+ const selectGridRef = useRef(null);
+ const [isBulkUpdateOpen, setIsBulkUpdateOpen] = useState(false);
+ const [bulkUpdateField, setBulkUpdateField] = useState('');
+ const [bulkUpdateValue, setBulkUpdateValue] = useState('');
+ const [isExcelDialogOpen, setIsExcelDialogOpen] = useState(false);
+ const [excelFile, setExcelFile] = useState(null);
+ const [isSelectedRecordsDialogOpen, setIsSelectedRecordsDialogOpen] = useState(false);
+ const [totalRecordCount, setTotalRecordCount] = useState(gridData.length);
+ const [selectedRecords, setSelectedRecords] = useState([]);
+ const [isBatchEditMode, setIsBatchEditMode] = useState(false);
+
+ const bulkUpdateFields = [
+ { text: 'Order Status', value: 'OrderStatus' },
+ { text: 'Customer Name', value: 'CustomerName' },
+ { text: 'Phone', value: 'Phone' },
+ { text: 'Ship Country', value: 'ShipCountry' },
+ { text: 'Product Name', value: 'ProductName' },
+ { text: 'Priority', value: 'Priority' },
+ { text: 'Payment Method', value: 'PaymentMethod' },
+ { text: 'Payment Status', value: 'PaymentStatus' },
+ ];
// Settings state
@@ -73,7 +203,24 @@ export default function Home() {
normal: 47,
};
- const toolbar = [
+ const isDevice = Browser.isDevice;
+ const handleEditModeChange = (args) => {
+ const mode = args.checked ? 'Batch' : 'Normal';
+ setIsBatchEditMode(args.checked);
+ if (gridRef.current) {
+ gridRef.current.editSettings.mode = mode;
+ }
+ };
+
+ const editModeToolbarTemplate = () => (
+
+ Batch Edit
+
+
+ );
+
+ const toolbar = isDevice ? ['Add', 'Edit', 'Delete', 'Update', 'Cancel', 'ExcelExport',{ tooltipText: 'Bind from Excel', id: 'bindFromExcel', prefixIcon: 'e-icons e-export-xls' },
+ { tooltipText: 'View Selected Records', id: 'viewSelectedRecords', prefixIcon: 'e-icons e-eye' }, 'PdfExport'] : [
'Add',
'Edit',
'Delete',
@@ -83,9 +230,17 @@ export default function Home() {
'ExcelExport',
'PdfExport',
{ type: 'Separator' },
- { text: 'Clear Filter', tooltipText: 'Clear all filters', id: 'quickfilter', prefixIcon: 'e-icons e-filter-clear' },
+ { tooltipText: 'Bind from Excel', id: 'bindFromExcel', prefixIcon: 'e-icons e-export-xls' },
+ { tooltipText: 'View Selected Records', id: 'viewSelectedRecords', prefixIcon: 'e-icons e-eye' },
+ { type: 'Separator' },
+ { tooltipText: 'Clear all filters', id: 'quickfilter', prefixIcon: 'e-icons e-filter-clear' },
{ text: 'Reset Defaults', tooltipText: 'Clear filters / sort / group / selection', id: 'reset', prefixIcon: 'e-icons e-refresh' },
+
+ { type: 'Separator' },
+ { id: 'editMode', template: editModeToolbarTemplate },
+
{ type: 'Separator' },
+
{
prefixIcon: 'e-icons e-small-icon',
id: 'big',
@@ -105,16 +260,52 @@ export default function Home() {
tooltipText: 'Row-height-small',
},
+
];
- const filterSettings = { type: 'Excel' };
- const selectionSettings = { type: 'Multiple', mode: selectionMode, persistSelection: true };
+ const filterSettings = { type: 'FilterBar', showFilterBarOperator: true, };
+ const selectionSettings = { type: 'Multiple', mode: 'Row', persistSelection: true };
const sortSettings = { columns: [] };
- const editSettings = { allowEditing: true, allowAdding: true, allowDeleting: true };
+ const editSettings = {
+ allowEditing: true,
+ allowAdding: true,
+ allowDeleting: true,
+ ...(isDevice ? { mode: 'Dialog' } : {}),
+ };
const pageSettings = { pageSize: 50 };
- const groupSettings = { showDropArea: true, showGroupedColumn: true };
+ const groupSettings = { showDropArea: false,showToggleButton:true, showGroupedColumn: true };
+
+
+ const filterDate = (field, value) => {
+ const grid = gridRef.current;
+ if (!grid) return;
+
+ if (value) {
+ grid.filterByColumn(field, 'equal', value);
+ } else {
+ grid.removeFilteredColsByField(field);
+ }
+ };
+
+ const filterValue = (field, value) => {
+ const grid = gridRef.current;
+ if (!grid) return;
+
+ if (value && value !== 'All') {
+ grid.filterByColumn(field, 'equal', value);
+ } else {
+ grid.removeFilteredColsByField(field);
+ }
+ };
+
+ const orderDateFilterTemplate = createDateFilterTemplate(filterDate);
+ const shipDateFilterTemplate = createDateFilterTemplate(filterDate);
+ const shipCountryFilterTemplate = createDropdownFilterTemplate(filterValue, ['USA', 'Canada', 'Mexico', 'UK']);
+ const orderStatusFilterTemplate = createDropdownFilterTemplate(filterValue, ['Ready To Ship', 'In Transit', 'Delivered']);
+ const priorityFilterTemplate = createDropdownFilterTemplate(filterValue, ['Low', 'Medium', 'High', 'Critical']);
+ const paymentStatusFilterTemplate = createDropdownFilterTemplate(filterValue, ['Paid', 'Pending', 'Refunded']);
const toolbarClick = (args) => {
const grid = gridRef.current;
@@ -152,6 +343,13 @@ export default function Home() {
grid.pageSettings.currentPage = 1;
grid.refresh();
break;
+ case 'bindFromExcel':
+ setExcelFile(null);
+ setIsExcelDialogOpen(true);
+ break;
+ case 'viewSelectedRecords':
+ setIsSelectedRecordsDialogOpen(true);
+ break;
default:
if (args.item.id === grid.element.id + '_excelexport') grid.excelExport();
@@ -159,271 +357,588 @@ export default function Home() {
break;
}
};
+ const gridCreated = (args) => {
+ if (Browser.isDevice) {
+ gridRef.current.hideColumns(['Total Amount', 'Tax Amount', 'Discount Amount', 'Product Name', 'Gross Amount', 'Name', 'Phone', 'Ship Fee', 'Ship Date', 'Ship Country', 'Ship Details'])
+ }
+ }
+ const contextMenuClick = (args) => {
+ if (args.item.id === 'bulkUpdate') {
+ setBulkUpdateField('');
+ setBulkUpdateValue('');
+ setIsBulkUpdateOpen(true);
+ }
+ };
+
+ const bulkCellUpdate = (
+ field,
+ value,
+ rowData
+ ) => {
+ // Require a primary key; without one, persistence and cell refresh are not possible.
+ const pkName = gridRef.current.getPrimaryKeyFieldNames()[0];
+ if (isNullOrUndefined(pkName)) {
+ return;
+ }
+
+ // Validate the field against grid columns.
+ if (isNullOrUndefined(gridRef.current.getColumnByField(field))) {
+ return;
+ }
+
+ // Determine the target records: use the passed rowData, otherwise selected records.
+ const records = (rowData && rowData.length)
+ ? rowData
+ : gridRef.current.getSelectedRecords();
+
+ const isValueArray = Array.isArray(value);
+
+ // Single value -> update every record; array -> up to the array length only.
+ const updateCount = isValueArray
+ ? Math.min(value.length, records.length)
+ : records.length;
+
+ // Nothing to do when there are no records or no values (empty array).
+ if (!updateCount) {
+ return;
+ }
+
+ // Build the change-set to be persisted through the data module.
+ const changes = {
+ addedRecords: [],
+ deletedRecords: [],
+ changedRecords: []
+ };
+
+ const original = {
+ addedRecords: [],
+ deletedRecords: [],
+ changedRecords: []
+ };
+
+ const valueArray = isValueArray ? value : null;
+ const singleValue = isValueArray ? null : value;
+
+ // Update only the resolved count of records.
+ for (let i = 0; i < updateCount; i++) {
+ const record = records[i];
+
+ const cellValue = isValueArray
+ ? valueArray[i]
+ : singleValue;
+
+ // Capture the original record (before modification) for persistence.
+ original.changedRecords.push(
+ extend({}, {}, record, true)
+ );
+
+ // Update the underlying record object directly.
+ setValue(field, cellValue, record);
+
+ // Track the modified record for persistence.
+ changes.changedRecords.push(
+ extend({}, {}, record, true)
+ );
+
+ // Refresh the rendered cell for the updated row.
+ gridRef.current.setCellValue(
+ getValue(pkName, record),
+ field,
+ cellValue
+ );
+ }
+
+ // Persist the batch of changes through the data module.
+ gridRef.current.getDataModule().saveChanges(changes, pkName, original);
+}
+ const handleBulkUpdateOk = () => {
+ const grid = gridRef.current;
+ if (!grid || !bulkUpdateField) return;
+ console.log(bulkUpdateField, bulkUpdateValue)
+ let selectedRecords = grid.getSelectedRecords();
+ bulkCellUpdate(bulkUpdateField, bulkUpdateValue, selectedRecords);
+ // grid.refresh();
+ setIsBulkUpdateOpen(false);
+ };
+
+ const handleBulkUpdateCancel = () => {
+ setIsBulkUpdateOpen(false);
+ };
+
+
+ const handleExcelBind = () => {
+ const grid = gridRef.current;
+ if (!grid || !excelFile) return;
+
+ const reader = new FileReader();
+ reader.onload = (event) => {
+ const workbook = XLSX.read(event.target.result, { type: 'array', cellDates: true });
+ const firstSheet = workbook.Sheets[workbook.SheetNames[0]];
+ const importedData = parseExcelSheet(firstSheet);
+
+ grid.setProperties({ dataSource: importedData }, true);
+ grid.freezeRefresh()
+ setExcelFile(null);
+ setIsExcelDialogOpen(false);
+ };
+ reader.readAsArrayBuffer(excelFile);
+ };
+
+ const handleExcelDialogCancel = () => {
+ setExcelFile(null);
+ setIsExcelDialogOpen(false);
+ };
+
+ const handleSelectedRecordsDialogClose = () => {
+ setIsSelectedRecordsDialogOpen(false);
+ };
+
+ const handleSelectedRecordsDialogOpen = () => {
+ selectGridRef.current.setProperties({ dataSource: gridRef.current.getSelectedRecords() }, true);
+ selectGridRef.current.freezeRefresh();
+ };
+
+ const updateTotalRecordCount = () => {
+
+ const dataSource = gridRef.current?.dataSource;
+ const records = Array.isArray(dataSource)
+ ? dataSource
+ : dataSource?.json || dataSource?.result || [];
+ setTotalRecordCount(Array.isArray(records) ? records.length : 0);
+ };
+
+ const path = {
+ saveUrl: 'https://services.syncfusion.com/react/production/api/FileUploader/Save',
+ removeUrl: 'https://services.syncfusion.com/react/production/api/FileUploader/Remove'
+ };
+ const dropElement = document.getElementsByClassName('control-fluid')[0];
+ const parseExcel = (file) => {
+ var reader = new FileReader();
+ reader.onload = (e) => {
+ var workbook = XLSX.read(e.target.result, { type: 'array', cellDates: true });
+ workbook.SheetNames.forEach((sheetName) => {
+ var importedData = parseExcelSheet(workbook.Sheets[sheetName]);
+ gridRef.current.changeDataSource(importedData, gridRef.current.getColumns());
+ });
+ };
+ reader.readAsArrayBuffer(file.rawFile);
+ };
+ const onSuccess = (args) => {
+ var files = args.file;
+ if (files) {
+ setExcelFile(files[0].rawFile);
+ }
+
+ }
+ const onRemove = (args) => {
+ console.log(args)
+ setExcelFile(null);
+ // gridRef.current.dataSource = [];
+ gridRef.current.changeDataSource(gridData, gridRef.current.getColumns());
+ }
+
return (
-
-
{
- if (data && data.Priority === 'Critical' && data.PaymentStatus === 'Paid') {
- return true
- }
+
+
+
+ setBulkUpdateField(args.value || '')}
+ floatLabelType="Always"
+ />
+ setBulkUpdateValue(args.value || '')}
+ floatLabelType="Always"
+ />
+
+
+
{
+ return (
+ )
+ }
+ }
+ showCloseIcon
+ isModal
+ close={handleExcelDialogCancel}
+ buttons={[
+ {
+ buttonModel: { content: 'Cancel' },
+ click: handleExcelDialogCancel,
+ },
+ {
+ buttonModel: { content: 'OK', isPrimary: true, disabled: !excelFile },
+ click: handleExcelBind,
+ },
+ ]}
+ >
+
+
+
+
+
{
+
+ return
+
+
+
+
+
+
+
+
+
+
+
+
+ }}
+ close={handleSelectedRecordsDialogClose}
+ buttons={[{
+ buttonModel: { content: 'Close' },
+ click: handleSelectedRecordsDialogClose,
+ }]}
+ >
+
+
+
+
+ Total records: {totalRecordCount}
+
+
+
+ {
+ if(data && !isDevice && data.Priority === 'Critical' && data.PaymentStatus === 'Paid')
+ {
+ return true;
}
+ return false;
+ }
+ }
+ dataSource={gridData}
+ dataBound={()=>
+ {
+ console.log('dataBound event triggered');
+ updateTotalRecordCount()
}
- height="250"
- width="100%"
- rowHeight={rowHeightMap.normal}
- allowSorting
- allowMultiSorting
- allowFiltering
- filterSettings={filterSettings}
- allowGrouping
- groupSettings={groupSettings}
- allowReordering
- allowResizing
- showColumnMenu
-
- allowSelection
- selectionSettings={selectionSettings}
- editSettings={editSettings}
- allowRowDragAndDrop={true}
- rowDropSettings={{ targetID: "second-grid" }}
-
- toolbar={toolbar}
- toolbarClick={toolbarClick}
- sortSettings={sortSettings}
- pageSettings={pageSettings}
- enableInfiniteScrolling={true}
- allowExcelExport
- allowPdfExport
- contextMenuItems={[
- 'AutoFit', 'SortAscending', 'SortDescending',
- 'Copy', 'Edit', 'Delete', 'Save', 'Cancel',
- 'Group', 'Ungroup',
- ]}
- >
-
- {/* --------- Stacked header: Order Info --------- */}
-
-
-
-
- {/* --------- Stacked header: Customer Info --------- */}
-
+ {
+ updateTotalRecordCount()
+ }
+ }
+ columnMenuItems={['AutoFit', 'Group', 'Ungroup', 'SortAscending', 'SortDescending']}
+
+ height={isDevice ? "400" : "200"}
+ width="100%"
+ rowHeight={isDevice ? undefined : rowHeightMap.normal}
+ allowSorting
+ allowMultiSorting
+ allowFiltering
+ filterSettings={filterSettings}
+ enableAdaptiveUI={isDevice}
+ rowRenderingMode={isDevice ? 'Vertical' : 'Horizontal'}
+ adaptiveUIMode={isDevice ? 'Mobile' : 'Both'}
+ allowGrouping={!isDevice}
+ groupSettings={groupSettings}
+ allowReordering={!isDevice}
+ allowResizing={!isDevice}
+ showColumnMenu={!isDevice}
+
+ allowSelection
+ selectionSettings={selectionSettings}
+ editSettings={editSettings}
+
+ toolbar={toolbar}
+ toolbarClick={toolbarClick}
+ sortSettings={sortSettings}
+ pageSettings={pageSettings}
+ enableInfiniteScrolling={true}
+ allowExcelExport
+ allowPdfExport
+ contextMenuItems={isDevice ? [] : [
+ 'AutoFit', 'SortAscending', 'SortDescending',
+ 'Copy', 'Edit', 'Delete', 'Save', 'Cancel',
+ 'Group', 'Ungroup', 'PinRow', 'UnpinRow', { id: 'bulkUpdate', text: 'Bulk Update' }
+ ]}
+ contextMenuClick={contextMenuClick}
+ >
+
+ {/* --------- Stacked header: Order Info --------- */}
+
+
-
- {/* --------- Stacked header: Shipping --------- */}
-
-
- {/* Product Name */}
-
-
- {/* Gross Amount */}
-
-
- {/* Discount Amount */}
-
-
- {/* Tax Amount */}
-
-
- {/* Total Amount */}
-
-
- {/* Priority */}
-
-
- {/* Payment Method */}
-
-
- {/* Payment Status */}
-
-
-
-
+
+
+ {/* --------- Stacked header: Customer Info --------- */}
+
+
+ {/* --------- Stacked header: Shipping --------- */}
+
+
+ {/* Product Name */}
+
+
+ {/* Gross Amount */}
+
+
+ {/* Discount Amount */}
+
+
+ {/* Tax Amount */}
+
-
-
+ {/* Total Amount */}
+
+ {/* Priority */}
+
+
+ {/* Payment Method */}
+
+
+ {/* Payment Status */}
+
+
+
+
+
+
+
);
}