0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2024-12-16 21:46:22 -05:00

Respect forms with enctype set for view transitions

This commit is contained in:
Ken Powers 2023-12-18 19:16:04 -05:00
parent 429be8cc3e
commit 6d3e04a959
4 changed files with 22 additions and 11 deletions

View file

@ -117,7 +117,18 @@ const { fallback = 'animate' } = Astro.props;
url.search = params.toString();
action = url.toString();
} else {
options.formData = formData;
// Form elements without enctype explicitly set default to application/x-www-form-urlencoded.
// In order to maintain compatibility with Astro 4.x, we need to check the value of enctype
// on the attributes property rather than accessing .enctype directly. Astro 5.x may
// introduce defaulting to application/x-www-form-urlencoded as a breaking change, and then
// we can access .enctype directly.
//
// Note: getNamedItem can return null in real life, even if TypeScript doesn't think so.
const enctype = form.attributes.getNamedItem('enctype')?.value;
options.body =
enctype === 'application/x-www-form-urlencoded'
? new URLSearchParams(formData as any)
: formData;
}
ev.preventDefault();

View file

@ -66,7 +66,7 @@ export const isTransitionBeforePreparationEvent = (
value: any
): value is TransitionBeforePreparationEvent => value.type === TRANSITION_BEFORE_PREPARATION;
export class TransitionBeforePreparationEvent extends BeforeEvent {
formData: FormData | undefined;
body: FormData | URLSearchParams | undefined;
loader: () => Promise<void>;
constructor(
from: URL,
@ -76,7 +76,7 @@ export class TransitionBeforePreparationEvent extends BeforeEvent {
sourceElement: Element | undefined,
info: any,
newDocument: Document,
formData: FormData | undefined,
body: FormData | URLSearchParams | undefined,
loader: (event: TransitionBeforePreparationEvent) => Promise<void>
) {
super(
@ -90,7 +90,7 @@ export class TransitionBeforePreparationEvent extends BeforeEvent {
info,
newDocument
);
this.formData = formData;
this.body = body;
this.loader = loader.bind(this, this);
Object.defineProperties(this, {
formData: { enumerable: true },
@ -145,7 +145,7 @@ export async function doPreparation(
navigationType: NavigationTypeString,
sourceElement: Element | undefined,
info: any,
formData: FormData | undefined,
body: FormData | URLSearchParams | undefined,
defaultLoader: (event: TransitionBeforePreparationEvent) => Promise<void>
) {
const event = new TransitionBeforePreparationEvent(
@ -156,7 +156,7 @@ export async function doPreparation(
sourceElement,
info,
window.document,
formData,
body,
defaultLoader
);
if (document.dispatchEvent(event)) {

View file

@ -449,7 +449,7 @@ async function transition(
navigationType,
options.sourceElement,
options.info,
options.formData,
options.body,
defaultLoader
);
if (prepEvent.defaultPrevented) {
@ -460,9 +460,9 @@ async function transition(
async function defaultLoader(preparationEvent: TransitionBeforePreparationEvent) {
const href = preparationEvent.to.href;
const init: RequestInit = {};
if (preparationEvent.formData) {
if (preparationEvent.body) {
init.method = 'POST';
init.body = preparationEvent.formData;
init.body = preparationEvent.body;
}
const response = await fetchHTML(href, init);
// If there is a problem fetching the new page, just do an MPA navigation to it.
@ -488,7 +488,7 @@ async function transition(
// Unless this was a form submission, in which case we do not want to trigger another mutation.
if (
!preparationEvent.newDocument.querySelector('[name="astro-view-transitions-enabled"]') &&
!preparationEvent.formData
!preparationEvent.body
) {
preparationEvent.preventDefault();
return;

View file

@ -5,6 +5,6 @@ export type Options = {
history?: 'auto' | 'push' | 'replace';
info?: any;
state?: any;
formData?: FormData;
body?: FormData | URLSearchParams;
sourceElement?: Element; // more than HTMLElement, e.g. SVGAElement
};