[Help Needed] Preventing LiveView Navigation When Form is Dirty

Hello Elixir community,

Introduction: I am in the process of developing a web application using Phoenix LiveView. One of the critical pages in this application contains a form.

Objective: I’m looking to enhance the user experience by preventing unintentional navigation away from this form page. Specifically, if a user starts filling out the form and then attempts to leave the page without saving (either by clicking elsewhere or interacting with the navigation menu), I want to present them with a confirmation box. This is to ensure that users don’t inadvertently lose the data they’ve inputted.

Attempts Made: To handle this, I’ve added a Javascript hook that utilizes the beforeunload event to inhibit window reloads. This solution is effective in preventing reloads or when switching to another LiveView. However, I’ve encountered issues with other types of navigation, particularly push state navigations. I tried to address this by setting up an event listener for the popstate event, but found that the event isn’t even being triggered.

Current Issue/Blocker: My challenge is twofold:

  1. The beforeunload event doesn’t prevent other push state navigations.
  2. The popstate event doesn’t seem to be firing, and I’m unsure why.

Desired Outcome: I wish to not only prevent page reloads but also inhibit any other navigation between different LiveView pages when the form is in a “dirty” state.

Additional Information:

  • Phoenix version: v1.7.7

I’d be extremely grateful for any insights or solutions to this issue. Your collective expertise has been invaluable to my journey in Elixir, and I thank you in advance for your guidance.

1 Like

What I do is set an @changed? assign in my socket in an on_mount hook, and pass that to my FormComponent’s through the parent. Then in my handle_event call for validation in the form, I check to see if the changeset has any changes, and notify the parent which sets the @changed? assign to true.

Then I add some logic around a data-changed attribute attached to the phx-key and modal close button to complain if you attempt to close the modal when there are changes in the form.

This doesn’t handle the reload/navigate cases, but that’s how I handle it on the Phoenix side. Your method for hooking onbeforeunload and friends is interesting and looks like more pieces to the puzzle.

A Javascript hook would be a more encompassing solution to this problem, though I haven’t really thought about how that would work between detecting changes and such, but you could check JavaScript interoperability — Phoenix LiveView v0.19.5 heading Event Listeners to handle the push edge cases and listen to the page loading events.

1 Like