Skip to content

Commit

Permalink
Allow same-page navigations on form posts (#9055)
Browse files Browse the repository at this point in the history
* Allow same-page navigations on form posts

* Add another comment
  • Loading branch information
matthewp authored Nov 10, 2023
1 parent 1bc3319 commit f105b10
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 2 deletions.
3 changes: 2 additions & 1 deletion packages/astro/components/ViewTransitions.astro
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ const { fallback = 'animate', handleForms } = Astro.props;

const form = el as HTMLFormElement;
const formData = new FormData(form);
let action = form.action;
// Use the form action, if defined, otherwise fallback to current path.
let action = form.action ?? location.pathname;
const options: Options = {};
if (form.method === 'get') {
const params = new URLSearchParams(formData as any);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
import Layout from '../components/Layout.astro';
if(Astro.request.method === 'POST') {
const formData = await Astro.request.formData();
const name = formData.get('name');
return Astro.redirect(`/form-response?name=${name}`);
}
---
<Layout>
<h2>Contact Form</h2>
<h3>This form does not have an `action` defined</h3>
<form method="post">
<input type="hidden" name="name" value="Testing">
<input type="submit" value="Submit" id="submit">
</form>
</Layout>
22 changes: 22 additions & 0 deletions packages/astro/e2e/view-transitions.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -982,4 +982,26 @@ test.describe('View Transitions', () => {
]);
expect(reqUrls).toContainEqual('/one');
});

test('form POST with no action handler', async ({ page, astro }) => {
const loads = [];
page.addListener('load', async (p) => {
loads.push(p);
});

await page.goto(astro.resolveUrl('/form-two'));

let locator = page.locator('h2');
await expect(locator, 'should have content').toHaveText('Contact Form');

// Submit the form
await page.click('#submit');
const span = page.locator('#contact-name');
await expect(span, 'should have content').toHaveText('Testing');

expect(
loads.length,
'There should be only 1 page load. No additional loads for the form submission'
).toEqual(1);
});
});
3 changes: 2 additions & 1 deletion packages/astro/src/transitions/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -463,9 +463,10 @@ export function navigate(href: string, options?: Options) {
}
const toLocation = new URL(href, location.href);
// We do not have page transitions on navigations to the same page (intra-page navigation)
// *unless* they are form posts which have side-effects and so need to happen
// but we want to handle prevent reload on navigation to the same page
// Same page means same origin, path and query params (but maybe different hash)
if (location.origin === toLocation.origin && samePage(toLocation)) {
if (location.origin === toLocation.origin && samePage(toLocation) && !options?.formData) {
moveToLocation(toLocation, options?.history === 'replace', true);
} else {
// different origin will be detected by fetch
Expand Down

0 comments on commit f105b10

Please sign in to comment.