23 October, 2012

Warning a user that the form has changed - Tabular Form Style.

Quite some time ago, I wrote a quit tip about How to Warn a User That the Form Has Changed. The gist of the post was this:
"It's a common problem. A user spends time entering data into a form and then, for some reason, clicks a button or tab that will navigate away from the form without saving his data. Wouldn't it be nice if there were a way to warn the user that the data hasn't been saved, and that they may lose their work? "
The original solution used JavaScript to do the following:

create and set a flag at the page level
register an onchange event against all of the fields in the APEX form that sets the flag any time a value is changed
register with the page onbeforeunload event to check to see if the flag had been set and pop-up a warning if it has been

The original script worked well for a standard form but I had never tested it agains a tabular form.  Well, someone else had, and let me know that it really didn’t work.

As you can imagine, there are a lot of moving parts in a tabular form, especially now with APEX 4. The original script would have registered onchange events against every item on the form whether it was user editable or not.  That obviously would’t work for a tabular form as there are some JavaScript events that fire and change some of the hidden items.

After thinking about this for bit, I finally realized that instead of registering onchange events against every item on the tabular form, only the items that are user editable should be registered. If you look at the editable items, the id of each will conform to the following format:  f99_9999

So the key was to register only those items who’s id conforms to that format.  To do that the JavaScript match function and regular expressions can be used for this purpose.

The following JavaScript is the key. You can include it either in the HTML HEADER of the page, or in an HTML Region on the page:

<script type="text/javascript">

function onChangeinit() {

// This function sets up those fields which should
// trigger the "Are You Sure" Popup box upon navigating
// away from the page.

// First set up the array of elements in the form
// This method uses JavaScript to create an array of elements.
 var fields = document.getElementById('wwvFlowForm').elements;

// Now loop through the array and see if the id matches the format f99_9999
// If it does,  assign the on-change event.
// The onchange function sets the value of a JavaScript variable
// to '1' to show that something has changed.

 for (var i=0; i<fields.length; i++)

   if (fields[i].id.match('^f[0-9]{2}_{1}[0-9]{4}$'))
     $x(fields[i]).onchange = function () {window.unsaved=1;}

// Now Set up the UNSAVED variable
// and the function that checks it on UNLOAD.
window.unsaved = '';
window.onbeforeunload = function() {
return window.unsaved ? 'There may be unsaved changes to your data.' : undefined;

// And you're done.

The onChangeinit JavaScript function needs to be run whenever the page loads. To do that, we call it by placing the following JavaScript in the Execute when Page Loads attribute at the page level.


Finally, we want to provide a way to short circuit this for instances where we want them to be able to press a button without getting the message. The most common example of this would be the SAVE button. Again, you can include it either in the HTML Header of the page, or in an HTML Region on the page.

<script type="text/javascript">

function preSubmit() {

// Call this before any action where you want the user
// to be able to navigate without the warning message.


The last thing to do is edit any buttons that we want to be able to submit the page without being warned and make sure they call the preSubmit JavaScript function.

To make this change to SUBMIT buttons, edit the button and do the following:

In the Action When Button Pressed region, change the Action to Redirect to URL
in the URL Target enter the following:  javascript:preSubmit();apex.submit('SUBMIT');

Make sure the that ‘SUBMIT’ in the code above is actually the name of the button that you’re editing. That way when the apex.submit JavaScript function is called, it will be as if the user pressed the button.

For the DELETE buttons, edit the button and do the following:

In the Action When Button Pressed region, change the Action to Redirect to URL
in the URL Target enter the following:  javascript:preSubmit();apex.confirm(htmldb_delete_message,'MULTI_ROW_DELETE');

Again, make sure the that ‘MULTI_ROW_DELETE’ in the code above is actually the name of the button that you’re editing.

Once all of these things are put together, this should work nicely with tabular forms.

Hope this help some of you out, and as always comments are encouraged.


Bill said...

After trying many other methods of removing the javascript popup window, this one finally did it, EXCEPT it seems to have removed he warning completely. Making a change to the form and clicking on any different link will discard the changed data and switch to the page without a warning. The submit, delete, and add buttons do work as intended though. Do you know of any way to get the warning back for everything that isn't one of the buttons?

Steve Maxwell said...

Great article Doug. I found your method easy to understand and implement. One small thing that I noticed is that if you add a new tabular form row, it does not detect changes in that row. The issue was easy to overcome though by simply calling a function to set window.unsaved to 1 before the addRow() function.

Anonymous said...

I just googled across this 2-year old post, and it was exactly what I needed. Thank you!

Anonymous said...

This is a wonderful post and exactly what I want except for one issue.
I have a button which doesnot submit the page but instead it opens up a popup window(another page).But when I update a record and click on the button without saving ,message is not displayed.
What can be done for the same?


Doug Gault said...


If I understand you correctly, you want to warn the user before the pop-up is shown. To do that you'll have to inject some JavaScript that checks the value of the window.unsaved variable to see if it's '1' before you pop open the window.

Hope this helps.

Doug Gault said...

To answer Bill's question.

The way the example is executed (Using the window.onbeforeunload event), it should catch any navigation away from the page that doesn't call the preSubmit() function.

I don't know why this might not be happening in your case. If you can reproduce this on apex.oracle.com, I'd be happy to look at it.

Sankul said...

Very useful article and I have implemented in one of the applications developed.
But I have a small issue. When the above code is implemented,the select list with pagination does not work in the tabular form.
ie,If I have 60 records in the tabular form and I have defined to display 20 records at a time.
The first time I select rows 21-40,the tabular region does not get me the next set of records.If I click 'Next' Button and then it moves to the next set of records.Once I am in the rows 21-40,then the select list works.

If I remove the below code $x(fields[i]).onchange = function () {
then it works.

Kindly advise on how I can get the Select List with Pagination work.

Thank You in Advance.


Anonymous said...

thnx Doug!
still a helpfull post in 2015 and apex5 )
kind regards,


Nivetha said...

Hi Doug,
The post is very much helpful. Thank you.
Its working perfectly now,but I need to change the message and header name in the pop-up box, also the color of the box.
i.e. I have the following requirements:

1.Confirm Navigation must be changed to "Unsaved Data"
2.Message Content needs to be changed.
3."Prevent this page from creating additional dialog" check box must not come
4."Leave this page", "Stay on this page" button names should be modified.

Is there any possible way to achieve this?

Thanks in Advance.

Doug Gault said...


Let me address your questions 1 by 1.

1. Confirm Navigation must be changed to "Unsaved Data"

This is actually an artifact of the browser you are using. Because of the message you're getting, I can tell you're using CHROME, but if you were to run this in FireFox, there would be no heading message.

2. Message Content needs to be changed.

The message content is set in the onChangeinit function. You can see and change it there.

3."Prevent this page from creating additional dialog" check box must not come
4."Leave this page", "Stay on this page" button names should be modified.

Both 3 and 4 are also artifacts of the browser and cannot be changed.

If you want to take things into your own hands, you could try to create your own JQUERY modal dialog instead of using the browser defaults. This would make things a bit more complicated but you then would have full control over the look/feel and the verbiage used in the window and the buttons.

Hope this helped.

Nivetha said...

Hi Doug,

Thanks for the suggestion.
As you suggested, I have created my own JQUERY modal dialog alert with my own message and buttons and its working perfect.
The problem is, this alert has to pop up on click of Next and Previous buttons in the tabular form pagination.There is no ID for these buttons.

Is there anyway to call these buttons for On Click action?
Iam using APEX 5



Doug Gault said...


You are correct that the pagination items (rendered automatically by APEX) don't have an ID, but they do have CSS Classes you can use to identify them. You should be able to use JavaScript to attach an "onclick" event listener to the NEXT and PREVIOUS anchor tags.

Hope this helps.