diff --git a/packages/fresh/src/runtime/client/partials.ts b/packages/fresh/src/runtime/client/partials.ts
index bd5d3b5665b..31eb59c0fec 100644
--- a/packages/fresh/src/runtime/client/partials.ts
+++ b/packages/fresh/src/runtime/client/partials.ts
@@ -231,12 +231,21 @@ document.addEventListener("submit", async (e) => {
return;
}
+ const hasExplicitPartial = e.submitter?.hasAttribute(PARTIAL_ATTR) ||
+ e.submitter?.hasAttribute("formaction") ||
+ el.hasAttribute(PARTIAL_ATTR) ||
+ el.hasAttribute("action");
+
const rawPartialUrl = e.submitter?.getAttribute(PARTIAL_ATTR) ??
e.submitter?.getAttribute("formaction") ??
el.getAttribute(PARTIAL_ATTR) ?? el.action;
const rawActionUrl = e.submitter?.getAttribute("formaction") ?? el.action;
- if (rawPartialUrl !== "") {
+ // Only intercept forms that explicitly opt in to partial navigation
+ // via f-partial, formaction, or an explicit action attribute. Without
+ // this check, every form inside f-client-nav would be intercepted
+ // because el.action is always non-empty (defaults to the current URL).
+ if (hasExplicitPartial && rawPartialUrl !== "") {
e.preventDefault();
const partialUrl = new URL(rawPartialUrl, location.href);
diff --git a/packages/fresh/tests/partials_test.tsx b/packages/fresh/tests/partials_test.tsx
index aae8420931f..03137f91deb 100644
--- a/packages/fresh/tests/partials_test.tsx
+++ b/packages/fresh/tests/partials_test.tsx
@@ -1857,6 +1857,49 @@ Deno.test({
},
});
+Deno.test({
+ name: "partials - form without action inside f-client-nav not intercepted",
+ fn: async () => {
+ const app = testApp()
+ .post("/", (ctx) => {
+ return ctx.render(
+
+ form submitted normally
+ ,
+ );
+ })
+ .get("/", (ctx) => {
+ return ctx.render(
+
+
+ ,
+ );
+ });
+
+ await withBrowserApp(app, async (page, address) => {
+ await page.goto(address, { waitUntil: "load" });
+ await page.locator(".init").wait();
+
+ // Form should do a full page navigation, not a partial update
+ await Promise.all([
+ page.waitForNavigation(),
+ page.locator(".update").click(),
+ ]);
+ await page.locator(".submitted").wait();
+ });
+ },
+});
+
Deno.test({
name: "partials - submit form redirect",
fn: async () => {