How-to use ClientIDs in JavaScript without the ugliness

ASP.Net has an interesting way of handing the potential ID conflicts caused by embedding third-party controls within your web-page; it prefixes any sub-controls with their parent’s ID.

<asp:TextBox ID="txtUsername" Runat="server" /> within a standard page simply has an ID of txtUsername within the HTML output. On the other hand, the following example would result in something along the lines of _parent_txtUsername as the ID:

<div id="parent" runat="server">
  <asp:TextBox ID="txtUsername" Runat="server" />
</div>

This isn’t really much of a problem when all you are working with is server-side code, but when you start tinkering with JavaScript, things become quite annoying and get an overall feeling of hackiness.

One solution, which I have used time-and-again, is to use a script block at the end of your page where you create a series of variables that contain the actual IDs. You then use these variables to reach the actual elements via JavaScript.

<script type="text/javascript">
  var txtUsernameID = '<%= txtUsername.ClientID %>';
  var txtPasswordID = '<%= txtPassword.ClientID %>';
</script>

This solution works fine, but it isn’t exactly pretty and it doesn’t weigh well on my conscience.

Javascript Mapping

I’ve created a simple class that traverses the control structure and outputs an object that contains the mappings, as above, but without any client-side intervention; not a <%= ...ClientID %> in sight.

An example of the output would be:

var ClientIDs = {
  txtUsername = 'ctrl0_txtUsername',
  txtPassword = 'ctrl0_txtPassword'
};

Which enables you to reference elements, that you know are server-controls, by calling ClientIDs.txtUsername.

Before:

<script type="text/javascript">
  var txtUsernameID = '<%= txtUsername.ClientID %>';
  var txtPasswordID = '<%= txtPassword.ClientID %>';

  function validate() {
    var username = $(txtUsernameID).value;
    var password = $(txtPasswordID).value;

    if (username == 'james') {
      alert("you shouldn't be here!");
    }
  }
</script>

After:

<script type="text/javascript">
  function validate() {
    var username = $(ClientIDs.txtUsername).value;
    var password = $(ClientIDs.txtPassword).value;

    if (username == 'james') {
      alert("you shouldn't be here!");
    }
  }
</script>

ServerControlIDs class

Methods

void Emit(page) - Builds the controls of the page into a mapped structure, registering a client-side script block for the output.

void Emit(control, literal) - Builds the controls of the control into a mapped structure, rendering the output into the literal control supplied. The literal is best suited to being placed into the <head> tag, which helps improve the semantic nature of your page.

Properties

bool Whitespace - Sets whether the output should contain whitespace, provided only for “prettifying” your code; defaults to off.

string VariableName - Sets the JavaScript variable name used; defaults to ClientID.

Usage

To use this class, simply create an instance in the PreRender event for your page — this ensures that all the controls have been set to their correct state — then call the Emit method you desire.

History

  • [1.1] Removed IDs from Repeater/DataGrid contained controls.
  • [1.0] Initial release

Download

Future James: This is all gone folks. Left here for curiosity.