Today i will introduce new ASP.net composite server control "Auto Complete"
using jQuery Auto Complete with few plugin modification that will support the main functionality of our control.
Let us go fast in control properties, the new control contains several properties most of them belongs to plugin itself and others will handle the control.
Properties belongs to plugin:
Note: txtAutoComplete is an instance of TextBox declared within the control
The other method is RegisterPluginScript() that will register the formatted script that will initialize the autocomplete instance.
Note: not allowed to forget passing "XMLElementKey and XMLElementTextAttribute" if you forgotten them or one of them the control will not complete it is functionality since those are the main functionality key for the plugin data also you will note that data will be formatted for the plugin from XML data to array to be handled by the plugin.
Prerequisites:
Note: To request the text you get the property called "SelectedText" and for value you will get the property called "SelectedValue"
using jQuery Auto Complete with few plugin modification that will support the main functionality of our control.
Let us go fast in control properties, the new control contains several properties most of them belongs to plugin itself and others will handle the control.
Properties belongs to plugin:
- MinimumChars: get or set the minimum characters to fire the autocomplete action * default = 1 *
- MaximumRows: get or set the maximum rows to be returned by the plugin * default = 5 *
- AutoFill: get or set autoFill property for the auto complete plugin "if true plugin will set input text with the first item" * default is false *
- MustMatch: get or set mustMatch property for the auto complete plugin* default is false *
- MatchContains:get or set matchContains property for the auto complete plugin* default is false *
- SelectFirst: get or set selectFirst property for the auto complete plugin * default is true *
- Scroll: get or set scroll property for the auto complete plugin * default is true *
- ScrollHeight: get or set scrollHeight property for the auto complete plugin * default is 180px *
- Delay: get or set delay property for the auto complete plugin* default is 400 mili seconds *
Properties belongs to control:
- TextBoxCssClass: get or set text box control css class
- PostURL: the url to post the jquery ajax call ** this url should url to an aspx page that will contain the method **
- MethodName: method name to be called ** this method should write response of type "text/xml" and has parameter called "searchKey" as string**
- MethodNameRequestKey: get or set requet key for method name "it is the query string key for method name if you need to specify your request such you post several posts to the same page"
- SelectedText (updated): get or set the text selected by user
- SelectedValue (updated): get or set the value selected by user
- XMLElementKey: get or set xmlelement key such as "user, employee and etc"
- XMLElementTextAttribute (updated): get or set xml element text attribute such as "name, department and etc"
- XMLElementValueAttribute (new): get or set xml element value attribute such as "id"
- IsRequired (new): provide option if user need to make the control required or not "default is false"
- IsSymbolsDisabled (new): provide option if user need to make the control disable symbols (special characters) or not "default is true"
- ValidationGroup (new): get or set the validation related group
- ErrorMessage (new): get or set required validator error message
- LettersErrorMessage (new): get or set the special characters error message
- LettersValidationExpression (new): get or set the special characters validation expression
- ErrorMessageDisplay (new): get or set validation message display layout (value of enumeration {Inline, Breakline} ) "default is inline"
Now i will show you the main two methods in the control:
protected override void CreateChildControls()
{
Controls.Clear();
// setting ids
txtAutoComplete.ID = "txtAutoComplete";
hdfValue.ID = "hdfValue";
// check if user provide cssclass for text input
if (!string.IsNullOrEmpty(TextBoxCssClass))
{
txtAutoComplete.CssClass = TextBoxCssClass + " autocompleteinput";
}
else
txtAutoComplete.CssClass = "autocompleteinput";
#region Required Field Validators
// text input RFV
rfvTextInput.Display = ValidatorDisplay.Dynamic;
rfvTextInput.ControlToValidate = "txtAutoComplete";
rfvTextInput.ErrorMessage = ErrorMessage;
// text input REXV
rexvTextInput.Display = ValidatorDisplay.Dynamic;
rexvTextInput.ControlToValidate = "txtAutoComplete";
rexvTextInput.ErrorMessage = LettersErrorMessage;
rexvTextInput.ValidationExpression = LettersValidationExpression;
// check if user need this instance required or not
if (!IsRequired)
{
rfvTextInput.Enabled = false;
}
// check if user need prevent user from entering special characters
if (!IsSymbolsDisabled)
{
rexvTextInput.Enabled = false;
}
if (!string.IsNullOrEmpty(ValidationGroup))
{
txtAutoComplete.ValidationGroup = ValidationGroup;
rfvTextInput.ValidationGroup = ValidationGroup;
rexvTextInput.ValidationGroup = ValidationGroup;
}
#endregion
#region User Interface
// adding the text box
Controls.Add(txtAutoComplete);
if (ErrorMessageDisplay == ErrorMessageDisplayLayout.BreakLine)
Controls.Add(new LiteralControl("<br />"));
// add validators
Controls.Add(rfvTextInput);
Controls.Add(rexvTextInput);
// adding the hidden field
Controls.Add(hdfValue);
#endregion
// register client script
RegisterPluginScript();
}
Note: txtAutoComplete is an instance of TextBox declared within the control
The other method is RegisterPluginScript() that will register the formatted script that will initialize the autocomplete instance.
private void RegisterPluginScript()
{
try
{
if (string.IsNullOrEmpty(XMLElementKey) || string.IsNullOrEmpty(XMLElementTextAttribute))
return;
// if user never specify XMLElementValueAttribute --> control will assign the same text element attribute for value element attribute
if (string.IsNullOrEmpty(XMLElementValueAttribute))
XMLElementValueAttribute = XMLElementTextAttribute;
string key = "AutoComplete" + this.ID;
if (Page.ClientScript.IsClientScriptBlockRegistered(GetType(), key))
return;
StringBuilder scriptValue = new StringBuilder();
scriptValue.Append("<script type=\"text/javascript\">");
scriptValue.Append("$(document).ready(function () {");
if (!string.IsNullOrEmpty(MethodNameRequestKey) && !string.IsNullOrEmpty(MethodName))
scriptValue.AppendFormat("$('input#{0}').autocomplete('{1}?{2}={3}&',", this.txtAutoComplete.ClientID, PostURL, MethodNameRequestKey, MethodName);
else
scriptValue.AppendFormat("$('input#{0}').autocomplete('{1}?',", this.txtAutoComplete.ClientID, PostURL);
scriptValue.Append("{parse: function (xml) {");
scriptValue.Append("var rows = new Array();");
scriptValue.AppendFormat("$(xml).find('{0}').each(function (i) ", XMLElementKey);
scriptValue.Append("{rows[i] = {");
scriptValue.AppendFormat("data: $(this), value: $(this).attr('{0}'), result: $(this).attr('{1}')", XMLElementValueAttribute, XMLElementTextAttribute);
scriptValue.Append("};});");
scriptValue.Append("return rows;");
scriptValue.Append("},");
scriptValue.Append("formatItem: function (row, i, n) {");
scriptValue.AppendFormat("return row.attr('{0}');", XMLElementTextAttribute);
scriptValue.Append("},");
scriptValue.AppendFormat("minChars: {0},", MinimumChars.ToString());
scriptValue.AppendFormat("max: {0},", MaximumRows.ToString());
scriptValue.AppendFormat("autoFill: {0},", AutoFill.ToString().ToLower());
scriptValue.AppendFormat("mustMatch: {0},", MustMatch.ToString().ToLower());
scriptValue.AppendFormat("matchContains: {0},", MatchContains.ToString().ToLower());
scriptValue.AppendFormat("selectFirst: {0},", SelectFirst.ToString().ToLower());
scriptValue.AppendFormat("scroll: {0},", Scroll.ToString().ToLower());
scriptValue.AppendFormat("scrollHeight: {0},", ScrollHeight.ToString());
scriptValue.AppendFormat("delay: {0}", Delay.ToString());
scriptValue.Append("});");
scriptValue.AppendFormat("$('input#{0}').result(function (event, data, value) ", this.txtAutoComplete.ClientID);
scriptValue.Append("{");
scriptValue.AppendFormat("var hidden = $('input#{0}');", this.hdfValue.ClientID);
scriptValue.Append("hidden.val(value);");
scriptValue.Append("}); });");
scriptValue.Append("</script>");
Page.ClientScript.RegisterStartupScript(GetType(), key, scriptValue.ToString());
}
catch { }
}
Note: not allowed to forget passing "XMLElementKey and XMLElementTextAttribute" if you forgotten them or one of them the control will not complete it is functionality since those are the main functionality key for the plugin data also you will note that data will be formatted for the plugin from XML data to array to be handled by the plugin.
Prerequisites:
- jQuery plugin registered
- jquery.autocomplete registered "new modified one you can get all files you will need here as zip file called AutoCompleteFiles.zip contains three files (plugin, CSS file for results "don not change classes names" and image for loading)"
- ASPX page that will handle the posts by the plugin "will be discussed soon"
- Registering control in web.config file
<add tagPrefix="dev" namespace="CustomControls" assembly="CustomControls" />
- Adding the control to your ASPX page
<dev:AutoComplete runat="server" ID="acEmployeeName" MaximumRows="10" MinimumChars="1" MatchContains="true" MethodName="SearchUsers" PostURL="http://localhost/SiteName/Pages/AjaxHelper.aspx" MethodNameRequestKey="op" TabIndex="3" XMLElementKey="User" XMLElementTextAttribute="Name" XMLElementValueAttribute="ID" />
- The ASPX page that will handle the ajax calls posted by the plugin will have the folloing implementation
protected void Page_Load(object sender, EventArgs e) { if (Request["op"] != null && Request["op"] == "SearchUsers") { if (Request["searchKey"] != null) SearchUsers(Request["searchKey"]); } } private void SearchUsers(string searchKey) { StringBuilder usersString = new StringBuilder(); // sample data --> data can be retrieved from any source and format the xml with and values you want string[] users = new string[] { "Ahmed", "Mohamed", "Fakhry", "Khalil", "Mansor" }; // build the XML usersString.Append("<?xml version=\"1.0\" encoding=\"utf-8\" ?>"); usersString.Append("<Users>"); for (int i = 0; i < users.Length; i++) if (users[i].ToLower().Contains(searchKey.ToLower())) usersString.AppendFormat("
", users[i], i.ToString()); usersString.Append("</Users>"); Response.ClearContent(); Response.ContentType = "text/xml"; Response.Write(usersString.ToString()); Response.End(); }
As noted the page will write an XML responce that will be reformatted by the control according to "XMLElementKey, XMLElementTextAttribute & XMLElementValueAttribute" properties provided --> here
- XMLElementKey: User
- XMLElementTextAttribute: Name
- XMLElementValueAttribute: ID
Note: If XMLElementValueAttribute same as XMLElementTextAttribute you can specify XMLElementTextAttribute only and the control will consider value attribute as the same as the text attribute.
Note: To request the text you get the property called "SelectedText" and for value you will get the property called "SelectedValue"
Note: new updates added as the following
- Each item will have text and value.
- If the user never specify new property "XMLElementValueAttribute" the control will specify the text property to the value property.
Finally i hope for all good luck and i wish that article helpful
Note: you can find the complete source code here that is called "CustomControls.zip"