@@ -849,6 +849,9 @@ export const ObjectGrid: React.FC<ObjectGridProps> = ({
849849
850850 return {
851851 ...col ,
852+ // Forward the resolved type so the inline editor (data-table) can
853+ // pick a type-aware control (date picker, number, ...).
854+ type : col . type ?? inferredType ,
852855 ...( schema . showColumnTypeIcons && { headerIcon : getTypeIcon ( inferredType ) } ) ,
853856 cell : ( value : any ) => < CellRenderer value = { value } field = { fieldMeta as any } /> ,
854857 } ;
@@ -1010,6 +1013,10 @@ export const ObjectGrid: React.FC<ObjectGridProps> = ({
10101013 return {
10111014 header,
10121015 accessorKey : col . field ,
1016+ // Forward the resolved (base) field type so the inline editor can
1017+ // pick a type-aware control. Use baseInferredType (date/number/...)
1018+ // rather than the renderer type so e.g. `date` stays `date`.
1019+ ...( baseInferredType && { type : baseInferredType } ) ,
10131020 ...( schema . showColumnTypeIcons && { headerIcon : getTypeIcon ( inferredType ) } ) ,
10141021 ...( ! isEssential && { className : 'hidden sm:table-cell' } ) ,
10151022 ...( col . width && { width : col . width } ) ,
@@ -1090,6 +1097,8 @@ export const ObjectGrid: React.FC<ObjectGridProps> = ({
10901097 return {
10911098 header,
10921099 accessorKey : fieldName ,
1100+ // Forward the resolved field type for the type-aware inline editor.
1101+ ...( resolvedType && { type : resolvedType } ) ,
10931102 ...( schema . showColumnTypeIcons && resolvedType && { headerIcon : getTypeIcon ( resolvedType ) } ) ,
10941103 ...( inferredAlign && { align : inferredAlign } ) ,
10951104 ...( cellRenderer && { cell : cellRenderer } ) ,
@@ -1133,6 +1142,8 @@ export const ObjectGrid: React.FC<ObjectGridProps> = ({
11331142 return {
11341143 header,
11351144 accessorKey : fieldName ,
1145+ // Forward the resolved field type for the type-aware inline editor.
1146+ ...( resolvedType && { type : resolvedType } ) ,
11361147 ...( schema . showColumnTypeIcons && resolvedType && { headerIcon : getTypeIcon ( resolvedType ) } ) ,
11371148 ...( inferredAlign && { align : inferredAlign } ) ,
11381149 ...( CellRenderer && { cell : ( value : any ) => < CellRenderer value = { value } field = { fieldMeta as any } /> } ) ,
@@ -1197,6 +1208,8 @@ export const ObjectGrid: React.FC<ObjectGridProps> = ({
11971208 generatedColumns . push ( {
11981209 header : schema . objectName ? resolveFieldLabel ( schema . objectName , fieldName , field . label || fieldName ) : field . label || fieldName ,
11991210 accessorKey : fieldName ,
1211+ // Forward the field type for the type-aware inline editor.
1212+ ...( field . type && { type : field . type } ) ,
12001213 ...( numericTypes . includes ( field . type ) && { align : 'right' } ) ,
12011214 cell : ( value : any ) => < CellRenderer value = { value } field = { fieldForCell } /> ,
12021215 sortable : field . sortable !== false ,
@@ -1544,6 +1557,56 @@ export const ObjectGrid: React.FC<ObjectGridProps> = ({
15441557 }
15451558 } ;
15461559
1560+ // Default inline-edit persistence.
1561+ //
1562+ // When a consumer wires `onRowSave`/`onBatchSave` (React host), we defer to it.
1563+ // But a declaratively-configured `editable: true` view has no host wiring — so
1564+ // "Save All" would otherwise just clear pending changes without writing to the
1565+ // backend. Supply a default that persists through the grid's `dataSource`, then
1566+ // refresh so the grid reflects persisted values. Throwing on failure is
1567+ // important: DataTable's saveRow/saveBatch keep pending changes when the save
1568+ // promise rejects, so a failed write doesn't silently lose the user's edits.
1569+ const resolveRecordId = ( row : any ) : string | number | undefined =>
1570+ row ?. _id ?? row ?. id ;
1571+
1572+ const defaultRowSave = async (
1573+ _rowIndex : number ,
1574+ changes : Record < string , any > ,
1575+ row : any ,
1576+ ) : Promise < void > => {
1577+ if ( ! dataSource || ! objectName ) {
1578+ throw new Error ( 'Cannot persist inline edit: no dataSource/objectName configured on the grid.' ) ;
1579+ }
1580+ const id = resolveRecordId ( row ) ;
1581+ if ( id === undefined || id === null ) {
1582+ throw new Error ( 'Cannot persist inline edit: row has no id/_id.' ) ;
1583+ }
1584+ await dataSource . update ( objectName , id , changes ) ;
1585+ // Refresh so the grid shows the persisted values.
1586+ setRefreshKey ( k => k + 1 ) ;
1587+ } ;
1588+
1589+ const defaultBatchSave = async (
1590+ changes : Array < { rowIndex : number ; changes : Record < string , any > ; row : any } > ,
1591+ ) : Promise < void > => {
1592+ if ( ! dataSource || ! objectName ) {
1593+ throw new Error ( 'Cannot persist inline edits: no dataSource/objectName configured on the grid.' ) ;
1594+ }
1595+ // Update each modified row. The DataSource `bulk`/`bulkUpdate` primitives
1596+ // apply a single uniform patch across many ids, which does NOT fit per-row
1597+ // edits (each row has its own field changes), so issue one update per row.
1598+ await Promise . all (
1599+ changes . map ( ( { changes : rowChanges , row } ) => {
1600+ const id = resolveRecordId ( row ) ;
1601+ if ( id === undefined || id === null ) {
1602+ throw new Error ( 'Cannot persist inline edit: row has no id/_id.' ) ;
1603+ }
1604+ return dataSource . update ( objectName , id , rowChanges ) ;
1605+ } ) ,
1606+ ) ;
1607+ setRefreshKey ( k => k + 1 ) ;
1608+ } ;
1609+
15471610 // Determine pagination settings (support both new and legacy formats)
15481611 const paginationEnabled = schema . pagination !== undefined
15491612 ? true
@@ -1639,8 +1702,10 @@ export const ObjectGrid: React.FC<ObjectGridProps> = ({
16391702 } ,
16401703 onRowClick : navigation . handleClick ,
16411704 onCellChange : onCellChange ,
1642- onRowSave : onRowSave ,
1643- onBatchSave : onBatchSave ,
1705+ // Install a dataSource-backed default only when the consumer did NOT wire
1706+ // its own handler, so declarative `editable: true` views still persist.
1707+ onRowSave : onRowSave ?? defaultRowSave ,
1708+ onBatchSave : onBatchSave ?? defaultBatchSave ,
16441709 onColumnResize : ( columnKey : string , width : number ) => {
16451710 saveColumnState ( {
16461711 ...columnState ,
0 commit comments