Skip to content

InPlaceEditor ignores blur when focus moves outside the editor #11303

Description

@ClarenceChoo

What you were expecting:

When an <InPlaceEditor> loses focus, it should save the edited value. When cancelOnBlur is set, it should cancel the edit instead.

This matches the documented behavior: the field is saved automatically when the user clicks outside it, and the cancelOnBlur prop changes that behavior to cancel.

What happened instead:

If focus moves to another focusable element (for example, a neighboring button, link, or input), the editor stays open and the value is neither saved nor canceled.

The current blur handler returns whenever event.relatedTarget is non-null. Browsers set relatedTarget to the element receiving focus, so the save/cancel logic is skipped for normal Tab navigation and clicks on focusable controls.

Steps to reproduce:

  1. Render an InPlaceEditor followed by a focusable control.
  2. Click the field to enter edit mode.
  3. Change its value.
  4. Press Tab to move to the next control, or click that control.
  5. Observe that the editor remains in edit mode and no update occurs.
<>
    <InPlaceEditor source="name" />
    <button>Next</button>
</>

A focused test also reproduces the issue:

const input = await screen.findByDisplayValue('John Doe');
fireEvent.change(input, { target: { value: 'Jane Doe' } });

const nextButton = screen.getByRole('button', { name: 'Next' });
fireEvent.blur(input, { relatedTarget: nextButton });

await screen.findByText('Jane Doe'); // times out; the input remains open

Related code:

handleBlur currently exits for every non-null relatedTarget:

if (event.relatedTarget) {
    return;
}

The guard likely needs to distinguish focus moving within the editor (for example, to its Save/Cancel buttons) from focus moving outside the editor.

Documentation: https://marmelab.com/react-admin/InPlaceEditor.html

Other information:

The same problem affects cancelOnBlur: moving focus to another focusable element does not restore the initial value.

Environment

  • React-admin version: 5.15.1 / current master
  • Last version that did not exhibit the issue: N/A (the guard is present in the initial InPlaceEditor implementation)
  • React version: 18.3.1
  • Browser: Reproduced at the React event level with standard browser FocusEvent.relatedTarget behavior
  • Stack trace: N/A

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions