diff --git a/client/packages/lowcoder/src/components/table/EditableCell.tsx b/client/packages/lowcoder/src/components/table/EditableCell.tsx index 42d712345..b88616744 100644 --- a/client/packages/lowcoder/src/components/table/EditableCell.tsx +++ b/client/packages/lowcoder/src/components/table/EditableCell.tsx @@ -54,6 +54,7 @@ export type EditViewFn = (props: { value: T; onChange: (value: T) => void; onChangeEnd: () => void; + onImmediateSave?: (value: T) => void; otherProps?: Record; }) => ReactNode; @@ -168,9 +169,26 @@ function EditableCellComp(props: EditableCellProps) { } }, [dispatch, tmpValue, baseValue, value, onTableEvent, setIsEditing]); + const onImmediateSave = useCallback((newValue: T) => { + if (!mountedRef.current) return; + + setTmpValue(newValue); + const changeValue = _.isNil(newValue) || _.isEqual(newValue, baseValue) ? null : newValue; + dispatch( + changeChildAction( + "changeValue", + changeValue, + false + ) + ); + if(!_.isEqual(newValue, value)) { + onTableEvent?.('columnEdited'); + } + }, [dispatch, baseValue, value, onTableEvent]); + const editView = useMemo( - () => editViewFn?.({ value, onChange, onChangeEnd, otherProps }) ?? <>, - [editViewFn, value, onChange, onChangeEnd, otherProps] + () => editViewFn?.({ value, onChange, onChangeEnd, onImmediateSave, otherProps }) ?? <>, + [editViewFn, value, onChange, onChangeEnd, onImmediateSave, otherProps] ); const enterEditFn = useCallback(() => { diff --git a/client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComps/columnBooleanComp.tsx b/client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComps/columnBooleanComp.tsx index d1d530eb6..1cc26a5ea 100644 --- a/client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComps/columnBooleanComp.tsx +++ b/client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComps/columnBooleanComp.tsx @@ -64,6 +64,7 @@ type CheckBoxEditPropsType = { value: boolean; onChange: (value: boolean) => void; onChangeEnd: () => void; + onImmediateSave?: (value: boolean) => void; }; // Memoized checkbox edit component @@ -92,8 +93,13 @@ const CheckBoxEdit = React.memo((props: CheckBoxEditPropsType) => { const handleChange = useCallback((e: CheckboxChangeEvent) => { if (!mountedRef.current) return; - props.onChange(e.target.checked); - }, [props.onChange]); + const newValue = e.target.checked; + props.onChange(newValue); + // Use immediate save to show Save Changes button without exiting edit mode + if (props.onImmediateSave) { + props.onImmediateSave(newValue); + } + }, [props.onChange, props.onImmediateSave]); return ( ); }) diff --git a/client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComps/columnSelectComp.tsx b/client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComps/columnSelectComp.tsx index b54be8799..adc2c4d88 100644 --- a/client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComps/columnSelectComp.tsx +++ b/client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComps/columnSelectComp.tsx @@ -124,6 +124,7 @@ type SelectEditProps = { initialValue: string; onChange: (value: string) => void; onChangeEnd: () => void; + onImmediateSave?: (value: string) => void; options: any[]; onMainEvent?: (eventName: string) => void; }; @@ -146,6 +147,11 @@ const SelectEdit = React.memo((props: SelectEditProps) => { props.onChange(val); setCurrentValue(val); + // Use immediate save to show Save Changes button without exiting edit mode + if (props.onImmediateSave) { + props.onImmediateSave(val); + } + // Trigger the specific option's event handler const selectedOption = props.options.find(option => option.value === val); if (selectedOption?.onEvent) { @@ -156,7 +162,7 @@ const SelectEdit = React.memo((props: SelectEditProps) => { if (props.onMainEvent) { props.onMainEvent("click"); } - }, [props.onChange, props.options, props.onMainEvent]); + }, [props.onChange, props.onImmediateSave, props.options, props.onMainEvent]); const handleEvent = useCallback(async (eventName: string) => { if (!mountedRef.current) return [] as unknown[]; @@ -209,6 +215,7 @@ export const ColumnSelectComp = (function () { options={props.otherProps?.options || []} onChange={props.onChange} onChangeEnd={props.onChangeEnd} + onImmediateSave={props.onImmediateSave} onMainEvent={props.otherProps?.onEvent} /> diff --git a/client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComps/columnSwitchComp.tsx b/client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComps/columnSwitchComp.tsx index 0cdeee48a..d005f2ecc 100644 --- a/client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComps/columnSwitchComp.tsx +++ b/client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComps/columnSwitchComp.tsx @@ -144,6 +144,10 @@ export const SwitchComp = (function () { disabled={false} onChange={(checked, e) => { props.onChange(checked); + // Use immediate save to show Save Changes button without exiting edit mode + if (props.onImmediateSave) { + props.onImmediateSave(checked); + } props.otherProps?.onEvent?.("change"); props.otherProps?.onEvent?.(checked ? "true" : "false"); }}