Robust ASP.NET control referencing in JavaScript
AJAX, ASP.NET By Dave Ward. Updated April 23, 2008As you may know, ASP.NET controls often render with client-side IDs different than what’s declared in your aspx code. Especially when they’re nested in other controls (Tabs, Wizard, GridView, etc). When working with them on the server side this isn’t an issue, but tends to throw a monkey wrench into the gears of client-side development. Here’s an example:
<asp:Wizard runat="server" ID="Wizard1"> <WizardSteps> <asp:WizardStep> <asp:TextBox runat="server" id="TextBox1" /> </asp:WizardStep> <asp:WizardStep> <asp:Button runat="server" ID="Button1" /> </asp:WizardStep> </WizardSteps> </asp:Wizard>
TextBox1 and Button1 are accessible in code-behind via their declarative IDs, as we’d expect. However, trying to use $get() or getElementById() on TextBox1 or Button1 will fail. As it turns out, TextBox1 is rendered as Wizard1_TextBox1 and Button1 is rendered as Wizard1_Button1.

One solution is to hard code those rendered values in your JavaScript. $get(‘Wizard1_TextBox1′) will correctly reference TextBox1 on the client side, but doing it that way is a maintenance nightmare. What would have otherwise been innocuous changes to the structure of your page could now break your client script. Not good.
There must be a better way!
Indeed there is. The better solution is to use inline ASP.NET code to inject the control’s ClientID property:
$get('<%= TextBox1.ClientID %>')
Now the correct client element ID is referenced, regardless of the structure of the page and the nesting level of the control.
In my opinion, the very slight performance cost of this method is well worth it to make your client scripting more resilient to change.
Similar posts
What do you think?
I appreciate all of your comments, but please try to stay on topic. If you have a question unrelated to this post, I recommend posting on the ASP.NET forums or Stack Overflow instead.
If you're replying to another comment, use the threading feature by clicking "Reply to this comment" before submitting your own.



Sorry, but I don’t quite get it. Could you please show a brief example in code?
Thanx.
For example:
I’ve got a similiar problem, but this doens’t work for me. I’m inside of an ascx control trying to reference an asp:textbox id. When I use the above code I get an error that states that “the name ‘CompletedDateTextBox’ does not exist in the current context.’ Any thoughts?
Your ASCX control needs to expose that property for it to be accessible at the page level. If it’s a user control that only has the TextBox, just give the user control a public ClientID property that returns the TextBox’s ClientID.
hi,
by default ascx controls are reffered to by dom like this
#ascxcontrolID_whatevercontrol you are looking for in the ascx
ex: #footercontrol_textboxinput
ok..this will work if we use a single webpage. if the page in masterpage then how to identify the control.
It works the same way from a content page.
The only situation I’m aware of where it doesn’t work is for controls in a repeated ITemplate.
Hum. It’s not working for me. I’ve tried the following and they all return null:
var p2 = $get(‘auxPanel’);
var p2 = $get(”).value;
var p2 = $find(‘auxPanel’);
var p2 = document.getElementById(”)
The only way I’ve got it to work is:
var p2 = $get(‘ctl00_ContentPlaceHolder1_auxPanel’)
and I don’t want to do it like that.
Any suggestions?
Thanks,
Brian
Oops – var p2 = $get(”).value; shoulda been var p2 = $get(‘auxPanel.ClientID’).value;
Is your code in an external file? Those ASP.NET expressions are only replaced in ASP.NET file types like ASPX. In an external JavaScript include, they will remain unchanged.
Ahhh, yes they are in an external file. Is there a fairly simple way to achieve that in an external file or should I just pull the javascript into the aspx file? It’s only about 40 – 50 lines of code.
Thank you Dave.
Brian
Since JavaScript all executes in the same global scope, you can define those ID variables inline in your ASPX and then use those variables in your external file. Just make sure your inline declarations appear before the external file’s script reference if the external file will need access to the variables immediately.
Got it! I decided to keep the code in the separate js file and then used Joey’s example below and created a “BASE” var. All is good now.
Thanks!!!
Yes that works, but only if on the .aspx page
What if we are separating out all our JavaScript in separate .js files, like everyone should be, for clear separation of view and controller?
Personally, I don’t mind a bit of light, presentation oriented JavaScript on the page.
I like to set up all of the heavy lifting in function libraries included off-page, but leave pageLoad() type initialization on-page (which is where I use this technique to pass the correct ClientIDs to the off-page JavaScript).
good idea … i usually create a global variable (ack!) that is basically the naming container for the nested control and reference the control like I would in normally. It works for smaller projects and I place it in a common.js file so I know where to look.
i.e.
var BASE = “cphMain_”;
function foo(){
var btn = $get(BASE+”btnSubmit”);
// do something interesting
}
That’s a good solution, but only if you’re not modifying the Page.Controls collection programatically from somewhere else in your server-side code. For example, if you try that on a page where you’re also doing something along the lines of Page.Controls.Add( new Label() ); or something like that, you’ll end up getting an error stating that the ClientID reference can’t be made because the Controls collection has been modified.
I’m quickly losing taste for the ASP.NET server controls model for this simple reason. You have to jump through some ridiculous hoops to write client-side code for an ASP.NET generated page. I wish there was a better way.
I also register a global variable to access the object. However I do a RegisterClientScriptBlock(…) and output all the variables through that method.
Exactly like Denny said: you do this:
RegisterClientScriptBlock(“var controlID = ‘” + Control.UniqueID + “‘)”;
Then you can keep your .js file separate.
For my money, it makes more sense to keep presentation related code in the aspx as much as possible. If you move it to code-behind, then that’s another step removed it is from a given JS include.
Too much JavaScript in code-behind always feels like coding business logic in stored procs to me.
Finally someone says what is the right way to do it.
Bad advice dude.
ClientID great until you need it in real world. You wouldnt even imagine the hacks I had to go through to just get the reference to the control that I wanted to call ClientID on. Iterating through a repeater just to find a control, just to find its client ID is absurd.
A superior workaround is to use CSS selectors in Javascript (mooTools, JQuery, and Prototype have them) to grab references to the runtime ids I need. Then its just about setting intelligent class names. May not be efficient on the client side, but it works. In ASP.NET as it stands now, I would recommend never ever referencing controls by ID.
What we need is a ClientID property on all controls that we can set manually or databind. So if I had a repeater with a bunch of buttons in it, each button could be bound to the ID of the corresponding database row. So I could say $(“button_5″) to grab the button.
I hate tying presentation to functionality.
I’ve done it when necessary (e.g. using jQuery plugins), but it’s not a very good long-term solution. Your design people shouldn’t need to understand client scripting and your personal conventions to work on a page’s presentation.
I kind of found another way to solve the problem, but it’s not necessarily the best nor most effecient way of doing it (but I thought I’d at least mention it).
http://www.ben-rush.net/blog/PermaLink.aspx?guid=70870288-191a-4dd0-a1a0-61365a26dea1
That’s an interesting way of handling it.
Keep in mind that using an arbitrary attribute won’t validate and will potentially be stripped out by the tools that designers use.
Yes, of course you’re absolutely right. However, in some circumstances where someone might be in a bind it might work – hard to say.
I think every solution is something of a hack (unfortunately).
hi i enjoyed the read
Hi Thanks a lot. This was nice and short. Thanks and It will sure make me to write good code…
Ewwww… :)
Here’s how I approach this challenge.
Most of the time I’m using a framework with DOM selectors anyway (my favorite being jQuery at the moment). So I simply supply an ID *AND* a NAME attribute for controls that I want to reference via Javascript. ASP.NET doesn’t modify the NAME attribute, so I can then use a simply jQuery selector to get the object I need from the page or external Javascript. For example, given the following HTML control:
Click me
I could then reference and modify it using jQuery like so:
$(‘a[@name=ExternalLink]‘).attr(“onclick”, “alert(‘We are off to Google!’);”);
$(‘a[@name=ExternalLink]‘).html(‘Click here to visit Google.’);
Of course, you’re not limited to using this NAME attribute method. There’s tons of ways to select objects with jQuery. Here’s an example using a class instead:
Click me
$(‘a.ExternalLink’).attr(“onclick”, “alert(‘We are off to Google!’);”);
$(‘a.ExternalLink’).html(‘Click here to visit Google.’);
that will only work for the controls that have a NAME attribute though. IMG control for example has no NAME attribute. What would you suggest doing in that case using JQuery?
Technically speaking, if you don’t care about stringent standards, any tag can have any attribute you want, so you could make up a whole new one ;)
I was mostly speaking from the perspective of getting form fields. Unfortunately though, I realized after I posted that in a repeater control, the name value is also modified by the .NET engine to match the id.
As I said above, you can also use class names to select against as well if you don’t want to use the name attribute. Not perfect, but it’s another option.
I tend to use tag-based selection (getElementByTagName()) and dom-walking to get to server control elements; I find it pretty reliable. If I need to, I can use staticall id’d html elements as anchors to get there more efficiently. But, in the button example in a repeater, I might wrap the whole repeater in a html div named something significant, then get a reference to that div, e.g. var div = $get(‘repeaterDiv’);
then I can get a collection of buttons that are in the repeater div like:
var buttons = div.getElementsByTagName(‘INPUT’);
for (var i=0;i
hmm… cut off some of my post there. Anyway, point is that you can iterate over that collection relatively easily at that point based on input type or the like, to make sur eyou’re only affecting what you want to be affecting.
Isn’t this entire problem caused because the HTML is generated on the server and not the client?
Shouldn’t the Ajax client be loading *data only* from the server and generating the HTML itself, ideally using client side implementations of extensible GUI widgets?
Then, when gui elements are created, they don’t even need Id’s, you would just store a refernce to them in javascript.
Something like this perhaps (an example OnHttpComplete method)
function onHttpComplete(result)
{
var grid = new myapp.controls.MyGridView(); // perhaps a styled subclass of a M$ provided Sys.WebForms.GridView
grid.dataSource = result;
grid.dataBind();
// if this was a class member:
this._grid = grid;
}
Unfortunatly we all seem to be heading off in the wrong direction and working round the server architecture of (classic postback style) asp.net.
One more thing, I just viewed one of the “how to” videos on doing “Pageflakes like” incremental page loads using asp.net ajax. Well, I couldn’t believe what I was seeing, Joe was actually proposing that you use an ajax call to download another aspx page and blat the entire thing (all HTML output from the aspx) into your page using the .innerHTML property of a div tag. He was delighting in how the page you bring down could have a server side Textbox in it and showed of how you could manipulate the content of it from posted variables! As if…as if that page could now be programmed like a regular aspx!!??
As a pattern, it’s a dead duck I’m afraid.
What I’m trying to say is that this is NOT how “real” ajax development is done, this is how asp.net developers are trying to emulate what they see on modern sites and I’m afraid itr looks like a hack from start to finish.
My advice would be to stick to the update panels as they are a genuine quick win, or invest in a gui library to generate your content on the client from the server data. Anything else and you are jumping through *asp.net induced* hoops in order to do even what should be simple stiff done.
I keep all my js in .js files, so I never use the $get. I just like to DOM walk.. It’s efficient enough I think. I pass the id and the tag of what is generated in the end.. ie (asp:Label = span). I also use a similar function for getting any gridview control I want.
hi,
i have create the popup window. i want to click to ok button to value pass other form.
Ex:-
yahooMail. when i have click to compose button to display the compose form (here provide (To)button).when clicked to button to display the popup window. here i have select to id and clicked to ok EmailId display to (To Textbox).
how to do this type of code.
Thanks
I went through loops and wholes for this, but found a very very easy way to do it in jQuery:
Since ASP.NET controls IDs just get prepend with some values, they always end with the ASP.NET Control’s ID.
So this nifty solution will search for elements that have an ‘id’ attribute that ends with ”
Just my 2 cents…
This is exactly how I’m dealing with the issue at the moment. I think it’s the most straight forward solution.
That is damn brilliant (and seems so obvious now that it’s been pointed out). Thank you Korayem. And thank you alkos333 for prompting me to look back here. I had totally missed Korayem’s post.
To be clear, put the id you’re searching for in the single quotes. For example:
would find the server control “mycontrolid” even if it was in a naming container and had a rendered id like “ct100_ParentContainer_mycontrolid”
You can technically leave off the single quotes as well:
Be aware though that this can match multiple controls if your naming is similar. For example, the above would also match the following:
id=”textfieldmycontrolid”
id=”divmycontrolid”
If you know the control is always within a naming container, you could include the underscore as well to be sure you’re selecting the right one:
One important thing to keep in mind when using that “ends with” selector is that it’s one of the slowest possible selectors. Each time it appears, you’re asking jQuery to loop through every DOM element on the page and execute a substring comparison (every DOM element – even after a first match is located).
If you know the type of element you’re searching for, you can use that to mitigate the problem a bit, e.g.:
Then, at least you narrow the search down to all of a particular element type on the page, which jQuery can quickly retrieve with a getElementsByTagName().
That is what I do to mitigate the issue – I rather take a performance hit than globally define variables for every possible element I’ll be using in the user control. That’s just seems like such a maintenance nightmare to me.
After a few years of ASP.NET now, it feels like a one big hack after all. Working on a project in PHP recently felt like a breath of fresh air – so clean and elegant.
I should add that I really enjoy the server-side programming in C# for example – it’s just writing pure client side code for a ASP.NET 4 can be such a pita sometimes.
I think the key is to either fully embrace the ASP.NET server control approach or fully avoid it. Trying to do half and half is tough.
That is true – you have to go all in to take the full advantage. But Dave, majority of the posts on this blog deal with how to have jQuery play nicely with ASP.NET. A perfect example is validation plug-in and validation group posts. If you are fully embracing here, why not use ASP.NET’s validation controls :)?
One step at a time.
Meaning? … ( hmm.. just how narrow can this threading window get w/ so many posts)
Often, the only way to wean legacy projects off the old WebForms model is slowly, over time. In those situations, it’s helpful to be able to transition to approaches like using jQuery Validation and using jQuery to interact with services, while remaining within the confines of WebForms and the single-form-per-page model that it imposes. Otherwise, the choice becomes one between an entire rewrite or just adding new functionality the old way, and the rewrite rarely wins there. (pretty narrow!)
So I am assuming you are a huge proponent of MVC then :)? (it’s closing in)
I’m able to make do with either ASP.NET WebForms or ASP.NET MVC, if I have the freedom to use them how I desire. Whether it’s an ASMX endpoint or an MVC controller action, I’ll work with anything that can send and receive JSON effectively. On the backend of either, working with the view models and business logic is almost identical.
I do like the Razor view engine a lot though.
(looks like we’re at the bottom now)
Yes, Razor is a thing of beauty – loving the templating concept w/o the need explicitly indicate server-side code.
What are you thoughts on ASP.NET WebForms MVP: http://webformsmvp.com/ (way down there..)
I think it has some interesting ideas, but it’s not something I’m interested in using myself. I think it relies on the assumption that you like things like the page lifecycle and server controls, which I don’t.
I have controls that are created at runtime. How can I get the clientID?
Can I use/how do I use to get the value of a required field validator:
What is the easiest way to get a control (in my case a dropdownlist) clientid that is in a gridview? I was trying something like this in one of the gridview template fields in the onclick event of a html input button.
Probably the best way is to do that during the RowDataBound event. You can use FindControl(“ddlUnderwriterUnassigned”).ClientID to find that row’s ddl’s ClientID. Then, use FindControl(“YourButton”).Attributes.Add to add your script to the button’s client side OnClick, with the ClientID you just found.
using clientID has one problem to find the html ‘id’ of asp.net server control. This problem last for many days for me and finally able to solve. But i don’t why this problem occured?
code i use like:
error message: code < %...%> something like this
I solved by keeping this script in
Am i right? if right, how it is justified?
We can’t use this “” in .js file ?
any solution for this ?
There are several alternatives in the comments on this post.
Since the JavaScript namespace is globally available, you can set ClientID variables in ASPX or output them from code behind, and still access them from a JS include.
how can i reference a asp:textbox inside wizard control using jquery,
ClientID is not working
Sorry for $(“#”) in the first line actually i was trying to reference the grabbing of clientid in your previous comment but somehow i forgot to check that you have code formatting on your website.
Its actually
Using $(‘#’) always cries that control collection has been modified and this error drives me crazy.
Although the alternative is to replace = with # but somehow it doesnot work for me as i use my serverside includes in the head section only.
One hack which i found while researching on net is to write this statement with = sign just after your closing
and before tag , i.e in between closing body and html tags.
If you can suggest some other good option for doing this then it would be great.
I dont want to go codebehind and do any registerclientscriptblock i think asp.net should allow this and it should not give this weired error.
Anyways all your post are great and the best on net in related topics.
Keep the good work going.
Is there a way to make this working when you use a external .js file instead of inline js?
regards
Not this specific technique. There are several good workarounds in the comments above though.
This article uses a technique to resolve the client id:
http://www.codeproject.com/KB/aspnet/0g_asp_resolve_clientid.aspx
If your using jquery the easiest way is to use the [attribute$=value] method – as Korayem pointed out – an example to get the aspx made link id, from your coded id:
//include jquery.js then:
$(document).ready(function(){$(“a[id$='login_link']“).click(function(event){tester(event,this)});});
function tester(event, el){
event.preventDefault();
alert($(el).attr(“id”));
}
//for element:
That works well, but you have to be careful with heavy use and/or use on large documents. Because it has to run a substring search on every element on the page, it can often be surprisingly slow.
thanks all for this useful information
The function $get() is not a javascript function is a ajax asp.net one. It does the same of document.getElementById(), so to get value just do $get(‘elementID’).value, but dont forget to put a scriptmanager in the top of the page for the ajax asp.net to work.
Hi, May I ask a quetion..
what is the name for the tool that u inspect the control id shown in the image?
Regards
cchitsiang
It’s a Firefox addon called Firebug. It is an absolute necessity for web development.
You can get it at http://get firebug.com
Since ASP.NET 4 now allows for a static ClientIDMode, wouldn’t that just be the way to go?
Yes, i believe that will be easier too..and I using that too :)
The only problem with static client IDs is potential clashes when writing for a bigger existing system. For example, when you are writing a module for a content management system which was implemented with WebForms, you might have a number of various content parts with various names, so you need to use either AutoID or Predictable modes to avoid clashes since there is only one . What a big freaking joke…