reactjs - ¿Cómo actualizar una celda en modo de edición al actualizar otra en MUI Data Grid v6?
Estoy usando el componente MUI Data Grid v6 y haciendo uso de su función de edición CRUD incorporada. Tengo varias columnas, todas editables. Después de seleccionar un nuevo valor en mi columna "category" de tipo singleSelect, este valor debería estar preasignado a la segunda columna llamada "remark", que es de tipo string.
Es bastante fácil cambiar el modelo de fila con valueSetter y valueGetter, pero no encontré una manera de también cambiar el "modelo de fila de edición" y aplicar el cambio directamente al campo de entrada.
¿Alguna idea de cómo lograr esto?
Aquí hay un extracto de mi código actual:
const columns: GridColDef[] = [
{
field: 'category',
headerName: 'Category',
type: 'singleSelect',
flex: 2,
editable: true,
valueOptions: ['First', 'Second', 'Third'],
},
{
field: 'remark',
headerName: 'Remark',
type: 'string',
flex: 2,
editable: true
},
{
field: 'actions',
headerName: 'Actions',
type: 'actions',
flex: 1,
getActions: ({ id }) => { /*...*/ },
},
];
// ...
<DataGrid
rows={rows}
columns={columns}
editMode="row"
rowModesModel={rowModesModel}
onRowModesModelChange={handleRowModesModelChange}
onRowEditStop={handleRowEditStop}
processRowUpdate={processRowUpdate}
slots={{
toolbar: EditToolbar,
}}
slotProps={{
toolbar: { setRows, setRowModesModel },
}}
/>
Respuesta #1
Creo que tengo una solución para este problema. Aunque podría ser solo para la licencia Pro.
En mi caso, tengo un objeto anidado llamado "vehicle".
Comienza creando un componente personalizado que use useGridApiContext(). Necesitaba algunos datos predeterminados para establecer si mi singleSelect cambia. Así que estoy agregando una prop a GridEditSingleSelectCellProps.
type CustomTypeEditProps = GridEditSingleSelectCellProps & {
vehicleTypes: VehicleType[]
}
const CustomTypeEditComponent = (props: CustomTypeEditProps) => {
const apiRef = useGridApiContext()
const handleValueChange = async (_: SelectChangeEvent, newValue: string) => {
const vehicleType = props.vehicleTypes.find(x => x.id === newValue)
await apiRef.current.setEditCellValue({
id: props.id,
field: 'vehicleWeight',
value: vehicleType?.vehicleWeight
})
await apiRef.current.setEditCellValue({
id: props.id,
field: 'vehicleLength',
value: vehicleType?.vehicleLength
})
}
return (
<GridEditSingleSelectCell onValueChange={handleValueChange} {...props} />
)
}
Entonces puedes usar este componente en el array de columnas. Algo así.
[
{
field: 'vehicle',
headerName: 'Vehicle',
flex: 1,
editable: true,
valueSetter: vehicleDataSetter('articleId'),
valueGetter ({ row }) {
return row.vehicle.articleId
},
renderEditCell (params) {
const customParams = { ...params, vehicleTypes }
return <CustomTypeEditComponent {...customParams} />
},
valueOptions: vehicleTypes.map(v => ({
value: v.id,
label: v.id
})),
type: 'singleSelect'
},
{
field: 'vehicleWeight',
headerName: 'Weight',
flex: 1,
editable: true,
type: 'number',
valueGetter (params) {
return params.row.vehicle.weight
},
valueSetter: vehicleDataSetter('weight')
},
{
field: 'vehicleLength',
headerName: 'Length',
flex: 1,
editable: true,
type: 'number',
valueGetter (params) {
return params.row.vehicle.length
},
valueSetter: vehicleDataSetter('length')
},
]
Tengo una función para manejar el establecimiento de los datos seleccionados en cada propiedad del objeto anidado.
const vehicleDataSetter =
(key: string) => (params: GridValueSetterParams) => {
return {
...params.row,
vehicle: {
...params.row.vehicle,
[key]: params.value
}
}
}
Respuesta #2
¿Intentaste implementar esa lógica en la función de retorno processRowUpdate?
Ahí puedes comparar la fila actualizada con la original y aplicar los cambios necesarios
<DataGrid
processRowUpdate={(updatedRow, originalRow) => {
if (updatedRow.category !== originalRow.category) {
return {
...updatedRow,
remark: `${updatedRow.category} FILL_MORE`
}
}
return updatedRow
}}
/>
Tenga en cuenta que el campo de observaciones cambiará solo después de que salga del modo de edición del campo de categoría
