Wednesday, December 17, 2008

Building a simple Dirty State Page in .Net with AJAX

I was building a small internal application for my company as a pilot application that tests the Business Object framework we had just built. This web application could well serve as a useful too.

And now I wanted to try out a simple dirty state page – a page that tracks any changes made to it and notifies accordingly to the user. With AJAX extensions, I know it was possible, there are options to extend and create your own control - like a DirtyStateUpdatePanel or something. Anyways, I just wanted to try a basic version - so here is the simple version that I came up with. Consider this as a work done for a proof of concept.

DISPLAY
We need something to notify that the page has become dirty – even a div tag should be suffice
<div id="DirtyStateNotifyDivCtl" class="dirtyPanel" runat="server">div>

CONTROLS AND EVENTS
We need to notify if any of the bound controls have changed – we should be fine with each control’s changed event. Additionally we need them all to perform one common function – notify a dirty state change. So we can have our own event declared

Public Event DirtyStateChangedEvent(ByVal getDirtyStateMethod As IDirtyPage.GetDirtyState) Implements IDirtyPage.DirtyStateChangedEvent

And its handler:

    Protected Sub ValueChanged(ByVal getDirtySateMethod As IDirtyPage.GetDirtyState) Handles Me.DirtyStateChangedEvent

        With Me.DirtyStateNotifyDivCtl

            If getDirtySateMethod.Invoke() Then

                .InnerText = "*Unsaved Changes"

            Else

                .InnerText = " "

            End If

        End With

    End Sub

And a cheeky way to expose the raise event from Master Page:

    Public Sub RaiseDirtyStateEvent(ByVal getDirtyStateMethod As IDirtyPage.GetDirtyState)

        RaiseEvent DirtyStateChangedEvent(getDirtyStateMethod)

    End Sub

POSTBACK
We need to get all our controls wrapped into an UpdatePanel to “Ajaxify” things.

DETERMINE IF DIRTY
We can wire up the page controls to one common event handler (you can have as many event handlers). And pass in a delegate of a GetDirtyState method and let the Master page take care of the display of the Unsaved change text – or clear the unsaved change text.

    Protected Sub Page_DirtyStateChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles EndDateTxtCtl.TextChanged, StartDateTxtCtl.TextChanged

        Me.MasterPage.RaiseDirtyStateEvent(AddressOf Me.GetDirtyState)

    End Sub

 

    Public Function GetDirtyState() As Boolean

        ' TODOK: loop through your controls and find out if the page has become dirty by any chance

        If Me.EndDateTxtCtl.Text <> Me.TeamProject.EndDate Then

            Return True

        Else

            Return False

        End If

 

    End Function

And the icing on the cake would be the following:
<script language="javascript" type="text/javascript">

window.onbeforeunload = confirmIfDirty;

function confirmIfDirty(){

    if(document.getElementById('ctl00_DirtyStateUpdatePanelCtl').innerText > "")    {

        event.returnValue = "There are some unsaved changes. Navigating away from this page would cause such data to be lost.";

    }

}

script>

The slick onbeforeunload event pops up every time the user tries to navigate away from the page leaving it dirty.

You can find the sample files here.

 

No comments: