Detecting Pending Changes in ASP.NET MVC

In this blog I am going to describe a pretty common problem that web applications have to deal with along with one way to solve this issue.

Here is the issue at hand.  Say, user pulled up an entry form and made some changes.  Then the above mentioned user clicked browser back button, navigating away from the current page, and thus loosing all the pending changes.  A friendly software application should warn the user, shouldn’t it?

So, how do we detect pending changes?  In typical desktop application, say the one that uses CSLA – http://lhotka.net/cslanet/, you can very easily check existing bound objects and see if there are pending changes.  CSLA, for example, takes a snapshot of business objects, then compare the snapshot to current state of the same object.  What if we could do the same?

To our benefit, there is a very useful function in jQuery, called serialize
http://api.jquery.com/serialize/

So, could we use that to solve the problem?  Let’s try something like

initialFormData = $(‘form’).serialize();

Seems pretty easy.  Now we need to create a JavaScript object that can help us to all the steps

  • Create snapshot of the data when it is loaded
  • Compare the snapshot to current data
  • Intercept navigation in progress and warn the user

I am going to create a brand new script file with my application in it, calling it App.js and define my object in it as following

if (!window.App) {
    window.App = {
        init:
function
() {
            window.onbeforeunload =
this
.onBeforeUnloadWindow;
           
this.initialFormData = $(‘form’
).serialize();
           
this.submitting = false
;
        },
        onBeforeUnloadWindow:
function
() {
           
return
window.App.hasPendingChanges();
        },
        submitting:
false
,
        initialFormData:
""
,
        hasPendingChanges:
function
() {
           
if (!window.App.submitting && 
                window.App.initialFormData !== $(
‘form’
).serialize()) {
               
return "You have pending changes. nrIf you leave current page, those changes will be lost."
;
            }
           
return
undefined;
        }
    };
}

Very quick and easy.  One small object, neatly organized that will do the work for me.  Now in my MVC application I locate _Layout.cshtml and include my script in the list of scripts.  The last step is to call init method on my App object after form loads, for example in Edit.cshtml:

<script type="text/javascript">
        window.App.init();
</script>

Now, if you try this solution, you will notice that your Save button does something strange.  It pops up the warning message for no reason.  So, we have to do one more thing in our Save button click event:

<input type="submit" onclick="window.App.submitting = true;" 
 
value=
@ViewBag.Action />

We have to let the App object know that we are navigating away because the user hit Save button.  That was our last step.  One of the guys on our team came up with this idea, and he and I refined it a bit to make the code cleaner.

Please let me know what you think.

Thanks.

5 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *