(C# VS 2008, .Net 3.5 SP1, RAD 2008 Q3)
But the following js client api calls for set_text and set_checked weren't working after the first ajax postback, that is,... until after user opened the combobox!
After hours of debugging I found a hack for the combo set_text ...
comboBox.get_items()._array[0]._text = aString;
comboBox.set_text(aString);
Then after more hours, the combox set_checked hack was (implemented in Attempt #2):
OnClientDropDownOpened="radComboBox_DDOpen"
I had to scrap your treeview and implement a custom control array of HTML checkboxes because it wasn't working inside the combo, and also wasn't otherwise controllable via your client-api.
(Had the code I wrote from the OnClientDropDownOpened event not worked I would have been forced to scrap both of your telerik controls as a solution.)
Then I noticed after the first ajax postback, that the combo would close after the first mouse click on the treeview or checkbox control array, which wasn't what the user needed (they needed multi-selection before close)...
At first I thought that the OnClientDropDownClosing event might have an arg that I could identify the source of the event to cancel, but that solution wasn't obvious, so I ended up using...
window.event.cancelBubble = true; (JS Hack implemented in Attempt #2):
My solution did work, however, finding the workaround for these bugs delayed our production release (not to mention the uglyness and headache of the solution).
All 11 senior devs on our team came to the same consensus,
Telerik needs to perform more QA and provide better documentation.
Code Attempt #1:
function ToggleTreeViewCheckList(currentNode)
{
var comboBox = $find('<%=radComboBox.ClientID%>');
var treeView = $find('<%=getTreeViewID() %>');
var aString="";
if (treeView.get_nodes())
{
//if current node checked-change is index 0
if (currentNode.get_index() == 0)
{
//Don't move this if statement, must be standalone
if (currentNode.get_checked())
{
//put -All- in temp string
aString = treeView.get_nodes().getNode(0).get_text();
}
//loop through all nodes, excluding index 0
for (var i=1; i<treeView.get_nodes().get_count();i++)
{
var node = treeView.get_nodes().getNode(i);
if (AllowCheckChange)
{
//ensure all nodes are toggled accordingly
node.set_checked(currentNode.get_checked());
}
}
}
//if there are nodes
else if (treeView.get_nodes().get_count() > 0)
{
var CheckedNodeCount = 0;
var tempstring = '';
//loop, excluding index 0
for (var i=1; i<treeView.get_nodes().get_count();i++)
{
var node = treeView.get_nodes().getNode(i);
if (node.get_checked())
{
//if node is checked add to temp string
CheckedNodeCount++;
tempstring += ',' + node.get_text();
}
}
//if all the nodes are checked (excluding one for index 0)
if (CheckedNodeCount == treeView.get_nodes().get_count() - 1)
{
if (AllowCheckChange)
{
//set text to '- All -' and check index 0
treeView.get_nodes().getNode(0).set_checked(true);
}
aString = treeView.get_nodes().getNode(0).get_text();
}
else
{
if (AllowCheckChange)
{
//ensure index 0 is not checked
treeView.get_nodes().getNode(0).set_checked(false);
}
//remove extra comma from temp string
aString = tempstring.substring(1, tempstring.length);
}
}
}
comboBox.get_items()._array[0]._text = aString;
comboBox.set_text(aString);
}
Code Attempt #2:
<%
@ Control Language="C#" AutoEventWireup="true" CodeBehind="ComboTreeView.ascx.cs"
Inherits="WebInterface.WebControls.ComboTreeView" %>
<%
@ Register TagPrefix="telerik" Namespace="Telerik.Web.UI" Assembly="Telerik.Web.UI" %>
<
script language="javascript" type="text/javascript">
//Flag for executing checking function
var RetailerCheckTheItems = false;
//Flag for locking checked items
var RetailerSearchLockItems = false;
//Instance of the Retailer CheckBox (set on NameLookup page)
//Needed to maintain viewstate on postback with ajax enabled
var RetailerCheckBox;
function SelectRetailerTreeViewItems(IsRetailerSearch)
{
RetailerCheckTheItems = IsRetailerSearch;
RetailerSearchLockItems = IsRetailerSearch;
CheckRetailerListItem();
}
function CheckRetailerListItem()
{
var comboBox = $find('<%=radComboBox.ClientID%>');
var itemsToCheck=new Array();
itemsToCheck[0] =
"Section1";
itemsToCheck[1] =
"Section2";
itemsToCheck[2] =
"Section3";
itemsToCheck[3] =
"Section4";
itemsToCheck[4] =
"Section5";
if (RetailerCheckTheItems)
{
var aString='';
var tempstring='';
for (var x=0; x<itemsToCheck.length; x++)
{
tempstring +=
',' + itemsToCheck[x];
}
//remove extra comma from temp string
aString = tempstring.substring(1, tempstring.length);
comboBox.get_items()._array[0]._text = aString;
comboBox.set_text(aString);
//loop through all nodes
var CheckControls = document.getElementsByName('CheckListItems');
for (i = 0; i < CheckControls.length; i++)
{
document.getElementById(
'CheckListItems' + i).checked = false;
for (var y=0; y<itemsToCheck.length; y++)
{
//if the checkbox value matches the list item, check it
if (document.getElementById('CheckListItems' + i).value == itemsToCheck[y])
{
document.getElementById(
'CheckListItems' + i).checked = true;
}
}
}
}
}
function radComboBox_DDOpen()
{
if (RetailerCheckBox)
{
//Lock Checkbox List if Retailer Search is Checked
//even after a postback without ajax.
RetailerSearchLockItems = RetailerCheckBox.checked;
}
CheckRetailerListItem();
if (RetailerCheckTheItems)
{
RetailerCheckTheItems =
false;
}
}
function CheckList_CheckChange(Index)
{
if (!RetailerSearchLockItems)
{
var comboBox = $find('<%=radComboBox.ClientID%>');
var aString = '';
if (Index == 0)
{
if (document.getElementById('CheckListItems0').checked)
{
aString = document.getElementById(
'CheckListItems0').value;
}
var CheckControls = document.getElementsByName('CheckListItems');
for (i = 0; i < CheckControls.length; i++)
{
CheckControls[i].checked = document.getElementById(
'CheckListItems' + Index).checked;
}
}
else if (Index > 0)
{
var CheckedNodeCount = 0;
var tempstring = '';
//loop, excluding index 0
var CheckControls = document.getElementsByName('CheckListItems');
for (i = 1; i < CheckControls.length; i++)
{
if (document.getElementById('CheckListItems' + i).checked)
{
//if node is checked add to temp string
CheckedNodeCount++;
tempstring +=
',' + CheckControls[i].value;
}
}
//if all the nodes are checked (excluding one for index 0)
if (CheckedNodeCount == CheckControls.length - 1)
{
//set text to '- All -' and check index 0
document.getElementById(
'CheckListItems0').checked = true;
aString =
'- ALL -';
}
else
{
//ensure index 0 is not checked
document.getElementById(
'CheckListItems0').checked = false;
//remove extra comma from temp string
aString = tempstring.substring(1, tempstring.length);
}
}
comboBox.get_items()._array[0]._text = aString;
comboBox.set_text(aString);
}
window.event.cancelBubble =
true;
}
function <%=this.ClientID %>_radComboBox_onClick(){
}
function <%=this.ClientID %>_radComboBox_OnClientFocus(sender){
}
function <%=this.ClientID %>_radComboBox_OnBlur(sender){
}
function StopPropagation(e) {
if (!e) {
e = window.event;
}
e.cancelBubble =
true;
}
function <%=this.ClientID %>_radComboBox_KeyPress(p1, p2){
if (window.event.keyCode==13){
}
}
</script>
<
telerik:RadComboBox ID="radComboBox" style="margin: 0px 0px 1px 0px;"
OnClientDropDownOpened="radComboBox_DDOpen" runat="server" Height="190px" Width="177" ShowToggleImage="True"
ShowMoreResultsBox="false" EnableEmbeddedSkins="false" Skin="CustomSkin" DropDownWidth="175">
<ItemTemplate>
<div id="div1" runat="server" style="margin-left: 0px; padding: 3px 0px 0px 0px;">
<ul style="width: 175px; list-style: none; margin: 0; padding: 0;">
<asp:Repeater ID="rptCheckList" runat="server">
<ItemTemplate>
<li>
<asp:Literal ID="litCheckBox" runat="server" />
<a id="CheckboxClicker" runat="server"><asp:Label ID="Label1" runat="server" Text="Label" /></a>
</li>
</ItemTemplate>
</asp:Repeater>
</ul>
</div>
</ItemTemplate>
<Items>
<telerik:RadComboBoxItem Text="" />
</Items>
</
telerik:RadComboBox>
<
script type="text/javascript">
var div1 = document.getElementById("<%=radComboBox.ClientID %>_i0_div1");
div1.onclick = StopPropagation;
</
script>
c# codebehind as follows...
public string getCSVofCheckedText() {
string returnvalue = string.Empty;
if (IsPostBack)
{
returnvalue =
this.Request.Form["ctl00$MainContent$Search2$cboExternalTypes$radComboBox_Input"];
}
return returnvalue;
}
protected void rptCheckList_ItemDataBound(object source, System.Web.UI.WebControls.RepeaterItemEventArgs e)
{
if ((e.Item.ItemType == ListItemType.Item) || (e.Item.ItemType == ListItemType.AlternatingItem))
{
var Label1 = e.Item.FindControl("Label1") as Label;
Label1.Text = e.Item.DataItem.ToString();
//Prepare the CheckChange JS function Call
var tempstring1 = string.Format("CheckList_CheckChange('{0}');", e.Item.ItemIndex);
var CheckBoxLit = e.Item.FindControl("litCheckBox") as Literal;
//The checkbox (can't be ASP.Net checkbox because of changed ClientID)
var LitText = @"<input type=""checkbox"" id=""CheckListItems{0}"" name=""CheckListItems"" onclick=""if (RetailerSearchLockItems) return false; {1}"" value=""{2}"" id=""chkItem"" {3} style=""border-style: none;"" />";
string CheckedText = string.Empty;
//check the checkboxes based on their viewstate on postback
if (this.getCSVofCheckedText().IndexOf("- ALL -") > -1 || this.getCSVofCheckedText().IndexOf(Label1.Text) > -1)
{
CheckedText =
"Checked";
}
//Set the checkbox properties and extra metadata
CheckBoxLit.Text =
string.Format(LitText, e.Item.ItemIndex, tempstring1, e.Item.DataItem.ToString(), CheckedText);
//Prepare the onclick JS for the hyperlink
var tempstring2 = string.Format(
"if (RetailerSearchLockItems) return false; document.getElementById('{0}{1}').checked = !document.getElementById('{0}{1}').checked; {2}",
"CheckListItems", e.Item.ItemIndex, tempstring1);
var CheckboxClicker = e.Item.FindControl("CheckboxClicker") as System.Web.UI.HtmlControls.HtmlAnchor;
CheckboxClicker.Attributes.Add(
"onclick", tempstring2);
}
}
Here is an example of the HTML code that repeater spits out for each data item...
<li>
<input type="checkbox" id="CheckListItems0" name="CheckListItems" onclick="if (RetailerSearchLockItems) return false; CheckList_CheckChange('0');" value="- ALL -" id="chkItem" style="border-style: none;" />
<a id="ctl00_MainContent_Search2_cboExternalTypes_radComboBox_i0_rptCheckList_ctl00_CheckboxClicker" onclick="if (RetailerSearchLockItems) return false; document.getElementById('CheckListItems0').checked = !document.getElementById('CheckListItems0').checked; CheckList_CheckChange('0');"><span id="ctl00_MainContent_Search2_cboExternalTypes_radComboBox_i0_rptCheckList_ctl00_Label1">- ALL -</span></a>
</li>