Skip to content

Commit

Permalink
[test] Test the validation before saving a value (#2087)
Browse files Browse the repository at this point in the history
  • Loading branch information
m4theushw committed Jul 13, 2021
1 parent 780daf7 commit a4df486
Show file tree
Hide file tree
Showing 10 changed files with 123 additions and 47 deletions.
3 changes: 2 additions & 1 deletion docs/pages/api-docs/data-grid/grid-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { GridApi } from '@material-ui/x-grid';
| <span class="prop-name">applyFilterLinkOperator</span> | <span class="prop-type">(operator: GridLinkOperator) =&gt; void</span> | Changes the GridLinkOperator used to connect the filters. |
| <span class="prop-name">applyFilters</span> | <span class="prop-type">() =&gt; void</span> | Applies all filters on all rows. |
| <span class="prop-name">applySorting</span> | <span class="prop-type">() =&gt; void</span> | Applies the current sort model to the rows. |
| <span class="prop-name">commitCellChange</span> | <span class="prop-type">(params: GridCommitCellChangeParams) =&gt; void</span> | Updates the field at the given id with the value stored in the edit row model. |
| <span class="prop-name">commitCellChange</span> | <span class="prop-type">(params: GridCommitCellChangeParams, event?: SyntheticEvent&lt;Element, Event&gt;) =&gt; boolean</span> | Updates the field at the given id with the value stored in the edit row model. |
| <span class="prop-name">components</span> | <span class="prop-type">GridApiRefComponentsProperty</span> | The set of overridable components used in the grid. |
| <span class="prop-name optional">componentsProps<sup><abbr title="optional">?</abbr></sup></span> | <span class="prop-type">GridSlotsComponentsProps</span> | Overrideable components props dynamically passed to the component at rendering. |
| <span class="prop-name">deleteFilter</span> | <span class="prop-type">(item: GridFilterItem) =&gt; void</span> | Deletes a GridFilterItem. |
Expand Down Expand Up @@ -72,6 +72,7 @@ import { GridApi } from '@material-ui/x-grid';
| <span class="prop-name">setColumnWidth</span> | <span class="prop-type">(field: string, width: number) =&gt; void</span> | Updates the width of a column. |
| <span class="prop-name">setDensity</span> | <span class="prop-type">(size: GridDensity, headerHeight?: number, rowHeight?: number) =&gt; void</span> | Sets the density of the grid. |
| <span class="prop-name">setEditCellProps</span> | <span class="prop-type">(params: GridEditCellPropsParams) =&gt; void</span> | Sets the input props of the edit cell. |
| <span class="prop-name">setEditCellValue</span> | <span class="prop-type">(params: GridEditCellValueParams, event?: SyntheticEvent&lt;Element, Event&gt;) =&gt; void</span> | Sets the value of the edit cell. |
| <span class="prop-name">setEditRowsModel</span> | <span class="prop-type">(model: GridEditRowsModel) =&gt; void</span> | Set sthe edit rows model of the grid. |
| <span class="prop-name">setFilterModel</span> | <span class="prop-type">(model: GridFilterModelState) =&gt; void</span> | Sets the filter model to the one given by `model`. |
| <span class="prop-name">setPage</span> | <span class="prop-type">(page: number) =&gt; void</span> | Sets the displayed page to the value given by `page`. |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ function RatingEditInputCell(props) {
const classes = useStyles();

const handleChange = (event) => {
const editProps = { value: Number(event.target.value) };
api.setEditCellProps({ id, field, props: editProps });
api.setEditCellValue({ id, field, value: Number(event.target.value) }, event);
// Check if the event is not from the keyboard
// https://github.com/facebook/react/issues/7407
if (event.nativeEvent.clientX !== 0 && event.nativeEvent.clientY !== 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ function RatingEditInputCell(props: GridCellParams) {
const classes = useStyles();

const handleChange = (event) => {
const editProps = { value: Number(event.target.value) };
api.setEditCellProps({ id, field, props: editProps });
api.setEditCellValue({ id, field, value: Number(event.target.value) }, event);
// Check if the event is not from the keyboard
// https://github.com/facebook/react/issues/7407
if (event.nativeEvent.clientX !== 0 && event.nativeEvent.clientY !== 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,10 @@ export function GridEditBooleanCell(
const handleChange = React.useCallback(
(event: React.ChangeEvent<HTMLInputElement>) => {
const newValue = event.target.checked;
const editProps = { value: newValue };
setValueState(newValue);
api.setEditCellProps({ id: idProp, field, props: editProps });
api.setEditCellValue({ id, field, value: newValue }, event);
},
[api, field, idProp],
[api, field, id],
);

React.useEffect(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ export function GridEditDateCell(props: GridCellParams & InputBaseProps) {
setValueState(newValue);

if (newValue === '') {
const editProps = { value: null };
api.setEditCellProps({ id, field, props: editProps }, event);
api.setEditCellValue({ id, field, value: null }, event);
return;
}

Expand All @@ -44,8 +43,7 @@ export function GridEditDateCell(props: GridCellParams & InputBaseProps) {
dateObj.setHours(Number(hours), Number(minutes), 0, 0);
}

const editProps = { value: dateObj };
api.setEditCellProps({ id, field, props: editProps }, event);
api.setEditCellValue({ id, field, value: dateObj }, event);
},
[api, field, id],
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,8 @@ export function GridEditInputCell(props: GridCellParams & InputBaseProps) {
const handleChange = React.useCallback(
(event) => {
const newValue = event.target.value;
const editProps = { value: newValue };
setValueState(newValue);
api.setEditCellProps({ id, field, props: editProps });
api.setEditCellValue({ id, field, value: newValue }, event);
},
[api, field, id],
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@ export function GridEditSingleSelectCell(props: GridCellParams & SelectProps) {
} = props;

const handleChange = (event) => {
const editProps = { value: event.target.value };
api.setEditCellProps({ id, field, props: editProps }, event);
api.setEditCellValue({ id, field, value: event.target.value }, event);
if (!event.key) {
api.commitCellChange({ id, field }, event);
api.setCellMode(id, field, 'view');
Expand Down
81 changes: 52 additions & 29 deletions packages/grid/_modules_/grid/hooks/features/rows/useGridEditRows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,7 @@ export function useGridEditRows(apiRef: GridApiRef) {
if (params.cellMode === 'view') {
return;
}

const cellCommitParams = apiRef.current.getEditCellPropsParams(params.id, params.field);
if (!cellCommitParams.props.error) {
// We commit the change when there is no error
apiRef.current.publishEvent(GRID_CELL_EDIT_PROPS_CHANGE_COMMITTED, cellCommitParams);
}

apiRef.current.commitCellChange(params);
apiRef.current.publishEvent(GRID_CELL_EDIT_EXIT, params);
};

Expand All @@ -67,7 +61,6 @@ export function useGridEditRows(apiRef: GridApiRef) {
if (event && (event as any).defaultMuiPrevented) {
return;
}

commitPropsAndExit(params);
},
);
Expand Down Expand Up @@ -137,14 +130,16 @@ export function useGridEditRows(apiRef: GridApiRef) {
[options.isCellEditable],
);

const setEditCellProps = React.useCallback(
(params: GridEditCellPropsParams, event?: React.SyntheticEvent) => {
if (event?.isPropagationStopped()) {
return;
}

apiRef.current.publishEvent(GRID_CELL_EDIT_PROPS_CHANGE, params, event);
const setEditCellValue = React.useCallback(
(params: GridEditCellValueParams, event?: React.SyntheticEvent) => {
const newParams = { id: params.id, field: params.field, props: { value: params.value } };
apiRef.current.publishEvent(GRID_CELL_EDIT_PROPS_CHANGE, newParams, event);
},
[apiRef],
);

const setEditCellProps = React.useCallback(
(params: GridEditCellPropsParams) => {
const { id, field, props } = params;
logger.debug(`Setting cell props on id: ${id} field: ${field}`);
setGridState((state) => {
Expand All @@ -168,6 +163,16 @@ export function useGridEditRows(apiRef: GridApiRef) {
[apiRef, forceUpdate, logger, setGridState],
);

const handleCellEditPropsChange = React.useCallback(
(params: GridEditCellPropsParams, event?: React.SyntheticEvent) => {
if (event?.isPropagationStopped()) {
return;
}
apiRef.current.setEditCellProps(params);
},
[apiRef],
);

const setEditRowsModel = React.useCallback(
(editRows: GridEditRowsModel): void => {
logger.debug(`Setting row model`);
Expand Down Expand Up @@ -195,17 +200,31 @@ export function useGridEditRows(apiRef: GridApiRef) {
);

const commitCellChange = React.useCallback(
(params: GridCommitCellChangeParams, event?: React.SyntheticEvent): boolean => {
const { id, field } = params;
const model = apiRef.current.getEditRowsModel();
if (!model[id] || !model[id][field]) {
throw new Error(`Cell at id: ${id} and field: ${field} is not in edit mode`);
}

const { error } = model[id][field];
if (!error) {
apiRef.current.publishEvent(GRID_CELL_EDIT_PROPS_CHANGE_COMMITTED, params, event);
return true;
}
return false;
},
[apiRef],
);

const handleCellEditPropsChangeCommited = React.useCallback(
(params: GridCommitCellChangeParams, event?: React.SyntheticEvent) => {
if (event?.isPropagationStopped()) {
return;
}

const { id, field } = params;
const model = apiRef.current.getEditRowsModel();
if (!model[id] || !model[id][field]) {
throw new Error(`Cell at id: ${id} and field: ${field} is not in edit mode`);
}

const { value } = model[id][field];
logger.debug(`Setting cell id: ${id} field: ${field} to value: ${value?.toString()}`);
const row = apiRef.current.getRow(id);
Expand Down Expand Up @@ -278,20 +297,16 @@ export function useGridEditRows(apiRef: GridApiRef) {
apiRef.current.publishEvent(GRID_CELL_EDIT_ENTER, params, event);
}
if (!isEditMode && isDeleteKeys(event.key)) {
const commitParams: GridEditCellPropsParams = apiRef.current.getEditCellPropsParams(
params.id,
params.field,
);
const commitParams = apiRef.current.getEditCellPropsParams(params.id, params.field);
commitParams.props.value = '';
apiRef.current.publishEvent(GRID_CELL_EDIT_PROPS_CHANGE_COMMITTED, commitParams, event);
apiRef.current.commitCellChange(commitParams, event);
apiRef.current.publishEvent(GRID_CELL_EDIT_EXIT, params, event);
}
if (isEditMode && isCellEditCommitKeys(event.key)) {
const cellCommitParams = apiRef.current.getEditCellPropsParams(params.id, params.field);
if (cellCommitParams.props.error) {
const commitParams = apiRef.current.getEditCellPropsParams(params.id, params.field);
if (!apiRef.current.commitCellChange(commitParams, event)) {
return;
}
apiRef.current.publishEvent(GRID_CELL_EDIT_PROPS_CHANGE_COMMITTED, cellCommitParams, event);
}
if (isEditMode && !event.isPropagationStopped() && isCellExitEditModeKeys(event.key)) {
apiRef.current.publishEvent(GRID_CELL_EDIT_EXIT, params, event);
Expand All @@ -313,15 +328,22 @@ export function useGridEditRows(apiRef: GridApiRef) {
useGridApiEventHandler(apiRef, GRID_CELL_EDIT_ENTER, handleEnterEdit);
useGridApiEventHandler(apiRef, GRID_CELL_EDIT_EXIT, handleExitEdit);
useGridApiEventHandler(apiRef, GRID_CELL_FOCUS_OUT, handleCellFocusOut);
useGridApiEventHandler(apiRef, GRID_CELL_EDIT_PROPS_CHANGE, handleCellEditPropsChange);
useGridApiEventHandler(apiRef, GRID_COLUMN_HEADER_DRAG_START, handleColumnHeaderDragStart);
useGridApiEventHandler(apiRef, GRID_CELL_EDIT_PROPS_CHANGE_COMMITTED, commitCellChange);
useGridApiEventHandler(
apiRef,
GRID_CELL_EDIT_PROPS_CHANGE_COMMITTED,
handleCellEditPropsChangeCommited,
);

useGridApiOptionHandler(
apiRef,
GRID_CELL_EDIT_PROPS_CHANGE_COMMITTED,
options.onEditCellChangeCommitted,
);
// TODO rename to onEditCellPropsChange
useGridApiOptionHandler(apiRef, GRID_CELL_EDIT_PROPS_CHANGE, options.onEditCellChange);
// TODO remove because onEditCellChange does the same
useGridApiOptionHandler(apiRef, GRID_CELL_VALUE_CHANGE, options.onCellValueChange);
useGridApiOptionHandler(apiRef, GRID_CELL_MODE_CHANGE, options.onCellModeChange);
useGridApiOptionHandler(apiRef, GRID_ROW_EDIT_MODEL_CHANGE, options.onEditRowModelChange);
Expand All @@ -333,10 +355,11 @@ export function useGridEditRows(apiRef: GridApiRef) {
getCellMode,
isCellEditable,
commitCellChange,
setEditCellProps,
setEditCellProps, // TODO don't expose, update the editRowsModel prop directly
getEditCellPropsParams,
setEditRowsModel,
getEditRowsModel,
setEditCellValue,
},
'EditRowApi',
);
Expand Down
16 changes: 14 additions & 2 deletions packages/grid/_modules_/grid/models/api/gridEditRowApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import { GridCellMode } from '../gridCell';
import { GridEditRowsModel } from '../gridEditRowModel';
import { GridRowId } from '../gridRows';
import { GridCellParams } from '../params/gridCellParams';
import { GridEditCellPropsParams, GridCommitCellChangeParams } from '../params/gridEditCellParams';
import {
GridEditCellPropsParams,
GridCommitCellChangeParams,
GridEditCellValueParams,
} from '../params/gridEditCellParams';

/**
* The editing API interface that is available in the grid `apiRef`.
Expand Down Expand Up @@ -43,6 +47,12 @@ export interface GridEditRowApi {
* @param {GridEditCellPropsParams} params The params to set.
*/
setEditCellProps: (params: GridEditCellPropsParams) => void;
/**
* Sets the value of the edit cell.
* @param {GridEditCellValueParams} params Contains the id, field and value to set.
* @param {React.SyntheticEvent} event The event to pass forward.
*/
setEditCellValue: (params: GridEditCellValueParams, event?: React.SyntheticEvent) => void;
/**
* Gets the params to be passed when calling `setEditCellProps`.
* @param {GridRowId} rowId The id of the row.
Expand All @@ -53,6 +63,8 @@ export interface GridEditRowApi {
/**
* Updates the field at the given id with the value stored in the edit row model.
* @param {GridCommitCellChangeParams} params The id and field to commit to.
* @param {React.SyntheticEvent} event The event to pass forward.
* @returns {boolean} A boolean indicating if there is an error.
*/
commitCellChange: (params: GridCommitCellChangeParams) => void;
commitCellChange: (params: GridCommitCellChangeParams, event?: React.SyntheticEvent) => boolean;
}

0 comments on commit a4df486

Please sign in to comment.