Improve auto-focus of editable data grid when adding/editing rows

This commit is contained in:
Aditya Toshniwal 2024-01-17 18:38:00 +05:30
parent 60983a25d2
commit d26c167c76
3 changed files with 33 additions and 2 deletions

View File

@ -34,6 +34,7 @@ import { DepListenerContext } from './DepListener';
import { useIsMounted } from '../custom_hooks';
import { InputText } from '../components/FormComponents';
import { usePgAdmin } from '../BrowserComponent';
import { requestAnimationAndFocus } from '../utils';
const useStyles = makeStyles((theme)=>({
grid: {
@ -221,6 +222,10 @@ function DataTableRow({index, row, totalRows, isResizing, isHovered, schema, sch
}
});
});
// Try autofocus on newly added row.
requestAnimationAndFocus(rowRef.current?.querySelector('input'));
return ()=>{
/* Cleanup the listeners when unmounting */
depListener?.removeDepListener(accessPath);
@ -656,7 +661,9 @@ export default function DataGridView({
{props.canEdit && row.isExpanded &&
<FormView value={row.original} viewHelperProps={viewHelperProps} dataDispatch={dataDispatch}
schema={schemaRef.current} accessPath={accessPath.concat([row.index])} isNested={true} className={classes.expandedForm}
isDataGridForm={true}/>
isDataGridForm={true} firstEleRef={(ele)=>{
requestAnimationAndFocus(ele);
}}/>
}
</React.Fragment>;
})}

View File

@ -324,7 +324,11 @@ export default function FormView({
let currentControl = <MappedFormControl
inputRef={(ele)=>{
if(firstEleRef && firstEleID.current === field.id) {
firstEleRef.current = ele;
if(typeof firstEleRef == 'function') {
firstEleRef(ele);
} else {
firstEleRef.current = ele;
}
}
}}
state={value}

View File

@ -574,3 +574,23 @@ export function gettextForTranslation(translations, ...replaceArgs) {
return rawTranslation;
}
}
// https://developer.mozilla.org/en-US/docs/Web/API/Window/cancelAnimationFrame
const requestAnimationFrame =
window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame;
const cancelAnimationFrame =
window.cancelAnimationFrame || window.mozCancelAnimationFrame;
/* Usefull in focussing an element after it appears on the screen */
export function requestAnimationAndFocus(ele) {
if(!ele) return;
const animateId = requestAnimationFrame(()=>{
ele?.focus?.();
cancelAnimationFrame(animateId);
});
}