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.