Checking a form to see if it has 'dirty' fields:
As I was thinking about what I should start my first ‘tech-article’ with, one of our Project Managers came up with a God-sent topic. He mentioned how his team had coded the entire application and now the client wanted a change in the navigation mechanism. They wanted that in case the user edited any field on that page, he should be prompted with a warning prompting that all changes the user made would be lost. For this they wanted a client side script to find out in case any ASP.NET control on that page had been fiddled with. They did not need to know which control it was as long as its value had changed at least once. This was needed irrespective of what control it was.. radio button, text box, label, check-box etc. It took me about
<o:p>
<o:p>
So in this article, I’ll talk about how to detect client side changes to a web-form coded in ASP.NET. Well the solution really isn’t difficult as it took me just around an hour to get them to the best approach, but since my PM (who’s a tech guru himself ) didn’t know it, I thought I might as well start with the same
<o:p>
So in a sample application to demonstrate the solution, lets create a ‘default.aspx’ file with the following form
<o:p>
<body><o:p>
<form id="form1" runat="server" ><o:p>
<div><o:p>
<asp:TextBox ID="txtCtrlOne" runat="server"></asp:TextBox><o:p>
<o:p>
<asp:CheckBox ID="chkCtl2" runat="server" /><o:p>
<o:p>
<o:p>
<asp:RadioButton ID="rdbCtl3" runat="server" /><o:p>
<o:p>
<asp:Label ID="lblCtl4" runat="server" Text="Label"></asp:Label><o:p>
<asp:Button ID="btnSubmit" runat="server" Text="Button" /><o:p>
</div> <o:p>
</form><o:p>
</body><o:p>
<o:p>
<o:p>
Now, we’ll need to invoke some client side scripts that’ll need to go in the head tag as shown below:
<o:p>
<head runat="server"><o:p>
<title>Test Page for Demo</title><o:p>
<script language="javascript" type="text/javascript" > <o:p>
var _boolFlag;<o:p>
function resetFlag()<o:p>
{<o:p>
_boolFlag=false;<o:p>
}<o:p>
<o:p>
function setFlag()<o:p>
{<o:p>
_boolFlag=true;<o:p>
}<o:p>
<o:p>
function checkFlag()<o:p>
{<o:p>
if( _boolFlag == true )<o:p>
{<o:p>
alert('Some data in this form has changed. Its dirty!!'); <o:p>
} <o:p>
} <o:p>
<o:p>
</script><o:p>
</head><o:p>
<o:p>
Essentially, we use a Boolean flag to indicate if the form has changed from what we received or not. Now comes the meat part, what do we do at the server side that we get the appropriate java-script functions called when required. Well, nothing great – we just add some attributes to the rendered controls for these ASP.NET controls. The basic idea is that, ASP.NET renders its controls ultimately as pure HTML (coz that’s what your browser will understand finally), so using the WebControl.Attributes collection for these control we can set the ‘onpropertychange’ event to call the setFlag() javascript method that ultimately sets the Boolean flag to mark the page as dirty. Here is the default.aspx.cs
<o:p>
using System;<o:p>
using System.Data;<o:p>
using System.Configuration;<o:p>
using System.Web;<o:p>
using System.Web.Security;<o:p>
using System.Web.UI;<o:p>
using System.Web.UI.WebControls;<o:p>
using System.Web.UI.WebControls.WebParts;<o:p>
using System.Web.UI.HtmlControls;<o:p>
<o:p>
public partial class _Default : System.Web.UI.Page <o:p>
{<o:p>
protected void Page_Load(object sender, EventArgs e)<o:p>
{<o:p>
if (!IsPostBack)<o:p>
{<o:p>
//normally here is where some logic would set values on the page<o:p>
txtCtrlOne.Text = "Someone Somewhere is testing code ";<o:p>
chkCtl2.Checked = true;<o:p>
}<o:p>
//after that we set out client side script attributes<o:p>
<o:p>
form1.Attributes["onload"] = "return resetFlag();";<o:p>
txtCtrlOne.Attributes["onpropertychange"] = "return setFlag();";<o:p>
chkCtl2.InputAttributes["onpropertychange"] = "return setFlag();";<o:p>
rdbCtl3.InputAttributes["onpropertychange"] = "return setFlag();";<o:p>
btnSubmit.Attributes["onclick"] = "return checkFlag();";<o:p>
<o:p>
}<o:p>
}<o:p>
The reason we use ‘InputAttributes’ for the checkboxes and radio-buttons is that, I realized that using the ‘Attributes’ collection resulting in .NET dumping a the “onpropertychange” attribute in a ‘span’ tag around the radio button or check box and not within the RB or CB. So I changed it to InputAttributes and it worked!!
<o:p>
For those lazy people (like myself) who’ll need the default.aspx file as well, here it is.
<o:p>
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><o:p>
<o:p>
<html xmlns="http://www.w3.org/1999/xhtml" ><o:p>
<head runat="server"><o:p>
<title>Test Page for Demo</title><o:p>
<script language="javascript" type="text/javascript" > <o:p>
var _boolFlag;<o:p>
function resetFlag()<o:p>
{<o:p>
_boolFlag=false;<o:p>
}<o:p>
<o:p>
function setFlag()<o:p>
{<o:p>
alert("flag set");<o:p>
_boolFlag=true;<o:p>
}<o:p>
<o:p>
function checkFlag()<o:p>
{<o:p>
if( _boolFlag == true )<o:p>
{<o:p>
alert('Some data in this form has changed. Its dirty!!'); <o:p>
} <o:p>
} <o:p>
<o:p>
</script><o:p>
</head><o:p>
<body><o:p>
<form id="form1" runat="server" ><o:p>
<div><o:p>
<asp:TextBox ID="txtCtrlOne" runat="server"></asp:TextBox><o:p>
<o:p>
<asp:CheckBox ID="chkCtl2" runat="server" /><o:p>
<o:p>
<o:p>
<asp:RadioButton ID="rdbCtl3" runat="server" /><o:p>
<o:p>
<o:p>
<asp:Button ID="btnSubmit" runat="server" Text="Button" /><o:p>
</div> <o:p>
</form><o:p>
</body><o:p>
</html><o:p>
<o:p>
The code in the if( !IsPostBack ) condition is where you’d normally write some logic to get the values from your business layer to populate your form fields, so its just a simulation.
<o:p>
<o:p>
In case you want you can use the event within javascript to determine which control fired the event and what property was changed as well. But since that’s not my PM’s requirement, so I’d leave that upto you. So that completes my first blog-post. Its pretty dumb I know…. but at least I started J.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.