The problemYou have a form on which users enter data and then save it through a Save button. If at some point they have data they have just entered, but haven't saved it yet, and they navigate away from the page—say by closing the current tab or window, clicking on a bookmark or a link—their latest changes to the form won't be saved, and will be lost. When that happens, you would like to warn users and give them a chance to stay on the form so they can save their changes.![]() The solution If you are creating a form with Form Builder, the runtime for your form (Form Runner) does this automatically for you, and there is nothing you need to worry about. What follows applies to XForms you write "by hand" if you're not using Form Builder and/or Form Runner.Maintaining a "data safe" flagYou don't want that message to show every time users navigate away from the page, but only if users have unsaved data. You do this by setting a flag totrue when users change something in the form, and setting it to false when they save. Let's assume you have an instance just for that purpose:<xforms:instance id="data-safe"> <data-safe>true</data-safe></xforms:instance>Let's assume you have a registration form, and the data users enter goes into an instance id registration. You want to watch that instance and if there are any changes, set the data-safe flag to false. You do this with the following, placed inside your xforms:model:<xforms:action ev:observer="registration" <xforms:setvalue ref="instance('data-safe')">false</xforms:setvalue></xforms:action>Similarly, when users save the data, you want to set that flag to true. The following button does just that (any only that—obviously, in a real scenario, you'll also want to actually save the data):<fr:button> <xforms:label>Save</xforms:label> <xforms:setvalue ev:event="DOMActivate" ref="instance('data-safe')">true</xforms:setvalue></fr:button>Showing an alertThe mechanism provided by the browser to show an alert uses JavaScript. You need to assign a function to window.onbeforeunload,
and when users navigate away from the page, that function is called. If
the function returns a string, that message is displayed to users in an
OK/Cancel type of alert box, giving them a chance to stay on the
current page. But first, that JavaScript code needs to be able to access the data-safe instance. You do this through an xforms:output you add to the view:<xforms:output ref="instance('data-safe')" id="data-safe-input" style="display: none"/>That xforms:output as a style display: none, as you don't want it to be visible to users; you just want to be able to access its value with JavaScript. You register a function on window.onbeforeunload, and test on the value of data-save with the following, placed in your model: |
