JQuery - get a handle on a server element in javascript without using <%= elem.ClientID %>

One of the things I see  a lot of is code that looks like this:

<asp:CheckBox ID="chkEnable" Text="My Checkbox" runat="server" />
<script type="text/javascript">
    var chkEnable = $get("<%= chkEnable.ClientID %>");
</script>

You can see that the ClientID is being used, which will grab the exact element that .net generates, and will look like ctl00_plcMain_chkEnable or something like that.

jQuery can select an element by looking at what its attribute ends with, as explained here.

So we get this instead:

<asp:CheckBox ID="chkEnable" Text="My Checkbox" runat="server" />
<script type="text/javascript">
    $(function() {
        var checked = $("input[id$=chkEnable]").attr("checked");
        if (checked) {
            alert("It is checked.  These are the droids you are looking for.");
        }
    });
</script>

 

The code in the selector gets all of the input elements that have an id attribute that ends with chkEnable.  What really rocks (or sucks, depending on your point of view) is that if you have a repeater full of <asp:checkbox> controls, this will select all of them so you can process them.

More later - joel

6 Comments

  • Sweet! I'm new to jQuery and this was my first complaint. How the heck do I use it with Controls nested in MasterPages or DataControls. Now I know. Thanks!

  • One issue with this is performance. $("#id") is very fast because it uses browser native functions. Selector matching of attributes on the other hand is much slower as it has to run through all elements. Filtering elements as much as possible to a parent element is essential to this approach, but then the expressions start getting ugly quick too.

  • This is an interesting find but you should be careful with this approach as you don't have any guarantee that the algorithm for the generation of ID's will stay the same between different versions of the ASP.NET runtime, that's the reason why it is recommended to resolve the ClientID. Furthermore it is possible to override the properties ClientID and UniqueID and in this case the ClientID of the checkbox could have been "EnableCheckbox" instead of ending with "chkEnable" if we were talking about a custom control. In ASP.NET 4.0 it will be possible to specify the ClientID declaratively (thus in the markup).

  • I agree with you all.

    My main reason for doing this was updating existing code and taking it OUT of aspx/ascx files and putting it in .js files where tags don't live.

    Glad to see some other ways of doing stuff, tho. It's awesome to see the kinds of creativity that jQuery promotes!

  • However just remember that with the latest version of visual studio, you will actually get compile time errors for code inside the block. Thus your compiler will help you should you rename a control.

    I try to create javascript variables for each ID used as in:
    var chkEnableID = "");

    I then use the actual variable in all my javascrip code. While currently I am doing that inside an ASPX page, it would be a good way of moving code to external .js files. Your ASPX page could create a bunch of variables with the clientIDs, and you could pass them into your functions in external files such that all your logic is in external files. I am sure you can think of many creative ways of getting the variables into the code in your external .js files.

    This would seem a better solution as it:
    a) Still gives you compile time errors in the blocks.
    b) Provides the best jQuery performance on lookups.
    c) Allows you to move your code to external files.

    Dave

  • You would want to consider if the chkEnable is embedded in a control that could be repeated on your page. That is the reason behind the ClientID that ASP.Net generates. In general, accessing by a partial name does not guarantee uniqueness.

    Of course, you could use this to your advantage if you want to access all checkboxes (or any other control) in multiple rows of a repeater or gridview.

Comments have been disabled for this content.