Tuesday, September 16, 2008

Add Scripts to Client Side Page 2

I have changed the ClientSidePage class. In the following articles, I'll use my updated class as examples. It is very easy to use the class, first use the ClientSidePage class as base class, and then use the base class method MonitorChanges() to add a web control for monitoring any changes.

For example, here is the code to add a textbox control for monitoring:

protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
base.MonitorChanges<TextBox>(MonitorChangeControl,
CONTROL_ID_MONITORCHANGECONTROL);
}
}

where MonitorChanges is a TextBox control placed on aspx page. It is directly accessible in the server-side code class, and CONTROL_ID_MONITORCHANGECONTROL is a constant defined in the server-side class. I prefer to define control ID in a region in a class so that can be be easily maintained in once place instead spread all over the places.

One change in the method is that it is a method with generic type T, where T is constrained with WebControl class. The first parameter is a web control or the parent control where a specified control can be found by control's ID. In some cases, you may place some web controls within a GridView's templates. Those controls cannot be directly accessible. You have find them by their parent container such as GridViewRow control. In this case, you can pass in the GridViewRow control.

With the method, I used another class to find a web control. This makes it easy to use. You don't need to add some codes to find the control. See my previous blog on Find a control in ASP.Net Page.

You can monitor as many web controls as you want. However, from my experiences, I found there are too many problems to directly monitor each editable web controls. Some times you don't know how many they. For example, a GridView control may be bound to a database with dynamical rows of data. As a result, it is very hard to maintain.

The second issue is you have to understand when to initialize these controls on the client side script. As I mentioned in my previous article, the ClientSidePage class registers two groups of scripts on client side page. One is the startup scripts, where the method assignInitialValuesForMonitorChanges() is called when the web page is loaded. However, some web controls may not have data values available in the first loading process if the control is bound to an object data source and the object will be created on server side codes. The control may be late postcalled back to set values. In this case, the client side array for initial values would be nulls. What I find out is that I have to call MonitorChanges at the time the control is bound to data on server side. Then I use another overloaded method to pass initial values to the client side script so that the array could be initialized with correct values.

protected void GridView_RowDataBound(object sender,
GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
GridViewRow row = e.Row;
base.MonitorChanges<CheckBox>(row,
CONTROL_ID_ISEMPLOYEECONTROL, true);
}
}

What I find out is that I don't need to monitor each web controls. What I need is to monitor only one TextBox control. It is initialized as empty. If any other control values are changed, this monitored control's value will be something like "Some data may have been changed. Click on Save button to confirm the changes".

In order to achieve this, I added two methods on ClientSidePage class. The first one is SetScriptOnClientSide(). This method will register two groups of scripts to client side in the same way as CliendSidePage does: a group script for starup and a group script for script block. These two groups of scripts are customized scripts with a customer provided registry key. This will make sure ClientSidePage registered scripts will not be conflict with customized scripts. You add whatever scripts you want to the client side.

SetControlEventScript(). This method takes three parameters, one for WelControl object, a string for an event attribute, a string for script, and a position to indicate where to add the script to the controls' event attribute if it has some scripts defined already.

Here is one example I use these methods in one aspx web page server side codes:

private void SetScriptsForClientSidePage()
{
string script;
/* Monitor one text box control: MonitorChangeControl with its control ID*/
base.MonitorChanges<TextBox>(MonitorChangeControl,
CONTROL_ID_MONITORCHANGECONTROL);
script = @"
<script language=""JavaScript"">
function {0}
{
var v_elem = document.getElementById('{1}');
if ( v_elem )
{
v_elem.value = '{2}';
}
}
</script>
"
.Replace("{0}", SCRIPT_FUNC_SomeValueChanged) /* constant for function name: "SOmeValueChaned()" */
.Replace("{1}", MonitorChangeControl.ClientID)
.Replace("{2}", SCRIPT_CHANGE_MESSAGE); /* Message like "Some data may have been changed. Click on Save button to confirm changes or click on Cancel to revoke changes." */
base.SetScriptOnClientSide("script", null, script);

/*Add scripts for one text box control: CurrentSales */
script = string.Format("{0};",
SCRIPT_FUNC_SomeValueChanged);
string eventOnChange = "onchange";
ScriptInsertPosition pos =
ScriptInsertPosition.BeforeExistingScrit;
base.SetControlEventScript(CurrentSales,
eventOnChange, script, pos);
}

This private method is called in the Page_Load() event when the page is first time loaded: monitoring one text box control, adding client side script with a script function definition, and adding event script for a web control. After done this, I always to view the client side source to verify my scripts.

The next article will provide the codes of ClientSidePage class.

0 comments: