[6.x] Dirty state fixes#14592
Merged
jasonvarga merged 3 commits into6.xfrom May 1, 2026
Merged
Conversation
Closes #14055 Intercept popstate in `dirty-state.js` before Inertia's listener so back/forward navigation (including trackpad swipe gestures) prompts the user instead of silently discarding unsaved form changes.
Member
|
Lookin' ok but don't merge yet. Found a couple issues. |
Member
Author
|
By all means! |
Container.vue now removes its dirty entry in onUnmounted, which fixes the stale-state leak that caused subsequent link clicks to prompt for a form that no longer exists after a silent popstate-induced page swap. dirty-state.js captures the dirty URL/state on the 0->1 add() transition instead of via a global inertia:navigate listener, removing module-load state and an event listener. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #14055.
Three related fixes around dirty form state in the CP.
Browser back/forward now prompts on unsaved changes
Inertia's popstate handler swaps pages via
page.setQuietly(..., { preserveState: false })without firing itsinertia:beforeevent, sodirty-state.jsnever had a chance to warn.window.onbeforeunloaddoesn't fire for SPA history navigation either, which is why the trackpad swipe-back gesture (and the actual back/forward buttons) silently nuked unsaved form data.dirty-state.jsnow registers apopstatelistener at module load — beforecreateInertiaApp()callseventHandler.init()— so our handler runs first andstopImmediatePropagation()blocks Inertia from wiping the form. We capture the dirty page's URL/state on the 0→1add()transition (soconfirm()can keep the URL bar in place during the prompt and after a cancel). Confirm →history.back()into Inertia's normal flow; cancel → user stays put, form stays intact.Containercleans up its dirty entry on unmountPreviously, the dirty
refwas module-level state that outlived the form component. When Inertia silently swapped pages on popstate, the form was destroyed but its dirty entry remained — so the next InertiaLinkclick would prompt you about a form that didn't exist anymore.Container.vuenow callsclearDirtyState()inonUnmounted, which is the right place to remove an entry the Container itself added.disableWarning()actually allows re-enablingdisableWarning()called the unsubscribe but keptinertiaWarningListenerset to the (already-called) function, so the??=inenableWarning()would skip re-subscribing on the next dirty cycle. It now nulls the variable.