Skip to content

Commit

Permalink
Add option to disable turbo for form or optin to forms.
Browse files Browse the repository at this point in the history
In large application upgrading from turbolinks to turbo requires all
forms that use `render` to return validations errors needs to be
updated with `status: :unprocessable_entity` to as in 4670f2b to.
This makes it hard to upgrade as you ether have to have a single PR that
upgrades all form (when you have over 400 forms is pretty risky) or
disable all forms which again can be risky if you miss one before
completing the upgrade.

There are options but it would be great if you can could do this in
turbo and save hours of work.

To allow this I've added a `formMode` to the session so you can change
the behaviour of turbo and how it interacts with forms.

The mode is set via the `Tubro.setFormMode` option and can be set to one
of 3 options:
- "on" all forms will be submitted with turbo, this is the default
- "off" forms will not be submitted with turbo
- "optin" forms by default will not be submitted with turbo unless the
  form is annotated with `data-turbo="true"` attribute.

Adding these options will allow user of turbo to decide how forms should
work and make upgrading easier.
  • Loading branch information
pythonandchips committed May 9, 2022
1 parent ce9cbff commit 4b738d4
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 1 deletion.
4 changes: 4 additions & 0 deletions src/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,7 @@ export function setProgressBarDelay(delay: number) {
export function setConfirmMethod(confirmMethod: (message: string, element: HTMLFormElement) => Promise<boolean>) {
FormSubmission.confirmMethod = confirmMethod
}

export function setFormMode(mode: string) {
session.setFormMode(mode)
}
16 changes: 15 additions & 1 deletion src/core/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export class Session
enabled = true
progressBarDelay = 500
started = false
formMode = "on"

start() {
if (!this.started) {
Expand Down Expand Up @@ -110,6 +111,10 @@ export class Session
this.progressBarDelay = delay
}

setFormMode(mode: string) {
this.formMode = mode
}

get location() {
return this.history.location
}
Expand Down Expand Up @@ -219,7 +224,7 @@ export class Session

return (
this.elementDriveEnabled(form) &&
(!submitter || this.elementDriveEnabled(submitter)) &&
(!submitter || this.formElementDriveEnabled(submitter)) &&
locationIsVisitable(expandURL(action), this.snapshot.rootLocation)
)
}
Expand Down Expand Up @@ -358,6 +363,15 @@ export class Session

// Helpers

formElementDriveEnabled(element?: Element) {
if (this.formMode == "off") { return false }
if (this.formMode == "optin") {
const form = element?.closest("form[data-turbo]")
return form?.getAttribute("data-turbo") == "true"
}
return this.elementDriveEnabled(element)
}

elementDriveEnabled(element?: Element) {
const container = element?.closest("[data-turbo]")

Expand Down
4 changes: 4 additions & 0 deletions src/tests/fixtures/form.html
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ <h1>Form</h1>
<input type="submit">
<button type="submit" name="greeting" id="secondary_submitter" data-turbo-confirm="Are you really sure?" formaction="/__turbo/redirect?path=/src/tests/fixtures/one.html" formmethod="post" value="secondary_submitter">Secondary action</button>
</form>
<form action="/__turbo/submit" method="post" data-turbo="true" class="turbo-enabled">
<input type="hidden" name="query" value="2">
<input type="submit">
</form>
</div>
<hr>
<div id="no-action">
Expand Down
21 changes: 21 additions & 0 deletions src/tests/functional/form_submission_tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -858,6 +858,27 @@ export class FormSubmissionTests extends TurboDriveTestCase {
this.assert.equal(await message.getVisibleText(), "Link!")
}

async "test form submission with form mode off"() {
await this.remote.execute(() => window.Turbo.setFormMode("off"))
await this.clickSelector('#standard form.turbo-enabled input[type=submit]')

this.assert.notOk(await this.formSubmitStarted)
}

async "test form submission with form mode optin and form not enabled"() {
await this.remote.execute(() => window.Turbo.setFormMode("optin"))
await this.clickSelector('#standard form.redirect input[type=submit]')

this.assert.notOk(await this.formSubmitStarted)
}

async "test form submission with form mode optin and form enabled"() {
await this.remote.execute(() => window.Turbo.setFormMode("optin"))
await this.clickSelector('#standard form.turbo-enabled input[type=submit]')

this.assert.ok(await this.formSubmitStarted)
}

async "test turbo:before-fetch-request fires on the form element"() {
await this.clickSelector('#targets-frame form.one [type="submit"]')
this.assert.ok(await this.nextEventOnTarget("form_one", "turbo:before-fetch-request"))
Expand Down

0 comments on commit 4b738d4

Please sign in to comment.