views:

236

answers:

5

I know that in the next version of ASP.NET we'll finally be able to set the clientids on System.Web controls without the framework doing it for us in a quasi-intelligent way e.g:

id="ctl00__loginStatus__profileButton"

Does anyone know a good method in the meantime to force the above id to something like

id="profileButton"

The main reason for this is manipulation of the clientids in jQuery when dynamically adding controls to a page. The problem I can see is changing the ids will break the Viewstate?

+5  A: 

What I tend to do is dynamically generate javascript methods which handle this. You can do this in markup or code behind so for example:

<script language="javascript" type="text/javascript">
function doXYZ()
{
   $("#" + getListBoxId()).css(...)
}

function getListBoxId()
{
 return "<%=this.myListBox.ClientId>";
}

</script>

You can also build the functions in the code behind and register them.

EDIT

A couple months ago I needed to fix the id of some server controls, I managed to hack it in and I described my method here here.

Basically you need put the controls inside a naming container like a user control, and then override a couple of properties which prevents the child controls from getting their uniqueid.

JoshBerke
My question was a bit unclear, what I'd prefer is to be able to set the ids so I always know what they are (instead of having to use a lookup table on the client, the client ids map to another type of id)
Chris S
I know I tried to find a similar solution and quickly decided it wasn't worth the effort at the time.
JoshBerke
+1  A: 

The performance isn't great, but you can use this selector syntax to match messy ClientIDs:

$("[id$='_profileButton']")

That matches any element ending in _profileButton. Adding the leading underscore ensures that you're matching the desired element and not another element that ends in the substring "profileButton" (e.g. "myprofileButton").

Since it has to iterate over the entire DOM, the performance can be poor if you use it in a loop or several times at once. If you don't overuse it, the performance impact is not very significant.

Dave Ward
A: 

I have often run in to this "problem" while developing in asp.net webforms. In most cases I tend to use the css class of the element.

jQuery(".My .Container12")

Before starting to manipulate the id:s, perhaps that is a way you can handle it aswell? It's a simple solution.

ullmark
This can have the same performance drawbacks as Dave's answer (using it in a loop, etc). Referencing by class is a lot slower than by ID
John Sheehan
+1  A: 

Another way would be to wrap your control with a div or span with a static id, then access the control through that.

E.g.

<span id="mySpan">
<asp:TextBox id="txtTest" runat="server" />
</span>

You could then target input tags inside MySpan. (though I agree it would be nice to be able to specify a nice name, provided you could handle the naming conflicts...)

Spongeboy
A: 

There is another solution not mentioned which is to subclass the ASP.NET controls and force the IDs:

public class MyCheckBox : CheckBox
{
    public string ForcedId { get;set; }

    public override string ID
    {
     get
     {
      if (!string.IsNullOrEmpty(ForcedId))
       return ForcedId;
      else
       return base.ID;
     }
     set
     {
      base.ID = value;
     }
    }

    public override string ClientID
    {
     get
     {
      return ID;
     }
    }
}

Then use this where you know the IDs will never clash:

<mytag:MyCheckBox ForcedId="_myCheckbox" runat="server" />

If you are using lists you will need to write a ListControlAdapter, and also adapters for each type of list you're using (dropdown,checkbox,radiobutton,listbox). Alternatively cross your legs and wait for .NET 4.0.

Chris S