Skip to content

Commit

Permalink
Fix missing form data when the submitter is outside the form
Browse files Browse the repository at this point in the history
Fixes facebook#27391

`form-associated elements` can be associated with `<form>`s anywhere in the document (even if the element is outside the `<form>`), and just like regular submitters, their name and value are expected to be reflected in the final `FormData`.
  • Loading branch information
jupapios committed Jan 23, 2024
1 parent 2f803b4 commit ee2685a
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ function extractEvents(
const temp = submitter.ownerDocument.createElement('input');
temp.name = submitter.name;
temp.value = submitter.value;
const isOutsideForm = !form.contains(submitter);
if (isOutsideForm) {
temp.setAttribute('form', form.id);
}
(submitter.parentNode: any).insertBefore(temp, submitter);
formData = new FormData(form);
(temp.parentNode: any).removeChild(temp);
Expand Down
30 changes: 23 additions & 7 deletions packages/react-dom/src/__tests__/ReactDOMForm-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,7 @@ describe('ReactDOMForm', () => {
it('can read the clicked button in the formdata event', async () => {
const inputRef = React.createRef();
const buttonRef = React.createRef();
const outsideButtonRef = React.createRef();
let button;
let title;

Expand All @@ -494,14 +495,24 @@ describe('ReactDOMForm', () => {
const root = ReactDOMClient.createRoot(container);
await act(async () => {
root.render(
<form action={action}>
<input type="text" name="title" defaultValue="hello" />
<input type="submit" name="button" value="save" />
<input type="submit" name="button" value="delete" ref={inputRef} />
<button name="button" value="edit" ref={buttonRef}>
Edit
<>
<button
form="form"
name="button"
value="outside"
ref={outsideButtonRef}>
Edit from outside
</button>
</form>,
<form id="form" action={action}>
<input type="text" name="title" defaultValue="hello" />
<input type="submit" name="button" value="save" />
<input type="submit" name="button" value="delete" ref={inputRef} />
<button name="button" value="edit" ref={buttonRef}>
Edit
</button>
</form>
,
</>,
);
});

Expand All @@ -522,6 +533,11 @@ describe('ReactDOMForm', () => {
expect(button).toBe('edit');
expect(title).toBe('hello');

await submit(outsideButtonRef.current);

expect(button).toBe('outside');
expect(title).toBe('hello');

// Ensure that the type field got correctly restored
expect(inputRef.current.getAttribute('type')).toBe('submit');
expect(buttonRef.current.getAttribute('type')).toBe(null);
Expand Down

0 comments on commit ee2685a

Please sign in to comment.