Hello.
I have a problem with RadAutoCompleteBox.EntryAdded server event. I created a user control (.ascx) called PeopleAndMachinesPicker with RadAutoCompleteBox (InputType="Token") in it.
RadAutoCompleteBox causes full page postback when server-side EntryAdded event handler is set. I tried to wrap my PeopleAndMachinesPicker control with UpdatePanel, but it causes JavaScript error:
"Microsoft JScript runtime error: Sys.InvalidOperationException: Two components with the same id 'PeopleAndMachinesPicker1_RadAutoCompleteBox2' can't be added to the application."
How can I process server-side EntryAdded event without full page postback? I tried __doPostBack() to update other controls on the page on ClientEntryAdded javascript event handler, but it's not suitable for my PeopleAndMachinesPicker control isolation.
Browser used: IE9 (9.0.8112.16421) 64 bit
Telerik.Web.UI assembly version: 2012.2.1002.35
17 Answers, 1 is accepted
Default.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="MainPage.aspx.cs" Inherits="RC.ITRequest.UI.MainPage" %><%@ Register Assembly="Telerik.Web.UI, Version=2012.2.1002.35, Culture=neutral, PublicKeyToken=121fae78165ba3d4" Namespace="Telerik.Web.UI" TagPrefix="telerik" %><%@ Register Src="~/_controltemplates/RC.ITRequest.UI/ItemsToRevoke.ascx" TagName="ItemsToRevoke" TagPrefix="uc1" %><%@ Register Src="~/PeopleAndMachinesPicker.ascx" TagName="PeopleAndMachinesPicker" TagPrefix="uc1" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"> <meta http-equiv="X-UA-Compatible" content="IE=9" /> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title></title> <script src="/_LAYOUTS/jquery-1.8.1.min.js" type="text/javascript"></script> <link rel='stylesheet' type='text/css' href='/_LAYOUTS/STYLES/RC.ITRequest.UI/Common.css' /> <link rel='stylesheet' type='text/css' href='/_LAYOUTS/STYLES/RC.ITRequest.UI/ItemsToRevoke.css' /></head><body> <form id="form1" runat="server"> <div> <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager> <table class="top-aligned"> <tr> <td style="width: 50%; height: 100%;"> <p class="header-text">Services</p> <div class="requestors"> <p>IT Request for users</p> <p> <asp:UpdatePanel runat="server"> <ContentTemplate> <uc1:PeopleAndMachinesPicker runat="server" ID="PeopleAndMachinesPicker1" IncludeComputers="True" TopRowsCount="10" SingleChoice="False" Width="500px" DropDownHeight="300px" DropDownWidth="500px" /> </ContentTemplate> </asp:UpdatePanel> </p> </div> <div class="tab-content" id="ItemsToRevoke"> <asp:UpdatePanel ID="ItemsToRevokeUpdatePanel" runat="server" > <ContentTemplate> <uc1:ItemsToRevoke ID="ItemsToRevoke1" runat="server" /> </ContentTemplate> </asp:UpdatePanel> </div> </td> </tr> </table> </div> </form></body></html>Default.aspx.cs
using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;namespace RC.ITRequest.UI{ public partial class MainPage : System.Web.UI.Page { protected void Page_Init(object sender, EventArgs e) { PeopleAndMachinesPicker1.EntryAdded += PeopleAndMachinesPicker1_EntryAdded; } void PeopleAndMachinesPicker1_EntryAdded(object sender, Telerik.Web.UI.AutoCompleteEntryEventArgs e) { ItemsToRevoke1.Requestors = PeopleAndMachinesPicker1.Entries; } }}PeopleAndMachinesPicker.ascx
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="PeopleAndMachinesPicker.ascx.cs" Inherits="RC.SP.PeopleAndMachinesPicker.PeopleAndMachinesPicker" %><%@ Register Assembly="Telerik.Web.UI, Version=2012.2.1002.35, Culture=neutral, PublicKeyToken=121fae78165ba3d4" Namespace="Telerik.Web.UI" TagPrefix="telerik" %><script type="text/javascript"> jQuery(document).ready(function () { var $input = jQuery("#<%=RadAutoCompleteBox2.ClientID%> input[name='" + "<%=RadAutoCompleteBox2.ClientID%>".replace('_', '$') + "']"); if(<%=PreventEditJS%>) $input.attr('readonly', 'readonly'); else if(<%=FocusedJS%>) $input.focus(); });</script><telerik:RadAutoCompleteBox runat="server" ID="RadAutoCompleteBox2" InputType="Token" />PeopleAndMachinesPicker.ascx.cs
using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;using Telerik.Web.UI;namespace RC.SP.PeopleAndMachinesPicker{ public partial class PeopleAndMachinesPicker : System.Web.UI.UserControl { public int TopRowsCount { get; set; } public string OnEntryAdded { get; set; } public bool SingleChoice { get; set; } private bool _focused = false; public string FocusedJS { get { return _focused.ToString().ToLowerInvariant(); } } public event AutoCompleteEntryEventHandler EntryAdded { add { RadAutoCompleteBox2.EntryAdded += value; } remove { RadAutoCompleteBox2.EntryAdded -= value; } } public string PreventEditJS { get { if (!SingleChoice) return false.ToString().ToLowerInvariant(); return (!EnableAutocomplete).ToString().ToLowerInvariant(); } } const string vsEnableAutocomplete = "EnableAutocomplete"; private bool EnableAutocomplete { get { return (bool)(ViewState[vsEnableAutocomplete] ?? true); } set { ViewState[vsEnableAutocomplete] = value; } } public IEnumerable<string> Entries { get { return RadAutoCompleteBox2.Entries.OfType<AutoCompleteBoxEntry>().Select(entry => entry.Text); } set { } } protected void Page_Init(object sender, EventArgs e) { RadAutoCompleteBox2.EntryAdded += RadAutoCompleteBox2_EntryAdded; RadAutoCompleteBox2.EntryRemoved += RadAutoCompleteBox2_EntryAdded; } void RadAutoCompleteBox2_EntryAdded(object sender, AutoCompleteEntryEventArgs e) { _focused = true; if(SingleChoice) EnableAutocomplete = (RadAutoCompleteBox2.Entries.Count == 0); } private const string EntryAddedHandlerName = "AutocompleteBoxEntryAdded"; protected void Page_Load(object sender, EventArgs e) { var UserEntryAddedHandlerName = string.Empty; if (!string.IsNullOrEmpty(OnEntryAdded)) UserEntryAddedHandlerName = OnEntryAdded + "(sender, eventArgs);"; Page.ClientScript.RegisterClientScriptBlock(this.GetType(), EntryAddedHandlerName, string.Format(@"function {0}(sender, eventArgs){{ {1}// user's OnClientEntryAdded handler // custom code }}", EntryAddedHandlerName, UserEntryAddedHandlerName), true); Page.LoadComplete += new EventHandler(Page_LoadComplete); } void Page_LoadComplete(object sender, EventArgs e) { RadAutoCompleteBox2.OnClientEntryAdded = EntryAddedHandlerName; List<string> adObjects = new List<string> { "Most", "of", "these", "pages", "are", "in", "the", "Afrikaans", "language", "spoken", "in", "South", "Africa" }; RadAutoCompleteBox2.DataSource = adObjects; } }}ItemsToRevoke.ascx
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="ItemsToRevoke.ascx.cs" Inherits="RC.ITRequest.UI._CONTROLTEMPLATES.RC.ITRequest.UI.ItemsToRevoke" %><div> <table class="items-to-revoke" id="ItemsToRevokeTable" border="0" cellpadding="0" cellspacing="0" style="width: 100%; "> <asp:Repeater ID="ItemsRepeater" runat="server"> <ItemTemplate> <tr> <td> <asp:Label runat="server" Text="<%#(((RepeaterItem)Container).ItemIndex+1).ToString() %>" ></asp:Label> </td> <td> <asp:Label runat="server" Text='<%# Container.DataItem.ToString() %>' ></asp:Label> </td> <td width="71px"><img class="revoke-image" src="../../_LAYOUTS/IMAGES/RC.ITRequest.UI/revokeBackground.png" alt="" ></img></td> </tr> </ItemTemplate> <SeparatorTemplate> <tr><td colspan="3"><hr/></td></tr> </SeparatorTemplate> </asp:Repeater> </table></div>ItemsToRevoke.ascx.cs
using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;using System.Web.UI.HtmlControls;using System.Threading;using RC.SP.PeopleAndMachinesPicker;namespace RC.ITRequest.UI._CONTROLTEMPLATES.RC.ITRequest.UI{ public partial class ItemsToRevoke : System.Web.UI.UserControl { public IEnumerable<string> Requestors { get; set; } protected void Page_Load(object sender, EventArgs e) { Page.LoadComplete += new EventHandler(Page_LoadComplete); } void Page_LoadComplete(object sender, EventArgs e) { ItemsRepeater.DataSource = Requestors; ItemsRepeater.DataBind(); } }}Can you reproduce the problem on a page that contains only with UpdatePanel and autocompletebox in it?
Cat, thank you for reply. Here's the simplified sample.
MainPage.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="MainPage.aspx.cs" Inherits="RC.ITRequest.UI.MainPage" %><%@ Register Assembly="Telerik.Web.UI, Version=2012.2.1002.35, Culture=neutral, PublicKeyToken=121fae78165ba3d4" Namespace="Telerik.Web.UI" TagPrefix="telerik" %><%@ Register Src="~/PeopleAndMachinesPicker.ascx" TagName="PeopleAndMachinesPicker" TagPrefix="uc1" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"> <title></title></head><body> <form id="form1" runat="server"> <div> <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager> <uc1:PeopleAndMachinesPicker runat="server" ID="PeopleAndMachinesPicker1" /> <%--Time output changes in browser => full postback--%> <asp:Label runat="server" ID="txtCurrentTime" /> </div> </form></body></html>MainPage.aspx.cs
using System;namespace RC.ITRequest.UI{ public partial class MainPage : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { txtCurrentTime.Text = DateTime.Now.ToString(); } }}PeopleAndMachinesPicker.ascx
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="PeopleAndMachinesPicker.ascx.cs" Inherits="RC.SP.PeopleAndMachinesPicker.PeopleAndMachinesPicker" %><%@ Register Assembly="Telerik.Web.UI, Version=2012.2.1002.35, Culture=neutral, PublicKeyToken=121fae78165ba3d4" Namespace="Telerik.Web.UI" TagPrefix="telerik" %><asp:UpdatePanel runat="server" UpdateMode="Conditional"> <ContentTemplate> <telerik:RadAutoCompleteBox runat="server" ID="RadAutoCompleteBox2" OnEntryAdded="RadAutoCompleteBox2_EntryAdded" InputType="Token" /> </ContentTemplate></asp:UpdatePanel>PeopleAndMachinesPicker.ascx.cs
using System;using System.Collections.Generic;using Telerik.Web.UI;namespace RC.SP.PeopleAndMachinesPicker{ public partial class PeopleAndMachinesPicker : System.Web.UI.UserControl { protected void RadAutoCompleteBox2_EntryAdded(object sender, AutoCompleteEntryEventArgs e) { /* process something */ } protected void Page_Load(object sender, EventArgs e) { List<string> adObjects = new List<string> { "Most", "of", "these", "pages", "are", "in", "the", "Afrikaans", "language", "spoken", "in", "South", "Africa" }; RadAutoCompleteBox2.DataSource = adObjects; } }}
In PeopleAndMachinesPicker.ascx added ChildrenAsTriggers = "false" for UpdatePanel. Now it works as desired.
Actually the problem you faced was an bug with the AutoCompleteBox in AJAX scenarios. We have just fixed the issue and the upcoming Q3 release will contain the fix.
Greetings,
Genady Sergeev
the Telerik team
I just did the Q3 update, and I am still getting the error. See attached.
Any suggestions?
Jim
PLEASE NOTE: My image below contains the following text. I've pasted it here so your search engines can find the text as well.
The error occurs when the RadEditor is "highlighted" like this. For some reason, that "highlighting" seems to trigger Ajax with throws the error.
This also seems slightly related to the tab index of the controls. For example, the RadAutoCompleteBox is TabIndex="1", but when I hit the tab, it does not go to TabIndex="2", which is the Textbox. Then, when I continue to tab, it eventually hits RadEditor and the error fires.
Overall, the tabbing is very inconsistent and strange.
Temporarily, I've solved the problem by wrapping only my upload control in a RadAjaxPanel. But, I would prefer the whole page to be wrapped in the panel for smoother performance.
The 2012 Q3 release did fix this. However, for some reason, I had to migrate the application 2 times. The first time didn't stick.
All good now. Thanks,
Jim
Default.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="TestAutocompleteSuggList._Default" %><%@ Register Assembly="Telerik.Web.UI, Version=2012.3.1120.35, Culture=neutral, PublicKeyToken=121fae78165ba3d4" Namespace="Telerik.Web.UI" TagPrefix="telerik" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"> <title></title></head><body> <form id="form1" runat="server"> <div> <asp:ScriptManager runat="server" /> <telerik:RadAutoCompleteBox runat="server" ID="racAutocomplete" AllowCustomEntry="true" OnEntryAdded="ServerEntryAdded" InputType="Token" /> </div> </form></body></html>Default.aspx.cs
using System;using System.Collections.Generic;using Telerik.Web.UI;namespace TestAutocompleteSuggList{ public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { racAutocomplete.DataSource = new List<string>(); racAutocomplete.DataBind(); } protected void ServerEntryAdded(object sender, AutoCompleteEntryEventArgs e) { } }}Could you specify which version is this because I am having hard time reproducing the problem. This is the markup I've tried with, using the latest Q3 release:
<asp:UpdatePanel runat="server"> <ContentTemplate> <telerik:RadAutoCompleteBox runat="server" ID="RadAutoCompleteBox1" InputType="Token" AllowCustomEntry="true"> </telerik:RadAutoCompleteBox> <asp:Label runat="server" ID="Foo"></asp:Label> </ContentTemplate> </asp:UpdatePanel>protected void Page_Load(object sender, EventArgs e) { var arr = "January February March April May June July August".Split(' '); ; RadAutoCompleteBox1.EntryAdded += RadAutoCompleteBox1_EntryAdded; RadAutoCompleteBox1.DataSource = arr; RadAutoCompleteBox1.DataBind(); } void RadAutoCompleteBox1_EntryAdded(object sender, AutoCompleteEntryEventArgs e) { Foo.Text = "AJAX"; }It didn't seem to trigger any issues.
Greetings,
Genady Sergeev
the Telerik team
The version under test is 2012.3.1120.35.
In your example an UpdatePanel is used. In my example -- there's no UpdatePanel. Though, in both cases RadAutoCompleteBox is repainted. Without EntryAdded event assigned the following behavior is possible:
1) user types in "jan"
2) suggestion list with the single option shows up -- "January"
3) user presses 'Enter' or click on "January" suggestion
4) a token "January" appears and the cursor is in edit box, user may continue typing (RadAutoCompleteBox is still focused). No full postback.
If EntryAdded is involved, on step 4) there's no cursor in RadAutoCompleteBox, the control's unfocused because of a postback.
Below is an example with EntryAdded commented out. Please compare the behavior when EntryAdded is uncommented. In the latter case current time appears on page, and this, I think, is a sign of a postback.
Default.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="TestAutocompleteSuggList._Default" %><%@ Register Assembly="Telerik.Web.UI, Version=2012.3.1120.35, Culture=neutral, PublicKeyToken=121fae78165ba3d4" Namespace="Telerik.Web.UI" TagPrefix="telerik" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head id="Head1" runat="server"> <title></title></head><body> <form id="form1" runat="server"> <div> <asp:ScriptManager ID="ScriptManager1" runat="server" /> <telerik:RadAutoCompleteBox runat="server" ID="RadAutoCompleteBox1" InputType="Token" > </telerik:RadAutoCompleteBox> <br /><br /><br /><br /> <asp:Label ID="lblCurrentTime" runat="server" /> </div> </form></body></html>Default.aspx.cs
using System;using System.Collections.Generic;using Telerik.Web.UI;namespace TestAutocompleteSuggList{ public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { var arr = "January February March April May June July August".Split(' '); ; //RadAutoCompleteBox1.EntryAdded += RadAutoCompleteBox1_EntryAdded; RadAutoCompleteBox1.DataSource = arr; RadAutoCompleteBox1.DataBind(); } protected void RadAutoCompleteBox1_EntryAdded(object sender, AutoCompleteEntryEventArgs e) { lblCurrentTime.Text = DateTime.Now.ToLongTimeString(); } }}
Thank you for the sample steps and code provided.
I used them to create a test page and reproduce the issue.
In fact the behaviour that you observe is by design - when you handle the OnEntryAdded server side event, a postback should occur.
Could you clarify about the concerns you have?
Can you explain in more details what is the exact scenario that you want to implement and which event you want to handle - OnEntryAdded or OnClientEntryAdded?
Regards,
Nencho
the Telerik team
The scenario is consecutive and uninterrupted input of tokens by a user. So I think the problem is
1) OnEntryAdded isn't assigned. When user finishes typing a token and presses ';' or 'Enter' the AutoCompleteBox keeps the focus and user can continue typing in tokens. That's convenient and usable.
2) OnEntryAdded is assigned. When user finishes typing a token and presses ';' or 'Enter' the AutoCompleteBox causes a postback, loses the focus and user needs to focus it again by clicking inside the control or by tabulating controls on the page before (s)he can continue typing in tokens. That's not so user-friendly.
I was able to replicate the described problematic behavior. I forwarded this issue to our developers team for further investigation. Thank for reporting this issue.
Regards,
Nencho
the Telerik team
A PostBack event would be fired, if you had hooked the OnTextChanged event. In addition please keep in mind, that the OnEntryAdded event would not be fired in an input type - "text" scenario.
All the best,
Nencho
the Telerik team
The issue that you had reported with the lost focus of the RadAutoCompleteBox, when an entry is added is already fixed and the fix will be released with our upcoming Service Pack, scheduled for 23th of July.
Regards,
Nencho
Telerik
Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.
