Friday, July 18, 2008

Use JavaScript on Controls in a GridView, DetailsView or FormView (even in a MasterPage with an UpdatePanel)

Ever want to use JavaScript on a Textbox inside a DetailsView? It can be done, you just need to overcome two issues. The first is that .Net will change the ID from "MyTextBox" to something like "ct100_ContentPlaceholder1_DetailsView1_MyTextBox". The second is that these controls may exist only in Edit or Insert mode.

The first thing we want to do is get the ID of MyTextbox that gets sent to the browser. Since MyTextbox only exists when we're editing or inserting, we need to use the PreRender event. We check to make sure we are in Edit/Insert mode and then use FindControl to get a handle on the textbox. Next we use the ScriptManager RegisterHiddenField method to register a hidden control that has the ClientID as its value.

Protected Sub DetailsView1_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles DetailsView1.PreRender
    If DetailsView1.CurrentMode = DetailsViewMode.Edit Or DetailsView1.CurrentMode = DetailsViewMode.Insert Then
        Dim txt As TextBox = DetailsView1.FindControl("MyTextbox")
        ScriptManager.RegisterHiddenField(DetailsUpdatePanel, "MyTextboxClientID", txt.ClientID)
    End If
End Sub

There's several important things to notice here. First, ScriptManager is used to register the hidden field since I'm assuming you are in an UpdatePanel. Look at ClientScript to add the hidden field if you're not using an UpdatePanel. Also, notice that I pass the UpdatePanel as the first parameter instead of the page.

Second, we dynamically register the hidden field. We don't use a HiddenField control because it will suffer from the same naming issue in a MasterPage.

Third, the hidden field is named MyTextboxClientID. We'll need that name in the JS to get our control. The following function takes the name and returns the control. If the hidden field or the control aren't present, it returns null. This keeps an error from getting thrown when we're not in Edit/Insert mode.

// Gets a contained control from a
// hidden field.
// name - The name of the hidden field
//        that has the ClientID name.
function GetContainedControl(name)
{
    var hdn = document.getElementById(name);
    if (hdn!=null)
        {return document.getElementById(hdn.value);}
    return null;
}

Here's how to call GetContainedControl. Notice we pass the name of the hidden field and not the name of the control we want to find. We check to see if it's null and we're ready to go.

var txt = GetContainedControl("MyTextboxClientID")
if (txt != null)
{
    // Do stuff here
}

Lastly, I'd recommend using constants for these names so that you don't get a name mismatch between the code behind and the JS. Here's the revised lines to use a constant.

Protected Const MyTextboxClientID As String = "MyTextboxClientID"

Protected Sub DetailsView1_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles DetailsView1.PreRender
    If DetailsView1.CurrentMode = DetailsViewMode.Edit Or DetailsView1.CurrentMode = DetailsViewMode.Insert Then
        Dim txt As TextBox = DetailsView1.FindControl("MyTextbox")
        ScriptManager.RegisterHiddenField(DetailsUpdatePanel, MyTextboxClientID, txt.ClientID)
    End If
End Sub

And the JavaScript.

var txt = GetContainedControl('<% = MyTextboxClientID %>')
if (txt != null)
{
    // Do stuff here
}

Hope that helps!!!!

3 comments:

Anonymous said...

just what I needed. thanks!

Anonymous said...

You saved me!
Thanks

Fred said...

8 years later and you've just saved me with this as well! You're my hero! Haha.