Identifying the element ID in a client script from a WebControl

K

kw

What is the proper way to get the element ID for a client script?

For example, suppose in the WebControl:
TextBox t=new TextBox;
t.ID=this.ClientID+"X";
....
Then elsewhere we want to access it on the client:
Control.Attributes["OnClick"] =
"javascript:document.getElementById('"+this.ClientID+"X"+"').value=
'test';";

It doesn't work because the textbox ID becomes something like:

TextBox1_X

and the link control looks like this:

javascript:document.getElementById('TextBox1X').value= 'test';
 
K

Karl

ClientId will get rendered as the id, UniqueId as the name...in your
getElementById example, you'd want to use ClientId

"javascript:document.getElementById('" + t.ClientId+ "').value = 'test';"

you don't have to give your textbox a special id, it'll automatically get
one assigned.

The problem with your code is that you append the "X" in the getElementbyId
field..by setting the ID property of the control, the ClientId is
automatically updated.

Karl
 
K

kw

Hi Karl, that doesn't work either. In the example below I've loaded a
WebControl into a dynamically created UserControl on a WebPage. The
ClientID returned is different from what finally appears on the control:

<input name="_ctl0:pg:_ctl4:_ctl0" type="text" value=""
OnFocus="javascript:document.getElementById('pg__X').value= 'test'>
<textarea name="_ctl0:pg:_X" rows="3" id="_ctl0_pg__X"></textarea>

Karl said:
ClientId will get rendered as the id, UniqueId as the name...in your
getElementById example, you'd want to use ClientId

"javascript:document.getElementById('" + t.ClientId+ "').value = 'test';"

you don't have to give your textbox a special id, it'll automatically get
one assigned.

The problem with your code is that you append the "X" in the getElementbyId
field..by setting the ID property of the control, the ClientId is
automatically updated.

Karl

kw said:
What is the proper way to get the element ID for a client script?

For example, suppose in the WebControl:
TextBox t=new TextBox;
t.ID=this.ClientID+"X";
...
Then elsewhere we want to access it on the client:
Control.Attributes["OnClick"] =
"javascript:document.getElementById('"+this.ClientID+"X"+"').value=
'test';";

It doesn't work because the textbox ID becomes something like:

TextBox1_X

and the link control looks like this:

javascript:document.getElementById('TextBox1X').value= 'test';
 
K

Karl

Can I see code as to how it's being added? I've played with adding it in a
placeholder, in a grid....can't reproduce the mismatch..

Karl

kw said:
Hi Karl, that doesn't work either. In the example below I've loaded a
WebControl into a dynamically created UserControl on a WebPage. The
ClientID returned is different from what finally appears on the control:

<input name="_ctl0:pg:_ctl4:_ctl0" type="text" value=""
OnFocus="javascript:document.getElementById('pg__X').value= 'test'>
<textarea name="_ctl0:pg:_X" rows="3" id="_ctl0_pg__X"></textarea>

"Karl" <none> wrote in message news:[email protected]...
ClientId will get rendered as the id, UniqueId as the name...in your
getElementById example, you'd want to use ClientId

"javascript:document.getElementById('" + t.ClientId+ "').value = 'test';"

you don't have to give your textbox a special id, it'll automatically get
one assigned.

The problem with your code is that you append the "X" in the getElementbyId
field..by setting the ID property of the control, the ClientId is
automatically updated.

Karl

kw said:
What is the proper way to get the element ID for a client script?

For example, suppose in the WebControl:
TextBox t=new TextBox;
t.ID=this.ClientID+"X";
...
Then elsewhere we want to access it on the client:
Control.Attributes["OnClick"] =
"javascript:document.getElementById('"+this.ClientID+"X"+"').value=
'test';";

It doesn't work because the textbox ID becomes something like:

TextBox1_X

and the link control looks like this:

javascript:document.getElementById('TextBox1X').value= 'test';
 
K

kw

Thanks Karl. I wish I could post you the code for the control, but it would
surely only confuse the issue because it's a very complex compound
WebControl.

The gist of it is this: OnLoad() -calls-> ControlCreation (wherein onClick
Attribute is set thus we will need to know the ID of the control) -calls->
creation of the final control in the WebControl (wherein the ID must be
assigned).

So ControlCreation looks like this:
Control.Attributes["OnClick"] =
"javascript:document.getElementById('"+this.ClientID+"X"+"').value='test';";

And the final stage looks like this:
TextBox t=new TextBox;
t.ID=this.ClientID+"X";

Now this strategy works *some* of the time, but not when the WebControl is
in a UserControl on a WebForm. The ID of the final control looks like
_ctl0_pg__X and not pg__X and I don't see any way for the webcontrol to know
what it's final ID is.

<input name="_ctl0:pg:_ctl4:_ctl0" type="text" value=""
OnClick="javascript:document.getElementById('pg__X').value= 'test'>

Karl said:
Can I see code as to how it's being added? I've played with adding it in a
placeholder, in a grid....can't reproduce the mismatch..

Karl

kw said:
Hi Karl, that doesn't work either. In the example below I've loaded a
WebControl into a dynamically created UserControl on a WebPage. The
ClientID returned is different from what finally appears on the control:

<input name="_ctl0:pg:_ctl4:_ctl0" type="text" value=""
OnFocus="javascript:document.getElementById('pg__X').value= 'test'>
<textarea name="_ctl0:pg:_X" rows="3" id="_ctl0_pg__X"></textarea>

"Karl" <none> wrote in message news:[email protected]...
ClientId will get rendered as the id, UniqueId as the name...in your
getElementById example, you'd want to use ClientId

"javascript:document.getElementById('" + t.ClientId+ "').value = 'test';"

you don't have to give your textbox a special id, it'll automatically get
one assigned.

The problem with your code is that you append the "X" in the getElementbyId
field..by setting the ID property of the control, the ClientId is
automatically updated.

Karl

What is the proper way to get the element ID for a client script?

For example, suppose in the WebControl:
TextBox t=new TextBox;
t.ID=this.ClientID+"X";
...
Then elsewhere we want to access it on the client:
Control.Attributes["OnClick"] =
"javascript:document.getElementById('"+this.ClientID+"X"+"').value=
'test';";

It doesn't work because the textbox ID becomes something like:

TextBox1_X

and the link control looks like this:

javascript:document.getElementById('TextBox1X').value= 'test';
 
K

Karl

I'm being an idiot..get the ClientId AFTER you add it to the control
collection...
Dim t As New TextBox
string firstClientId = t.clientId
plc.Controls.Add(t)
string secondClientId = t.clientId


(that's a c#/vb.net mix :) ) anyways...secondClientId won't be equal to
firstClientId : ) when you add it to a control, the parent'd id gets
appended, which is what you are missing

Karl

kw said:
Thanks Karl. I wish I could post you the code for the control, but it would
surely only confuse the issue because it's a very complex compound
WebControl.

The gist of it is this: OnLoad() -calls-> ControlCreation (wherein onClick
Attribute is set thus we will need to know the ID of the control) -calls->
creation of the final control in the WebControl (wherein the ID must be
assigned).

So ControlCreation looks like this:
Control.Attributes["OnClick"] =
"javascript:document.getElementById('"+this.ClientID+"X"+"').value='test';";

And the final stage looks like this:
TextBox t=new TextBox;
t.ID=this.ClientID+"X";

Now this strategy works *some* of the time, but not when the WebControl is
in a UserControl on a WebForm. The ID of the final control looks like
_ctl0_pg__X and not pg__X and I don't see any way for the webcontrol to know
what it's final ID is.

<input name="_ctl0:pg:_ctl4:_ctl0" type="text" value=""
OnClick="javascript:document.getElementById('pg__X').value= 'test'>

Karl said:
Can I see code as to how it's being added? I've played with adding it in a
placeholder, in a grid....can't reproduce the mismatch..

Karl

kw said:
Hi Karl, that doesn't work either. In the example below I've loaded a
WebControl into a dynamically created UserControl on a WebPage. The
ClientID returned is different from what finally appears on the control:

<input name="_ctl0:pg:_ctl4:_ctl0" type="text" value=""
OnFocus="javascript:document.getElementById('pg__X').value= 'test'>
<textarea name="_ctl0:pg:_X" rows="3" id="_ctl0_pg__X"></textarea>

"Karl" <none> wrote in message ClientId will get rendered as the id, UniqueId as the name...in your
getElementById example, you'd want to use ClientId

"javascript:document.getElementById('" + t.ClientId+ "').value = 'test';"

you don't have to give your textbox a special id, it'll
automatically
get
one assigned.

The problem with your code is that you append the "X" in the
getElementbyId
field..by setting the ID property of the control, the ClientId is
automatically updated.

Karl

What is the proper way to get the element ID for a client script?

For example, suppose in the WebControl:
TextBox t=new TextBox;
t.ID=this.ClientID+"X";
...
Then elsewhere we want to access it on the client:
Control.Attributes["OnClick"] =
"javascript:document.getElementById('"+this.ClientID+"X"+"').value=
'test';";

It doesn't work because the textbox ID becomes something like:

TextBox1_X

and the link control looks like this:

javascript:document.getElementById('TextBox1X').value= 'test';
 
K

kw

Guess what...it still doesn't work for me (I can see how this will work in
your example). And here's the funny thing: after the controls are added and
ClientID is known (even in OnPreRender)...the final HTML looks like this:

MyControl1_MyControl1__ctl16

instead of (from tb.ClientID)

_MyControl1__ctl16

I don't understand why ASP.NET is modifying the ID after OnPreRender.
 
K

Karl

I'm stumped :(
tb needs to be added to its parent control, but that parent control needs to
be added to its parent control. however the controls are added up in the
final scenario is where you want to get clientid...

Try to output <%=tb.ClientId%> in your page...make sure tb is protected or
less....this will give you the clientId at the very end..if it doesn't match
the cientID you are getting in your codebehind, I'm either being a tard, or
you aren't getting it after all Adds are completed.

Karl
 
B

bruce barker

control id and names are a mess because MS did not understand the W3C rules
when they wrote the code.

background.

html form controls have a name property that is used in a form post

<form><input name="myInput" type="button" value="foo"></form>

when posted the browser will send

myInput=foo

originally there were no rules for forming name. later version of html set
rules (use id rule - see below)

later version of html added the id attribute from xml. the id attribute has
many rules.

1) must be unique across the document
2) must start with a letter
3) can only contain letters, numbers and underscore

when ms wrote web controls they had the issue of naming nested controls. the
simple fix concat the names together with ":" between them. for example if
button1 was nested in control control1, the name would be
"control1:button1". this turned out to be a really bad decision. for several
reasons.

1) ":" are not allowed in the id attribute, so they are removed and replaced
with _
2) while non w3c compliant browser allowed the ":" in name, it lead to
scripting errors, because the name was not valid javascript name, so could
not be used in the common syntax:

document.forms[0].myFieldname

3) IE has a bug which causes an alert if a ":" is present in a url under
https. this caused problems with postback:
javascript:_doPostBack('control1:control2')
would cause an alert on an https page, so now __dopostback() replaces
the ":" with $.
javascript:_doPostBack('control1$control2')

4) the name attribute is the name the backend uses to match up the posted
data with the controls. the name still uses ":" even though some proxy
servers will strip it, and thus are not compatiable with .net


now:

ClientID is the name of the control on the server side, it does not have to
be unique. Two parent controls can controls of the same name, otherwise
writing composite controls would be hard.

UniqueID is the what the rendered html attribute id will be. this is what
your javascript should use and will contain the any parent container names.

in your web control you want to:

TextBox t=new TextBox;
t.ID = "X";

Control.Attributes["OnClick"] ="javascript:document.getElementById('"
+ this.FindControl("X").UniqueID + // get the unique id of my
child control X
+ "').value='test';";


assuming the webcontrol's id is TextBox1 (and is a div), when rendered it
looks like:

<div id="TextBox1"
OnClick="javascript:document.getElementById('TextBox1_X').value='test';" >
<input type=text id="TextBox1_X" name="TextBox1:X">
</div>

-- bruce (sqlwork.com)
 
K

kw

BOB BARKER You are the greatest! Not only did it work in the simple cases,
but the most complex nexted dynamically loaded ones too.

I did try UniqueID, but I found it has to be in the OnPreRender phase.
Thus, the script generation has to be the last step.

string s=this.FindControl("X").UniqueID;//should be called from
OnPreRender()
private string GetScript(){
string s=this.FindControl("X").UniqueID;
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append("<script>\n");
sb.Append("function DoSomethingReallyImportant(ctl)\n{\n");
sb.Append("document.getElementById(\"");
sb.Append(s);
sb.Append("\").value=\"test\";\n}\n");
sb.Append("</script>\n");
return sb.ToString();
}




bruce barker said:
control id and names are a mess because MS did not understand the W3C rules
when they wrote the code.

background.

html form controls have a name property that is used in a form post

<form><input name="myInput" type="button" value="foo"></form>

when posted the browser will send

myInput=foo

originally there were no rules for forming name. later version of html set
rules (use id rule - see below)

later version of html added the id attribute from xml. the id attribute has
many rules.

1) must be unique across the document
2) must start with a letter
3) can only contain letters, numbers and underscore

when ms wrote web controls they had the issue of naming nested controls. the
simple fix concat the names together with ":" between them. for example if
button1 was nested in control control1, the name would be
"control1:button1". this turned out to be a really bad decision. for several
reasons.

1) ":" are not allowed in the id attribute, so they are removed and replaced
with _
2) while non w3c compliant browser allowed the ":" in name, it lead to
scripting errors, because the name was not valid javascript name, so could
not be used in the common syntax:

document.forms[0].myFieldname

3) IE has a bug which causes an alert if a ":" is present in a url under
https. this caused problems with postback:
javascript:_doPostBack('control1:control2')
would cause an alert on an https page, so now __dopostback() replaces
the ":" with $.
javascript:_doPostBack('control1$control2')

4) the name attribute is the name the backend uses to match up the posted
data with the controls. the name still uses ":" even though some proxy
servers will strip it, and thus are not compatiable with .net


now:

ClientID is the name of the control on the server side, it does not have to
be unique. Two parent controls can controls of the same name, otherwise
writing composite controls would be hard.

UniqueID is the what the rendered html attribute id will be. this is what
your javascript should use and will contain the any parent container names.

in your web control you want to:

TextBox t=new TextBox;
t.ID = "X";

Control.Attributes["OnClick"] ="javascript:document.getElementById('"
+ this.FindControl("X").UniqueID + // get the unique id of my
child control X
+ "').value='test';";


assuming the webcontrol's id is TextBox1 (and is a div), when rendered it
looks like:

<div id="TextBox1"
OnClick="javascript:document.getElementById('TextBox1_X').value='test';" >
<input type=text id="TextBox1_X" name="TextBox1:X">
</div>

-- bruce (sqlwork.com)













kw said:
Guess what...it still doesn't work for me (I can see how this will work in
your example). And here's the funny thing: after the controls are added and
ClientID is known (even in OnPreRender)...the final HTML looks like this:

MyControl1_MyControl1__ctl16

instead of (from tb.ClientID)

_MyControl1__ctl16

I don't understand why ASP.NET is modifying the ID after OnPreRender.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,996
Messages
2,570,238
Members
46,826
Latest member
robinsontor

Latest Threads

Top