UNPKG

@mui/x-data-grid

Version:

The community edition of the data grid component (MUI X).

505 lines (431 loc) 17.9 kB
import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator"; import _extends from "@babel/runtime/helpers/esm/extends"; import _regeneratorRuntime from "@babel/runtime/regenerator"; import * as React from 'react'; import { useEventCallback } from '@mui/material/utils'; import { useGridApiMethod } from '../../utils/useGridApiMethod'; import { GridRowModes, GridEditModes, GridCellModes } from '../../../models/gridEditRowModel'; import { useGridSelector } from '../../utils/useGridSelector'; import { gridColumnDefinitionsSelector } from '../columns/gridColumnsSelector'; import { gridEditRowsStateSelector } from './gridEditRowsSelector'; import { gridFocusCellSelector } from '../focus/gridFocusStateSelector'; import { useGridApiOptionHandler, useGridApiEventHandler } from '../../utils/useGridApiEventHandler'; export var useGridRowEditing = function useGridRowEditing(apiRef, props) { var _props$experimentalFe2, _props$experimentalFe4; var focusTimeout = React.useRef(null); var nextFocusedCell = React.useRef(null); var columns = useGridSelector(apiRef, gridColumnDefinitionsSelector); var buildCallback = function buildCallback(callback) { return function () { if (props.editMode === GridEditModes.Row) { callback.apply(void 0, arguments); } }; }; var setRowMode = React.useCallback(function (id, mode) { if (mode === apiRef.current.getRowMode(id)) { return; } apiRef.current.setState(function (state) { var newEditRowsState = _extends({}, state.editRows); if (mode === GridRowModes.Edit) { newEditRowsState[id] = {}; columns.forEach(function (column) { var cellParams = apiRef.current.getCellParams(id, column.field); if (cellParams.isEditable) { newEditRowsState[id][column.field] = { value: cellParams.value }; } }); } else { delete newEditRowsState[id]; } return _extends({}, state, { editRows: newEditRowsState }); }); apiRef.current.forceUpdate(); }, [apiRef, columns]); var getRowMode = React.useCallback(function (id) { if (props.editMode === GridEditModes.Cell) { return GridRowModes.View; } var editRowsState = gridEditRowsStateSelector(apiRef.current.state); return editRowsState[id] ? GridRowModes.Edit : GridRowModes.View; }, [apiRef, props.editMode]); var commitRowChange = React.useCallback(function (id) { var _props$experimentalFe; var event = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; if (props.editMode === GridEditModes.Cell) { throw new Error("MUI: You can't commit changes when the edit mode is 'cell'."); } apiRef.current.unstable_runPendingEditCellValueMutation(id); var model = apiRef.current.getEditRowsModel(); var editRowProps = model[id]; if (!editRowProps) { throw new Error("MUI: Row at id: ".concat(id, " is not being edited.")); } if ((_props$experimentalFe = props.experimentalFeatures) != null && _props$experimentalFe.preventCommitWhileValidating) { var isValid = Object.keys(editRowProps).reduce(function (acc, field) { return acc && !editRowProps[field].isValidating && !editRowProps[field].error; }, true); if (!isValid) { return false; } } var hasFieldWithError = Object.values(editRowProps).some(function (value) { return !!value.error; }); if (hasFieldWithError) { return false; } var fieldsWithValidator = Object.keys(editRowProps).filter(function (field) { var column = apiRef.current.getColumn(field); return typeof column.preProcessEditCellProps === 'function'; }); if (fieldsWithValidator.length > 0) { var row = apiRef.current.getRow(id); var validatorErrors = fieldsWithValidator.map( /*#__PURE__*/function () { var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(field) { var column, newEditCellProps; return _regeneratorRuntime.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: column = apiRef.current.getColumn(field); _context.next = 3; return Promise.resolve(column.preProcessEditCellProps({ id: id, row: row, props: editRowProps[field] })); case 3: newEditCellProps = _context.sent; apiRef.current.unstable_setEditCellProps({ id: id, field: field, props: newEditCellProps }); return _context.abrupt("return", newEditCellProps.error); case 6: case "end": return _context.stop(); } } }, _callee); })); return function (_x) { return _ref.apply(this, arguments); }; }()); return Promise.all(validatorErrors).then(function (errors) { if (errors.some(function (error) { return !!error; })) { return false; } apiRef.current.publishEvent('rowEditCommit', id, event); return true; }); } apiRef.current.publishEvent('rowEditCommit', id, event); return true; }, [apiRef, props.editMode, (_props$experimentalFe2 = props.experimentalFeatures) == null ? void 0 : _props$experimentalFe2.preventCommitWhileValidating]); var setRowEditingEditCellValue = React.useCallback(function (params) { var model = apiRef.current.getEditRowsModel(); var editRow = model[params.id]; var row = apiRef.current.getRow(params.id); var isValid = true; return new Promise(function (resolve) { Object.keys(editRow).forEach( /*#__PURE__*/function () { var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(field) { var column, editCellProps; return _regeneratorRuntime.wrap(function _callee2$(_context2) { while (1) { switch (_context2.prev = _context2.next) { case 0: column = apiRef.current.getColumn(field); editCellProps = field === params.field ? { value: params.value } : editRow[field]; // setEditCellProps runs the value parser and returns the updated props editCellProps = apiRef.current.unstable_setEditCellProps({ id: params.id, field: field, props: _extends({}, editCellProps, { isValidating: true }) }); if (!column.preProcessEditCellProps) { _context2.next = 7; break; } _context2.next = 6; return Promise.resolve(column.preProcessEditCellProps({ id: params.id, row: row, props: _extends({}, editCellProps, { value: field === params.field ? apiRef.current.unstable_parseValue(params.id, field, params.value) : editCellProps.value }) })); case 6: editCellProps = _context2.sent; case 7: if (editCellProps.error) { isValid = false; } apiRef.current.unstable_setEditCellProps({ id: params.id, field: field, props: _extends({}, editCellProps, { isValidating: false }) }); case 9: case "end": return _context2.stop(); } } }, _callee2); })); return function (_x2) { return _ref2.apply(this, arguments); }; }()); resolve(isValid); }); }, [apiRef]); var rowEditingApi = { setRowMode: setRowMode, getRowMode: getRowMode, commitRowChange: commitRowChange, unstable_setRowEditingEditCellValue: setRowEditingEditCellValue }; useGridApiMethod(apiRef, rowEditingApi, 'EditRowApi'); var handleCellKeyDown = React.useCallback( /*#__PURE__*/function () { var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3(params, event) { var cellMode, isEditable, isEditMode, rowParams, _props$experimentalFe3, isValid; return _regeneratorRuntime.wrap(function _callee3$(_context3) { while (1) { switch (_context3.prev = _context3.next) { case 0: if (!(event.which === 229)) { _context3.next = 2; break; } return _context3.abrupt("return"); case 2: cellMode = params.cellMode, isEditable = params.isEditable; if (isEditable) { _context3.next = 5; break; } return _context3.abrupt("return"); case 5: isEditMode = cellMode === GridCellModes.Edit; rowParams = apiRef.current.getRowParams(params.id); if (!isEditMode) { _context3.next = 20; break; } if (!(event.key === 'Enter')) { _context3.next = 17; break; } _context3.next = 11; return apiRef.current.commitRowChange(params.id); case 11: isValid = _context3.sent; if (!(!isValid && (_props$experimentalFe3 = props.experimentalFeatures) != null && _props$experimentalFe3.preventCommitWhileValidating)) { _context3.next = 14; break; } return _context3.abrupt("return"); case 14: apiRef.current.publishEvent('rowEditStop', rowParams, event); _context3.next = 18; break; case 17: if (event.key === 'Escape') { apiRef.current.publishEvent('rowEditStop', rowParams, event); } case 18: _context3.next = 21; break; case 20: if (event.key === 'Enter') { apiRef.current.publishEvent('rowEditStart', rowParams, event); } case 21: case "end": return _context3.stop(); } } }, _callee3); })); return function (_x3, _x4) { return _ref3.apply(this, arguments); }; }(), [apiRef, (_props$experimentalFe4 = props.experimentalFeatures) == null ? void 0 : _props$experimentalFe4.preventCommitWhileValidating]); var handleCellDoubleClick = React.useCallback(function (params, event) { if (!params.isEditable) { return; } var rowParams = apiRef.current.getRowParams(params.id); apiRef.current.publishEvent('rowEditStart', rowParams, event); }, [apiRef]); var handleEditCellPropsChange = React.useCallback(function (params) { var row = apiRef.current.getRow(params.id); var model = apiRef.current.getEditRowsModel(); var editRow = model[params.id]; Object.keys(editRow).forEach( /*#__PURE__*/function () { var _ref4 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee4(field) { var column, editCellProps, newEditCellProps; return _regeneratorRuntime.wrap(function _callee4$(_context4) { while (1) { switch (_context4.prev = _context4.next) { case 0: column = apiRef.current.getColumn(field); if (!column.preProcessEditCellProps) { _context4.next = 9; break; } editCellProps = field === params.field ? params.props : editRow[field]; _context4.next = 5; return Promise.resolve(column.preProcessEditCellProps({ id: params.id, row: row, props: editCellProps })); case 5: newEditCellProps = _context4.sent; apiRef.current.unstable_setEditCellProps({ id: params.id, field: field, props: newEditCellProps }); _context4.next = 10; break; case 9: if (field === params.field) { apiRef.current.unstable_setEditCellProps(params); } case 10: case "end": return _context4.stop(); } } }, _callee4); })); return function (_x5) { return _ref4.apply(this, arguments); }; }()); }, [apiRef]); var handleRowEditStart = React.useCallback(function (params) { apiRef.current.setRowMode(params.id, GridRowModes.Edit); }, [apiRef]); var handleRowEditStop = React.useCallback(function (params, event) { apiRef.current.setRowMode(params.id, GridRowModes.View); if (event.key === 'Enter') { apiRef.current.publishEvent('cellNavigationKeyDown', params, event); } }, [apiRef]); var handleRowEditCommit = React.useCallback(function (id) { var model = apiRef.current.getEditRowsModel(); var editRow = model[id]; if (!editRow) { throw new Error("MUI: Row at id: ".concat(id, " is not being edited.")); } var row = apiRef.current.getRow(id); if (row) { var rowUpdate = _extends({}, row); Object.keys(editRow).forEach(function (field) { var column = apiRef.current.getColumn(field); var value = editRow[field].value; if (column.valueSetter) { rowUpdate = column.valueSetter({ row: rowUpdate, value: value }); } else { rowUpdate[field] = value; } }); apiRef.current.updateRows([rowUpdate]); } }, [apiRef]); var handleCellFocusIn = React.useCallback(function (params) { nextFocusedCell.current = params; }, []); var commitPropsAndExit = /*#__PURE__*/function () { var _ref5 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee6(params, event) { return _regeneratorRuntime.wrap(function _callee6$(_context6) { while (1) { switch (_context6.prev = _context6.next) { case 0: if (!(params.cellMode === GridCellModes.View)) { _context6.next = 2; break; } return _context6.abrupt("return"); case 2: nextFocusedCell.current = null; focusTimeout.current = setTimeout( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee5() { var _nextFocusedCell$curr; var rowParams; return _regeneratorRuntime.wrap(function _callee5$(_context5) { while (1) { switch (_context5.prev = _context5.next) { case 0: if (!(((_nextFocusedCell$curr = nextFocusedCell.current) == null ? void 0 : _nextFocusedCell$curr.id) !== params.id)) { _context5.next = 5; break; } _context5.next = 3; return apiRef.current.commitRowChange(params.id, event); case 3: rowParams = apiRef.current.getRowParams(params.id); apiRef.current.publishEvent('rowEditStop', rowParams, event); case 5: case "end": return _context5.stop(); } } }, _callee5); }))); case 4: case "end": return _context6.stop(); } } }, _callee6); })); return function commitPropsAndExit(_x6, _x7) { return _ref5.apply(this, arguments); }; }(); var handleCellFocusOut = useEventCallback(function (params, event) { commitPropsAndExit(params, event); }); var handleColumnHeaderDragStart = useEventCallback(function () { var cell = gridFocusCellSelector(apiRef); if (!cell) { return; } var params = apiRef.current.getCellParams(cell.id, cell.field); commitPropsAndExit(params, {}); }); useGridApiEventHandler(apiRef, 'cellKeyDown', buildCallback(handleCellKeyDown)); useGridApiEventHandler(apiRef, 'cellDoubleClick', buildCallback(handleCellDoubleClick)); useGridApiEventHandler(apiRef, 'editCellPropsChange', buildCallback(handleEditCellPropsChange)); useGridApiEventHandler(apiRef, 'rowEditStart', buildCallback(handleRowEditStart)); useGridApiEventHandler(apiRef, 'rowEditStop', buildCallback(handleRowEditStop)); useGridApiEventHandler(apiRef, 'rowEditCommit', buildCallback(handleRowEditCommit)); useGridApiEventHandler(apiRef, 'cellFocusIn', buildCallback(handleCellFocusIn)); useGridApiEventHandler(apiRef, 'cellFocusOut', buildCallback(handleCellFocusOut)); useGridApiEventHandler(apiRef, 'columnHeaderDragStart', buildCallback(handleColumnHeaderDragStart)); useGridApiOptionHandler(apiRef, 'rowEditCommit', props.onRowEditCommit); useGridApiOptionHandler(apiRef, 'rowEditStart', props.onRowEditStart); useGridApiOptionHandler(apiRef, 'rowEditStop', props.onRowEditStop); };