It doesn’t take long for anyone who does client-side coding in SharePoint to figure out that the trusty ol’ getElementById() method just ain’t all it’s cracked up to be. Sure, it works fine in standard ASP.NET pages but in SharePoint all that pretty client-side code goes right out the window. Just what is going on here?
The simple answer is that SharePoint is coming between you and your control ID’s. Keep in mind that a typical SharePoint page may have dozens of individual server controls, user controls, field elements web parts, and other objects scattered throughout the page hierarchy. In order to maintain viewstate for all these elements, SharePoint must translate simple, easy-to-read ID’s into something that it can be sure is unique, as it has no way to determine if that same control ID might exist somewhere else on the page. So something as easy as ‘txtTextBox1’ becomes ‘ctl00$m$g_1438a021_e6f0_4010_bf4b_33713d2e724a$ctl00
The real problem here is that SharePoint’s funky ID’s aren’t created until the page is rendered and they may change depending upon what other elements exist on the page. So just grabbing the ID from View Source doesn’t guarantee that your script is going to work. The trick here is to capture the ID before it is rendered to the client and use it in your getElementById() method.
Instead of this:
You’ll need to do this:
But wait, that’s only the beginning. If you, like most other ASP.NET 2.0 programmers, are using any .NET-specific controls, such as GridView, FormView, ItemTemplate, etc. you’ve got another problem. SharePoint builds the unique identifier for individual controls by inspecting the control hierarchy; that is, the long ID string is actually composed of strings representing the control AND it’s parent elements. So the sample ID above actuall represents this structure:
[General Control ID]$[Page GUID]$[Root User Control Name]$[Container Control Name]$[Container Control Name]$[Parent Control]$[Child Control]
This will come back to haunt you if your contol is inside of another control as [Control Name].ClientID will only generate an ID with the topmost parent (the page itself) and the specific control name – it will skip the containing elements in between. To get around this, you frst need to locate the control in the page hierarchy using server-side script and then get the client ID. So, if you are trying to reference a textbox inside of a FormView, the script would look like this:
document.getElementById(‘<%= ((TextBox)this.fvFormView.FindControl("txtTextBox1")).ClientID %>’)
The above code uses the FindControl method to locate a control with the ID of ‘txtTextBox1’ inside of a Form View with an ID of ‘fvFormView’, casts it as a System.Web.UI.WebControls.TextBox object, then renders the Client ID property for the control in its proper context. Now the client-side script will have the proper ID string to located the control on the page after SharePoint has intervened. This same method can be used for just about any control on the page so long as you remember to honor the hierarchy of the control structure (including nested controls).