Forcing TargetControl Textbox to use a value in the AutocompleteExtender - asp.net-2.0

I'm sure I'm going to have to write supporting javascript code to do this. I have an autocomplete extender set up that selects values from a database table, when a selection is made, i would like it to set the ID of the value selected to a hidden control. I can do that by handling a value change on the text box and making a select call to the database, Select idCompany from Companies Where CompanyName = "the text box value";
The most important thing is to constrain the values of the text box that is the targetcontrol for the autocomplete extender to ONLY use values from the autocomplete drop down. Is this possible with that control, is there examples somewhere? is there a better control to use (within the ajax control toolkit or standard .net framework - not a third party control)?
I'm going to be trying to work out some javascript, but I'll be checking back to this question to see if anyone has some useful links. I've been googling this last night for quite a while.
Update: I did not get an answer or any useful links, I've posted an almost acceptable user control that does what I want, with a few workable issues.

No one was able to give me an answer. This has been an ongoing saga. It started when I was trying to find a solution not using drop down lists for large amounts of data. I have run into issues with this so many times in previous projects. This seems to be workable code. Now I need to know how to supply a AutoPostBack Property, and allow for some events, such as SelectedValueChanged. And due to the javascript, it will conflict with another control, if I have more than one of them on the same page. Well, that's some of the known issues I'm looking at with the code, but it's a start and definately better than looking at a hung browser for 3 or 4 minutes while the drop down is loading 30k list items.
This code is assuming there is an asmx file with the script methods GetCompanyListBySearchString and GetCompanyIDByCompanyName.
ASPX FILE
<%# Control Language="C#" AutoEventWireup="true" CodeFile="SelectCompany.ascx.cs" Inherits="Controls_SelectCompany" %>
<%# Register TagPrefix="ajaxToolkit" Namespace="AjaxControlToolkit" Assembly="AjaxControlToolkit" %>
<script language="javascript" type="text/javascript">
var txtCompanyIDHiddenField = '<%= fldCompanyID.ClientID %>';
var txtCompanyIDTextBox = '<%= txtCompany.ClientID %>';
function getCompanyID() {
if (document.getElementById(txtCompanyIDTextBox).value != "")
CompanyService.GetCompanyIDByCompanyName(document.getElementById(txtCompanyIDTextBox).value, onCompanyIDSuccess, onCompanyIDFail);
}
function onCompanyIDSuccess(sender, e) {
if (sender == -1)
document.getElementById(txtCompanyIDTextBox).value = "";
document.getElementById(txtCompanyIDHiddenField).value = sender;
}
function onCompanyIDFail(sender, e) {
document.getElementById(txtCompanyIDTextBox).value = "";
document.getElementById(txtCompanyIDHiddenField).value = "-1";
}
function onCompanySelected() {
document.getElementById(txtCompanyIDTextBox).blur();
}
</script>
<asp:TextBox ID="txtCompany" runat="server" onblur='getCompanyID()'
/><ajaxToolkit:AutoCompleteExtender runat="server" ID="aceCompany" CompletionInterval="1000" CompletionSetCount="10"
MinimumPrefixLength="2" ServicePath="~/Company/CompanyService.asmx" ServiceMethod="GetCompanyListBySearchString"
OnClientItemSelected="onCompanySelected" TargetControlID="txtCompany" />
<asp:HiddenField ID="fldCompanyID" runat="server" Value="0" />
CODE BEHIND
[System.ComponentModel.DefaultProperty("Text")]
[ValidationProperty("Text")]
public partial class ApplicationControls_SelectCompany : System.Web.UI.UserControl
{
public string Text
{
get { return txtCompany.Text; }
set
{
txtCompany.Text = value;
//this should probably be read only and set the value based off of ID to
// make certain this is a valid Company
}
}
public int CompanyID
{
get
{
int ret = -1; Int32.TryParse(fldCompanyID.Value, out ret); return ret;
}
set
{
fldCompanyID.Value = value.ToString();
//Todo: should set code to set the Text based on the ID to keep things straight
}
}
}

Thanks for your post here. It is useful, however, it is assuming that everyone knows the setup to get the webservice called by a javascript function.
Sorry to be soo newbie, but I couldn't get the webservice called from client-side.
I read this documentation: http://msdn.microsoft.com/en-us/magazine/cc163499.aspx
Furthermore, I found an interesting post that explains how to create/get a name value pair which is pretty much what you are expecting as far as I understood:
http://blogs.msdn.com/phaniraj/archive/2007/06/19/how-to-use-a-key-value-pair-in-your-autocompleteextender.aspx
Sorry if I misunderstood you, but I am just trying to guide other people that pass through the same situation.
Thanks a lot.

You can check the value of the selection by trapping on ClientItemSelected event and ensure that it is not blank.

Related

ASP.NET / UserControl, ViewState and losing Property values

this is about ASP.NET, ViewState, UserControls and losing the values of my properties. It is an classic question by know, I know, and even though I have searched here and on Google for a resolution to this problem, I havent succeeded. On the contrary, the more I test different things, the less I understand it seems.
On top of this I am using ext.net and their so called DirectMethod's but I dont think that has much to do with this problem. There are numerous questions I have and I hope that this text will be fairly readable and understandable =)
The UserControl
I have a UserControl, Customers.ascx, that contains some Properties. The "most" important is *_CustomerId*. The _CustomerId is set in code-behind, in ext.net's "DirectMethod" like this (code below from the Page Customers.aspx):
[DirectMethod]
public void SetCustomer()
{
RowSelectionModel sm = GridPanel2.SelectionModel.Primary as RowSelectionModel;
if (sm.SelectedRow != null)
{
uint customerId = uint.Parse(sm.SelectedRow.RecordID);
customer_modify._CustomerId = customerId;
}
}
The "customer_modify" is the instance of the UserControl as defined in Customers.aspx (a Page, not a UserControl):
<asp:Content ID="Content2" ContentPlaceHolderID="CPH_center" runat="server">
<CP:Customer ID="customer_modify" runat="server" _IsCreateMode="false" ViewStateMode="Enabled" />
</asp:Content>
In that Page, Customers.aspx, I have ext.net GridPanel that lists the Customers and when I click the rows in the GridPanel the (Direct)method SetCustomer is executed.
As you can see in the SetCustomer-method, the property "_CustomerId" is updated with an uint, so lets take a look at the Property in the UserControl:
public uint _CustomerId
{
get
{
object o = ViewState["_CustomerId"];
if (o == null)
return 0;
return (uint)o;
}
set
{
object o = ViewState["_CustomerId"];
ViewState["_CustomerId"] = value;
SetCustomer();
}
}
As you can see, I am using the ViewState-thingie and it was my hope that the state, ie the value of the properties would be remembered. They are not.
When I click a Row in the GridPanel the first time I can see (by breaking) that the ViewState["_CustomerId"] == null which is alright. I see thereafter that the setter for _CustomerId is executed and that the ViewState["_CustomerId"] is assigned the RecordID (uint).
I now click another Row in the GridPanel and the SetCustomer-method is executed again. I break in the setter for _CustomerId and take a look at what the ViewState["_CustomerId"] is BEFORE assigning it. It is 0, but I expect it to be the value from the previous Row clicked.
Why is it 0? What am I missing?
Also:
I actually have two of there UserControls on the Page, the other one named "customer_create":
<ext:Window
ID="Window_CreateNewCustomer"
runat="server"
Icon="New"
Title="Skapa ny kund"
Hidden="true"
Width="480"
Height="370"
Modal="true">
<Content>
<CP:Customer ID="customer_create" runat="server" Title="Skapa ny kund" _IsCreateMode="true" />
</Content>
</ext:Window>
What disturbs me a lot is that each and every time I click on a Row in the GridPanel the Page_Load in the UserControl is executed twice, even though I am only updating one of them in the SetCustomer()-method.
Why is that?
Any tips, ideas and help would be greatly appreciated.
ViewState is serialized, enciphered and sent to the client as a hidden form field so that it may be reconstituted when something triggers a form submission. A [DirectMethod] does not go through form submission (it's processed as an AJAX call), so it can neither read nor write ViewState data, unless round-tripping of this data is specifically requested with ViewStateMode.Enabled.
On any given request directed to a form, the Load event will be fired from the Page, and thus received by every user control on the page that subscribes to the event at the expected phase of the page processing lifecycle -- whether it's two instances of one UserControlor two different UserControls, it's two subscribers and therefore two calls (one to each instance).

How to validate special character entry in any controls within a page?

I have designed a page where user can write messages and send within a group but i want that if they enter any special character like <>?## etc a msg should be displayed irrespective of the crashing of the page.
Can anyone help me out???
for that you have to use javaScript validation or any server site validation
for javaScript
function validate(inputText)
{
if(inputText.match(/[<>]/))
return false;
}
function TextBoxValidate()
{
var txt1=document.getElementById(TextBoxId).value;
if(!(validate(inputText)))
{
alert("incorrect text")
return false;
}
else
return true;
}
call these function in that text box where you want to validate by using onClientClick="return TextBoxValidate();"
You have 2 possibilities for doing that.
A) You are adding a regularexpression validator to each control
B) You use a customvalidator which you can bind to each control too
First solution is the better one for you.
How you do it? See here: http://www.codeproject.com/KB/validation/aspnetvalidation.aspx
It's not reccommended but you can use ValidateRequest="false" in the page declaration to allow values like that to be sucessfully posted back.
e.g. <%# Page Title="" Language="C#" ValidateRequest="false"..

How to set focus to a web control in ASP.NET

Question: What is the best way to set focus to a web control in ASP .NET.
I can do it, but it's ugly. I have a web control wrapped in a web control hosted on a web page. So, if you do a view | source on the page the id is something like WrapperControl_Control_TextBox.
I've tried the "tried and true" Javascript methods of grabbing the element and setting it's focus: document.getElementByID( "WrapperControl_Control_TextBox" ).focus(); and it didn't work. I'm not sure why.
I know I could possibly do:
document.getElementById( "<%= TextBox.ClientID %>" ).focus(); too, I think. This won't work because of another totally separate error based on the fact you can't dynamically add controls to a header if there is a "<% %>" in the page. GAH.
In the "bottom-most" control, I've tried setting the focus (TextBox.Focus() in Page_Load) and that doesn't work either.
Anyway, the way that works is by simply taking the ControlsCollection of the Page, grabbing the control I need from that, getting it's collection, grabbing the next lower control and so forth.
I only have to do this seven times. So I have eight foreach loops.
Basically, my code is like this:
///////////////////////////////
// On the page
///////////////////////////////
ControlCollection controls = Controls;
foreach( Control control in controls)
{
if ( string.Equals( control.ID, "FormID", StringComparison.InvariantCultureIgnore ) )
{
ControlCollection nextControls = control.Controls;
foreach( Control nextControl in nextControls )
{
if ( string.Equals( nextControl.ID, "DivICareAboutInTheForm", StringComparison.InvariantCultureIgnor ) )
{
ControlCollection nextNextControls = nextControl.Controls;
//:
//:
//Yes, it's that bad and so forth.
//:
//:
}
}
}
}
You can use jQuery to do a search for IDs that end with your textbox name. This way you wont have to call the UniqueID server-side code. Just make sure not to have multiple controls that end with the same name
<script type="text/javascript">
$(document).ready(function() {
$('[id$=txtBox]').focus();
});
</script>
Or, you can use a Class name for the default text box.
<asp:Textbox ID="txtBox" runat="server" cCssClass="defaultTextbox" />
jquery:
$('.defaultTextbox').focus();
You can get around the "cannot add dynamic controls because a <%= %> block exists on the page" error by changing the block to use databinding syntax: <%# TextBox.ClientID %>, and manually calling Page.DataBind() in Page_Load.
If you really want to use the Page_Load method, then you could always call the SetFocus method on the Page object.
Page.SetFocus(myTextBox);

ASP.Net - repeating input boxes on the client side using Repeater

I have the following requirement for creating a user profile in my application:
User should be able to enter multiple phone numbers/email addresses in his profile.
The screen looks somewhat like this:
- By default, on page load a single textbox for phone and email are shown.
- User can click a "+" button to add additional numbers/addresses.
- On clicking the "+" button we need to add another textbox just below the first one. User can add as many numbers/addresses as he wants. On submit, the server should collect all numbers/emails and save it in DB.
I tried using the Repeater control to do this. On page_load I bind the repeater to a "new arraylist" object of size 1. So, this renders fine - user sees a single textbox with no value in it.
When he clicks the "+" button, I ideally want to use javascript to create more textboxes with similar mark-up as the first.
My questions are these:
Can I render the new textboxes anyway using js? I notice that the HTML rendered by the repeater control is somewhat complex (names/ids) etc. and it might not be possible to correctly create those controls on client-side.
If there is a way to do #1, will the server understand that these additional inputs are items in the repeater control? Say, I want to get all the phone numbers that the user entered by iterating over Repeater.DataItems.
Conceptually, is my approach correct or is it wrong to use the Repeater for this? Would you suggest any other approach that might handle this requirement?
Coming from a Struts/JSP background, I am still struggling to get a grip on the .NET way of doing things - so any help would be appreciated.
The repeater control may be a bit of overkill for what you're trying to accomplish. It is mainly meant as a databound control for presenting rows of data.
What you can do is to dynamically create the boxes as part of the Page_Load event (C#):
TestInput.aspx :
<form id="form1" runat="server">
<asp:HiddenField ID="hdnAddInput" runat="server" />
<asp:Button ID="btnPlus" OnClientClick="setAdd()" Text="Plus" runat="server" />
<asp:PlaceHolder ID="phInputs" runat="server" />
</form>
<script type="text/javascript">
function setAdd() {
var add = document.getElementById('<%=hdnAddInput.ClientID%>');
add.value = '1';
return true;
}
</script>
TestInput.aspx.cs:
protected void Page_Load(object sender, EventArgs e)
{
if (ViewState["inputs"] == null)
ViewState["inputs"] = 1;
if (hdnAddInput.Value == "1")
{
ViewState["inputs"] = int.Parse(ViewState["inputs"].ToString()) + 1;
hdnAddInput.Value = "";
}
for (int loop = 0; loop < int.Parse(ViewState["inputs"].ToString()); loop++)
phInputs.Controls.Add(new TextBox() { ID = "phone" + loop });
}
I ended up using a PlaceHolder to dynamically add the text boxes and a HiddenField to flag when another TextBox needed to be added. Since the IDs were matching, it maintains the ViewState of the controls during each postback.
Welcome to the hairball that is dynamically-added controls in ASP.NET. It's not pretty but it can be done.
You cannot add new fields dynamically using javascript because the new field would have no representation in the server-side controls collection of the page.
Given that the requirements are that there is no limit to the number of addresses a user can add to the page, your only option is to do "traditional" dynamic ASP.NET controls. This means that you must handle the adding of the control server-side by new-ing a new object to represent the control:
private ArrayList _dynamicControls = new ArrayList();
public void Page_Init()
{
foreach (string c in _dynamicControls)
{
TextBox txtDynamicBox = new TextBox();
txtDynamicBox.ID = c;
Controls.Add(txtDynamicBox);
}
}
public void AddNewTextBox()
{
TextBox txtNewBox = new TextBox();
txtNewBox.ID = [uniqueID] // Give the textbox a unique name
Controls.Add(txtNewBox);
_dynamicControls.Add([uniqueID]);
}
You can see here that the object that backs each dynamically-added field has to be added back to the Controls collection of the Page on each postback. If you don't do this, data POSTed back from the field has nowhere to go.
If you want to user the repeater, I think the easiest way is to put the repeater in a ASP.Net AJAX update panel, add the extra textbox on the sever side.
There are definitely other way to implement this without using repeater, and it maybe much easier to add the textbox using js.
No, but you can create input elements similar to what TextBox controls would render.
No. ASP.NET protects itself from phony data posted to the server. You can't make the server code think that it created a TextBox earlier by just adding data that it would return.
The approach is wrong. You are trying to go a middle way that doesn't work. You have to go all the way in either direction. Either you make a postback and add the TextBox on the server side, or you do it completely on the client side and use the Request.Form collection to receive the data on the server side.

How to set Page.IsValid in ASP.Net

When the page class property IsValid is read only, how can I set it using my own validation method?
So far all I've been able to do is set this property by calling Page.Validate().
How can I write my own functionality that will change the IsValid property just like Page.Validate()?
You don't set IsValid directly instead you call Validate() method of the Page object. If you have your custom validation methods then you need to use CustomValidator object and set that function in its server side validation property.
<asp:CustomValidator ID="YourValidator" runat="server" SetFocusOnError="true"
ControlToValidate="YourControl"
ClientValidationFunction="YOUR_JAVASCRIPT_FUNCTION"
OnServerValidate="YOUR_SERVER_VALIDATION_FUNCTION" Text="*" />
I know this is old, but, I needed to do something similar, basically forcing the IsValid property to false (don't ask why). Here is what I did basically (what you see here is my proof of concept):
Added this to the .aspx page:
<asp:TextBox ID="txtDummy" runat="server" Visible="false" />
<asp:RangeValidator ID="rvDummy" ControlToValidate="txtDummy" runat="server" MinimumValue="1" MaximumValue="2" />
And then I added this to the code behind:
bool makeMyPageInvalid = true;
if (makeMyPageInvalid)
txtDummy.Text = "0";
Page.Validate();
if (Page.IsValid)
ScriptManager.RegisterStartupScript(Page, Page.GetType(), "test", "alert('valid');", true);
else
ScriptManager.RegisterStartupScript(Page, Page.GetType(), "test", "alert('not valid');", true);
You can see that this only allows you to force the page validation to an invalid state. You can use any validator or reason to set this. Hope this helps someone!
The IsValid property is read-only because it is intended for use with server and client-side validators like the RequiredFieldValidator and RegularExpressionValidator. It's read-only because you can't force a page to be valid programmatically. "Valid" in this context means all the validators on the page evaluate to true.
If you feel like using some JavaScript you can do it in the client-side by modifying the variable Page_IsValid like this:
function pageLoad() {
Page_IsValid = false;
}
I use this just in case someone clicks the submit button w/o entering data. Then I can display an alert like this:
function valid() {
if (!Page_IsValid) {
alert("Some Questions Remain Unanswered and are Marked with a Red Asterisc. ( * )");
}
(at the beginning I thought 'who would submit a form w/o data' but sooner rather than later I realized it happens)
This is a really old question, but it came up in a search so I thought I'd add my answer to it. First, create an extension method in one of your helper classes.
public static IEnumerable<T> GetAllControlsOfType<T>(this Control parent) where T : Control
{
var result = new List<T>();
foreach (Control control in parent.Controls)
{
if (control is T)
{
result.Add((T)control);
}
if (control.HasControls())
{
result.AddRange(control.GetAllControlsOfType<T>());
}
}
return result;
}
Now in your code behind file, loop over every validator on the page that is not validating.
foreach (var validator in Page.GetAllControlsOfType<BaseValidator>().Where(w => !w.IsValid))
{
validator.IsValid = true;
}

Resources