0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2025-01-06 22:10:10 -05:00

Allow same-page navigations on form posts (#9055)

* Allow same-page navigations on form posts

* Add another comment
This commit is contained in:
Matthew Phillips 2023-11-10 11:23:31 -05:00 committed by GitHub
parent 1bc3319686
commit f105b1002b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 43 additions and 2 deletions

View file

@ -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);

View file

@ -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>

View file

@ -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);
});
});

View file

@ -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