ASP.NET dynamic controls and validators - Unable to find control id '...' referenced by the 'ControlToValidate' property of '...' - asp.net

I have seem many forum posts / responses on this subject but I am no closer to a solution.
I am loading a repeating data structure from the DB into UpdatePanel controls in an event handler. The number of repeats varies so controls are all created and added to a container panel dynamically. The user has the ability to edit the data so I am also dynamically creating validator controls (RegularExpressionValidators)
The problem is in setting the ControlToValidate property of the validator. No matter how I set this I get the Unable to find control id '...' referenced by the 'ControlToValidate' property of '...' error response from the server which is then raised by ASP.NET AJAX JS.
The short version of the control adding code looks like this:
TextBox licenseCode = new TextBox();
licenseCode.ID = this.getNextId(); // generated ID contains only [A-Za-Z], [0-9], :, -, .
licenseCode.MaxLength = 50;
this.purchaseEdit.Controls.Add(licenseCode); // this.purchaseEdit is an asp:Panel
RegularExpressionValidator licenseCodeVal = new RegularExpressionValidator();
licenseCodeVal.ControlToValidate = licenseCode.ClientID;
licenseCodeVal.ID = this.getNextId();
licenseCodeVal.ValidationGroup = this.purchaseEditSave.ValidationGroup; // save button within the panel
licenseCodeVal.ValidationExpression = #"^.{1," + licenseCode.MaxLength.ToString() + "}$";
licenseCodeVal.ErrorMessage = "Between 1 and " + licenseCode.MaxLength.ToString() + " chars.";
this.purchaseEdit.Controls.Add(licenseCodeVal);
As you can see both controls are added to the same container, the validator is added after the TextBox, and the ControlToValidate property is currently set to the ClientID of the TextBox. I have tried the ID value too but no joy.
The really irritating thing is that if I don't add the validator, and using a breakpoint inspect the ClientID of the TextBox, I can inspect the DOM of the updated page and find the ID attribute of the TextBox:
<input type="text" id="ctl00_ContentBody_PCTL::4890cc3a-8d07-4dee-aa9f-bdd8735fcaf8::licCode"... />
As far as I can tell I'm not doing anything wrong, so why am I getting this error??
Any suggestions much appreciated.

You should not use the ClientID but the ID of the TextBox.
http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.basevalidator.controltovalidate.aspx
"I have tried the ID value too but no joy."
But you didn't get an exception and only the validation didn't work?!
My suggestion is to wrap the control and the validator in an UserControl and add this dynamically to your container-control. On this way you can use fix ID's because they all have distinct NamingContainers.
The code will be cleaner. Encapsulation also increases reusability.

ARGH so I finally figured this thing out - it came down to special characters in the ID. I was having an issue with a JQuery selector which contained ':' and figured I should just check if that was causing the validator issues - it was.
In the end I created my GUIDs without any hyphens and replaced ':' with '_' and the problem went away. This question helped.
I haven't seen anything from MSDN saying certain characters are not permitted in IDs, but then I tend to refer to MSDN with specific problems after jumping in, so maybe there is something on there.. See comment below

Related

Hide aspx button in code behind

I am trying to hide an aspx button on page load if another element has a certain value.
Button:
<input type="button" class="formButton" id="btnShowTerminate" value="Terminate Credential" onclick="ToggleTerminationRow()">
My issue is that I don't know how to edit the buttons attributes (to make it hidden) in the code behind.
In code behind (on PageLoad event):
Page.btnShowTerminate.Visible = false;
HTML controls need to be given the runat="server" attribute in order to be used in the server-side code.
To hide the button from your code behind, use an If statement to test if your 'other element' has the required value.
C#
If(exampleElement.Value == "example value")
{
Page.btnShowTerminate.Visible = false;
}
VB
If exampleElement.Value == "example value"
Page.btnShowTerminate.Visible = false;
End If
This error -
'System.Web.UI.Page' does not contain a definition for
'btnShowTerminate' and no extension method 'btnShowTerminate'
accepting a first argument of type 'System.Web.UI.Page' could be found
(are you missing a using directive or an assembly reference?
is because you haven't included runat="server" in your input.
The exampleElement.Value may have to be different depending on what type of element exampleElement is. For example, Value will work with a TextBox , but you would need to use InnerHtml for a div
Although, a button (any control for that matter) can be hidden from code behind by setting the Visible property to false, there is subtle, and dangerous nuance to that. Doing this causes the button not only to be hidden, but the resulting HTML button will not render on the page. Should you have JavaScript that is referencing the button, the JavaScript will fail because the button does not exist on the rendered page. In debugging, the bug will be caught, but if the JavaScript is never exercised until the code is deployed to a server, it will fail there but no exception will be thrown. The code just won't work and there will be no indication as to why!
The safe way to hide the button is setting the Style as follows:
btnName.Style.Add("display", "none");
This way the button will be rendered but hidden and JavaScript will be able to find it.

ASP.Net Code Optimization

I have almost every piece of code, I just need it to be optimized using correct IF_ELSE conditions and arranging the right flow.
I have a webform (UserProfile.aspx), which contains FormView (to display user profile).
In FormView ItemTemplate, I have put simple HTML and ASP.Net Labels to display Info using Label's Text property :
Eval("col_name");
In EditItemTemplate, I have same table with but textboxes instead of Labels.
I have a button "Edit", on its Click event, I'm changing FormViewMode
FormView1.changeMode(FormViewMode.Edit); [ WORKING ]
I have another button "Cancel", on its Click event, I'm changing FormViewMode
FormView1.changeMode(FormViewMode.ReadOnly); [ <-- NOT WORKING ]
To display user profile, I'm passing user-id from querystring (querystring field = "user")
So the valid URL looks like :
/UserProfile.aspx?user=121
What I want to achieve is :
If (user_IS_Logged_In)
//Some basic tasks like setting welcome message label with username/email etc.
If (querystring_is_EMPTY OR querystring_field_is_incorrect OR user_IS_NOT_Logged_IN)
//Remove the Edit and Cancel buttons
If (querystring_field_is_exist)
//initialize user_id (this will be passed to ShowUserDetails(user_id))
If (user_IS_Logged_In AND querystring_is_exist)
If querystring value and logged in user_id ARE NOT EQUAL THEN
//Again Remove the Edit and Cancel buttons
P.S --> I'm thinking to add an UpdatePanel around the FormView Once I achieve above tasks, for consistent look.
I know the problem is quite difficult to understand so feel free to ask details.
I will provide the code as needed.

How to access literal control in javascript

I have got a literal control on page (with some data on it). i want to access it in javascript and want to put some text on it. please tell me how can i access literal control in javascript. (i am using asp.net)
My code in javascript (but not working):
lths = document.getElementById("<%= lblhs.ClientID %>");
lths.innerHTML = 'this is text line"
You can find it using document.getElementById('<%= myControl.ClientID %>') or if you are using .NET 4.0 you can directly set the id field to be pulled by javascript. Alternatively you can use jquery's selectors. Your code isn't working because the Literal control doesn't render as an element, just static text. You can place a span around it, or use a Label control, which renders as a span for you.
I don't think that you can access a literal control from your javascript client code because a literal control just renders it's pure value without any surrounding tags. So you don't really have an element which you could get by id.
What you could to is changing the literal control to a label control. This renders out as a html span tag by default. Like that you can select it on the client side.
Another option would be to write a span or div tag in your literal control on the server side like this:
myLiteral.Text = "<div id=\"myDiv\">Some Text here</div>"
on the client you could select the elemnt by using:
var myDiv = document.getElementById('myDiv');
Just to rule out the obvious (since no one else mentioned it), this is a syntax error in JS:
lths.innerHTML = 'this is text line"
Not sure if this was a typing error here, or if you copied it from your code. You can use either " or ' but not both to surround a string. Also, you should use terminating semi-colons as best practice (although it's not required).
lths.innerHTML = 'this is text line';
The <%= myControl.ClientId %> technique does not work when you are using master pages. That could be the case.
What you can do is: Take a hidden field. Save the ID of the label in the hidden field. Access the value attribute to get the ID and then use document.getElementByID('HiddenField.Value') to get the control.

Difference between assigning a property and adding a attribute in a asp.net control

I am creating ASP.NET textbox controls dynamically. I want to know the difference between assigning the property of the control and adding it as an attribute.
For ex:
I can do:
TextBox txtBox = new TextBox();
txtBox.MaxLength = 100;
or I could do
txtBox.Attributes.Add("maxlength", "100);
The first example is strongly typed, so the compiler will check to make sure that a) MaxLength exists and b) an integer is set for that property.
The second example will work, but the compiler has no way to check to see if the attribute you are adding is correct.
In the end they get translated to the maxlength HTML attribute. TextBox offers a property mostly for convenience.
First one is better because of misspelling or wrong using.
Also first one is more readable.

Setting Focus with ASP.NET AJAX Control Toolkit

I'm using the AutoComplete control from the ASP.NET AJAX Control Toolkit and I'm experiencing an issue where the AutoComplete does not populate when I set the focus to the assigned textbox.
I've tried setting the focus in the Page_Load, Page_PreRender, and Page_Init events and the focus is set properly but the AutoComplete does not work. If I don't set the focus, everything works fine but I'd like to set it so the users don't have that extra click.
Is there a special place I need to set the focus or something else I need to do to make this work? Thanks.
We had exactly the same problem. What we had to do is write a script at the bottom of the page that quickly blurs then refocuses to the textbox. You can have a look at the (terribly hacky) solution here: http://www.drive.com.au
The textbox id is MainSearchBox_SearchTextBox. Have a look at about line 586 & you can see where I'm wiring up all the events (I'm actually using prototype for this bit.
Basically on the focus event of the textbox I set a global var called textBoxHasFocus to true and on the blur event I set it to false. The on the load event of the page I call this script:
if (textBoxHasFocus) {
$get("MainSearchBox_SearchTextBox").blur();
$get("MainSearchBox_SearchTextBox").focus();
}
This resets the textbox. It's really dodgy, but it's the only solution I could find
this is waste , its simple
this is what you need to do
controlId.focus(); in C#
controlID.focus() in VB
place this in page load or button_click section
eg. panel1.focus(); if panel1 has model popup extender attached to it, then we put this code in page load section
How are you setting focus? I haven't tried the specific scenario you've suggested, but here's how I set focus to my controls:
Public Sub SetFocus(ByVal ctrl As Control)
Dim sb As New System.Text.StringBuilder
Dim p As Control
p = ctrl.Parent
While (Not (p.GetType() Is GetType(System.Web.UI.HtmlControls.HtmlForm)))
p = p.Parent
End While
With sb
.Append("<script language='JavaScript'>")
.Append("function SetFocus()")
.Append("{")
.Append("document.")
.Append(p.ClientID)
.Append("['")
.Append(ctrl.UniqueID)
.Append("'].focus();")
.Append("}")
.Append("window.onload = SetFocus;")
.Append("")
.Append("</script")
.Append(">")
End With
ctrl.Page.RegisterClientScriptBlock("SetFocus", sb.ToString())
End Sub
So, I'm not sure what method you're using, but if it's different than mine, give that a shot and see if you still have a problem or not.
What I normally do is register a clientside script to run the below setFocusTimeout method from my codebehind method. When this runs, it waits some small amount of time and then calls the method that actually sets focus (setFocus). It's terribly hackish, but it seems you have to go a route like this to stop AJAX from stealing your focus.
function setFocusTimeout(controlID) {
focusControlID = controlID;
setTimeout("setFocus(focusControlID)", 100);
}
function setFocus() {
document.getElementById(focusControlID).focus();
}
I found the answers from Glenn Slaven and from Kris/Alex to get me closer to a solution to my particular problem with setting focus on an ASP.NET TextBox control that had an AutoCompleteExtender attached. The document.getElementById(focusControlID).focus() kept throwing a javascript error that implied document.getElementById was returning a null object. The focusControlID variable was returning the correct runtime ClientID value for the TextBox control. But for whatever reason, the document.getElementById function didn't like it.
My solution was to throw jQuery into the mix, as I was already using it to paint the background of any control that had focus, plus forcing the Enter key to tab through the form instead of firing a postback.
My setFocus function ended up looking like this:
function setFocus(focusControlID) {
$('#' + focusControlID).blur();
$('#' + focusControlID).focus();
}
This got rid of the javascript runtime error, put focus on the desired TextBox control, and placed the cursor within the control as well. Without first blurring then focusing, the control would be highlighted as if it had focus, but the cursor would not be sitting in the control yet. The user would still have to click inside the control to begin editing, which would be an UX annoyance.
I also had to increase the timeout from 100 to 300. Your mileage my vary...
I agree with everyone that this is a hack. But from the end-user's perspective, they don't see this code. The hack for them is if they have to manually click inside the control instead of just being automatically placed inside the control already and typing the first few letters to trigger the auto lookup functionality. So, hats off to all who provided their hacks.
I hope this is helpful to someone else.

Resources