diff --git a/src/components/reactGrid/CustomReactGrid.jsx b/src/components/reactGrid/CustomReactGrid.jsx index 8b86aa9..6cffeee 100644 --- a/src/components/reactGrid/CustomReactGrid.jsx +++ b/src/components/reactGrid/CustomReactGrid.jsx @@ -4,7 +4,7 @@ import '@silevis/reactgrid/styles.css'; import { CellTemplates } from './cells'; const departmentOptions = [ - { label: 'None', value: undefined }, + { label: '', value: '' }, { label: 'HR', value: 'hr' }, { label: 'Sales', value: 'sales' }, { label: 'Marketing', value: 'marketing' }, @@ -27,7 +27,7 @@ const getEmployees = () => [ dept: 'sales', hiredAt: new Date('10-15-2020'), }, - { id: '', fName: '', lName: '', dept: undefined, hiredAt: '' }, + { id: '', fName: '', lName: '', dept: '', hiredAt: '' }, ]; const getColumns = () => [ @@ -45,7 +45,7 @@ const headerRow = { { type: 'header', text: 'First Name' }, { type: 'header', text: 'Last Name' }, { type: 'header', text: 'Department' }, - { type: 'header', text: 'Hire Date' }, + { type: 'header', text: 'Hired Date' }, ], }; @@ -77,7 +77,6 @@ const applyCellChanges = (changes, prevRows) => { changes.forEach((change) => { const { rowId, columnId, previousCell, newCell } = change; - if (newCell.type === 'number') { prevRows[rowId][columnId] = newCell.value; } @@ -89,10 +88,7 @@ const applyCellChanges = (changes, prevRows) => { } if (change.type === 'dropdown' && change.columnId === 'dept') { prevRows[rowId].isOpen = newCell.isOpen; - if ( - newCell.selectedValue && - newCell.selectedValue !== previousCell.selectedValue - ) { + if (newCell.selectedValue !== previousCell.selectedValue) { prevRows[rowId].dept = newCell.selectedValue; } } @@ -103,7 +99,6 @@ const applyCellChanges = (changes, prevRows) => { const CustomReactGrid = () => { const [employees, setEmployees] = useState(getEmployees()); - // console.log('employees', employees); const [columns] = useState(getColumns()); const rows = getRows(employees); @@ -148,6 +143,7 @@ const CustomReactGrid = () => { customCellTemplates={CellTemplates} onCellsChanged={handleChanges} onContextMenu={handleContextMenu} + enableColumnSelection enableRowSelection enableRangeSelection enableFillHandle diff --git a/src/components/reactGrid/cells/DropdownCellTemplateOg.jsx b/src/components/reactGrid/cells/DropdownCellTemplateOg.jsx new file mode 100644 index 0000000..1460d03 --- /dev/null +++ b/src/components/reactGrid/cells/DropdownCellTemplateOg.jsx @@ -0,0 +1,275 @@ +import React from 'react'; +import { + getCellProperty, + getCharFromKey, + isAlphaNumericKey, + keyCodes, +} from '@silevis/reactgrid'; + +import Select from 'react-select'; + +export class DropdownCellTemplate { + getCompatibleCell(uncertainCell) { + let selectedValue; + + try { + selectedValue = getCellProperty(uncertainCell, 'selectedValue', 'string'); + } catch { + selectedValue = undefined; + } + + const values = getCellProperty(uncertainCell, 'values', 'object'); + const value = selectedValue ? parseFloat(selectedValue) : NaN; + + let isDisabled = true; + try { + isDisabled = getCellProperty(uncertainCell, 'isDisabled', 'boolean'); + } catch { + isDisabled = false; + } + + let inputValue; + try { + inputValue = getCellProperty(uncertainCell, 'inputValue', 'string'); + } catch { + inputValue = undefined; + } + + let isOpen; + try { + isOpen = getCellProperty(uncertainCell, 'isOpen', 'boolean'); + } catch { + isOpen = false; + } + + const text = selectedValue || ''; + + return { + ...uncertainCell, + selectedValue, + text, + value, + values, + isDisabled, + isOpen, + inputValue, + }; + } + + update(cell, cellToMerge) { + // I use the text property as a selectedValue property because behaviors don't know about the selectedValue property + // and instead throw an error when we try to access it. + // Before merging, we also need to check if the incoming value is in the target values array, otherwise we set it to undefined. + const selectedValueFromText = cell.values.some( + (val) => val.value === cellToMerge.text + ) + ? cellToMerge.text + : undefined; + + return this.getCompatibleCell({ + ...cell, + selectedValue: selectedValueFromText, + isOpen: cellToMerge.isOpen, + inputValue: cellToMerge.inputValue, + }); + } + + getClassName(cell, isInEditMode) { + const isOpen = cell.isOpen ? 'open' : 'closed'; + return `${cell.className ? cell.className : ''}${isOpen}`; + } + + handleKeyDown(cell, keyCode, ctrl, shift, alt, key, capsLock) { + if ((keyCode === keyCodes.SPACE || keyCode === keyCodes.ENTER) && !shift) { + return { + cell: this.getCompatibleCell({ ...cell, isOpen: !cell.isOpen }), + enableEditMode: false, + }; + } + + const char = getCharFromKey(key, shift, capsLock); + + if ( + !ctrl && + !alt && + isAlphaNumericKey(keyCode) && + !(shift && keyCode === keyCodes.SPACE) + ) + return { + cell: this.getCompatibleCell({ + ...cell, + inputValue: char, + isOpen: !cell.isOpen, + }), + enableEditMode: false, + }; + + return { cell, enableEditMode: false }; + } + + handleCompositionEnd(cell, eventData) { + return { + cell: { ...cell, inputValue: eventData, isOpen: !cell.isOpen }, + enableEditMode: false, + }; + } + + render(cell, isInEditMode, onCellChanged) { + return ( + + onCellChanged(this.getCompatibleCell(cell), true) + } + cell={cell} + /> + ); + } +} + +const DropdownInput = ({ onCellChanged, cell }) => { + const selectRef = React.useRef(null); + + const [inputValue, setInputValue] = React.useState(cell.inputValue); + const selectedValue = React.useMemo( + () => cell.values.find((val) => val.value === cell.text), + [cell.text, cell.values] + ); + + React.useEffect(() => { + if (cell.isOpen && selectRef.current) { + selectRef.current.focus(); + setInputValue(cell.inputValue); + } + }, [cell.isOpen, cell.inputValue]); + + return ( +
onCellChanged({ ...cell, isOpen: true })} + > +