Crash in disable(), after partial postback

2 posts, 0 answers
  1. Jeff
    Jeff avatar
    100 posts
    Member since:
    Apr 2008

    Posted 13 Jun 2011 Link to this post

    I have a page that has two RadComboBoxes and a button inside an UpdatePanel.  The first combo box is populated server-side, the second is populated client-side, when a selection is made on the first.

    That's not my problem.  It's working fine.

    My problem is that the button does a partial postback.  I'm calling .trackChanges() and .commitChanges on the second combo box as I populate it, so the values in the dropdowns are preserved across the partial postback.  But when I change the selected value in the first combo box, I get errors when I try to manipulate the second combo box.

    Note - I don't get errors initially, I only get errors after the partial postback,

    Currently, I'm getting the error in .disable(), which I call prior to making the ajax call that gets the data.  But if I don't call disable, I get the same error in .clearItems(), etc.  The second box seems to be confused about how many items are actually in the list. 

    The error is: Microsoft JScript runtime error: 'this.get_element()' is null or not an object

    I'm calling ddLevel2.disable(), where ddLevel2 is my second RadComboBox, as returned by $find().  The javascript for RadComboBox.disable() is:

    disable:function()
    {
        var e=this.get_tableElement();
        if (e!=null)
        {
            e.className="rcbDisabled";
        }
        this.set_enabled(false);
        this.get_inputDomElement().disabled="disabled";
        this.disableEvents();
        var d=this.get_items().get_count();
        for (var c=0; c<d; c++)
        {
            this._children.getItem(c).disable();
        }
    }

    Prior to the partial postback, the second dropdown had five items.  After the partial postback there are five items in the list.  And in this code, 'd' has the value 5.

    disable:function()
    {
        this.set_enabled(false);
        this.get_element().className="rcbDisabled";
    }

    And here, this.get_element() is not defined.

    I've created a simple example page that demonstrates the problem.  Load the page, select an item from the first combo box.  Wait a bit, then select an item from the second combo box.  Try this a few times.

    Then click on "Go", to generate the partial postback.

    Try selecting a different item from the second combo box.  You'll see that it contains the same items as prior to the postback.

    Then try selecting a different item from the first combo box.  That's when I get the error.

    I'm using version number 2010.1.519.35 of the Telerik.Web.UI.dll.

    My example page:

    <%@ Page Language="C#" %>
     
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
     
    <%@ Register assembly="Telerik.Web.UI" namespace="Telerik.Web.UI" tagprefix="telerik" %>
     
    <script runat="server">
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                populateLevel1();
                connectEvents();
            }
        }
     
        protected void Page_PreRender(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                initJavascript();
            }
        }
     
        protected void btnRun_Click(object sender, EventArgs e)
        {
        }
     
        private void populateLevel1()
        {
            ddLevel1.Items.Add(new RadComboBoxItem("", ""));
            for (var i = 1; i <= 4; i++)
            {
                string name = String.Format("Item {0}", i);
                string value = String.Format("{0}", i);
                ddLevel1.Items.Add(new RadComboBoxItem(name, value));
            }
     
            ddLevel1.SelectedIndex = 0;
        }
     
        protected virtual void connectEvents()
        {
            ddLevel1.OnClientSelectedIndexChanged = "ddLevel1SelectedIndexChanged";
        }
     
        protected virtual void initJavascript()
        {
            string script = @"
    Sys.UI.DomEvent.addHandler(window, 'load',
        function()
        {{
            initJavascript('{0}');
        }}
    );";
     
            script = String.Format(script, ddLevel2.ClientID);
     
            ClientScript.RegisterStartupScript(this.GetType(), this.ClientID + "_initJavascript", script, true);
        }  
    </script>
     
     
    <head runat="server">
     
        <script type="text/javascript">
            var ddLevel2 = null;
     
            function initJavascript(ddLevel2ClientID)
            {
                var foo = $find(ddLevel2ClientID);
     
                if (!foo)
                {
                    window.setTimeout(function() { initJavascript(ddLevel2ClientID); }, 100);
                    return;
                }
     
                ddLevel2 = $find(ddLevel2ClientID);
            }
     
            function ddLevel1SelectedIndexChanged(sender, eventArgs)
            {
                var item = eventArgs.get_item();
                var value = item.get_value();
     
                ddLevel2.disable();
                window.setTimeout(function() { getLevel2(value, ddLevel2); }, 1000);
            }
     
            function getLevel2(value, dd)
            {
                dd.trackChanges();
     
                dd.clearSelection();
                dd.clearItems();
     
                if (value)
                {
                    var items = dd.get_items();
     
                    var item = new Telerik.Web.UI.RadComboBoxItem();
                    item.set_text("");
                    item.set_value("");
                    items.add(item);
                    item.select();
     
                    items.add(item);
                    for (var i = 1; i <= 4; i++)
                    {
                        item = new Telerik.Web.UI.RadComboBoxItem();
                        item.set_text("Item " + value + "." + i);
                        item.set_value(value + "." + i);
     
                        items.add(item);
                    }
     
                    dd.commitChanges();
                }
     
                dd.enable();
            }
     
        </script>
     
        <title>Testing RadComboBoxes</title>
     
    </head>
     
    <body>
        <form id="form1" runat="server">
        <asp:ScriptManager ID="scriptManager" runat="server"></asp:ScriptManager>
         
        <asp:UpdatePanel ID="updatePanel" runat="server">
            <ContentTemplate>
                <asp:Label ID="lblLevel1" runat="server">Level One:</asp:Label>
                <telerik:RadComboBox ID="ddLevel1" runat="server"></telerik:RadComboBox>
                <br />
                <asp:Label ID="lblLevel2" runat="server">Level Two:</asp:Label>
                <telerik:RadComboBox ID="ddLevel2" runat="server"></telerik:RadComboBox>
                <br />
                <asp:Button ID="btnRun" runat="server"
                     OnClick="btnRun_Click" Text="Go!" />
            </ContentTemplate>
        </asp:UpdatePanel>
     
        </form>
    </body>
    </html>
  2. Jeff
    Jeff avatar
    100 posts
    Member since:
    Apr 2008

    Posted 14 Jun 2011 Link to this post

    I think I've found the problem.

    My javascript init function was running only on initial load, and not on partial postbacks.

    It looks as if the DOM elements within the update panel are destroyed and then recreated with the same ClientIDs, during the partial postback.  Which means that references to them that were obtained prior to the partial postback no longer work.

    Two solutions:

    1. Do the $find() in each function, rather than relying on a saved value, or
    2. hook the init function to an event that fires on every partial postback.
Back to Top