Dual ListBox Item State Issues

3 posts, 1 answers
  1. JD
    JD avatar
    22 posts
    Member since:
    Jul 2013

    Posted 08 Oct 2013 Link to this post

    Hi,

    I'm using two lists as a dual list.  I need to enhance the lists in a few ways: allow checkboxes in the destination list, only allow ONE item to be checked in the destination list, and enhance the items in the destination list to provide obvious visual cues for users.

    All the code is in a user control - the lists are completely programmatically created and jquery is used to do some of the client-side magic.  I am having state issues, though.

    Issue 1 - move an item from the select list to the destination list.  Check the item then move it back to the select list, using the To Top button.  Note the item's style (now in the select list) has taken on the Red style of the inserted span from the destination list.  It should be back to just a regular list item with the select list's default style.  

    Issue 2 - now move the same item back to the Destination list. Note that it somehow retains its checked status and the additional span I added.  It should be back to just a default unchecked item (which then gets styled blue).  With multiple items in the bottom list, in this manner it's possible to end up with 2 items checked in the destination list.

    Issue 3 - now uncheck the item then move it back to the select list, using the To Top button. Back to the Red style???

    All these issues are related - the list is trying to preserve item state. I need it to forget the item state and just let the items fall back to their default state so they can be predictably manipulated.  

    There is also a block of code commented out in the .js file in which I explicitly remove all the changes I make to the items.  This code doesn't work either, as spans get moved around when the listbox is trying to preserve their state.

    Thanks in advance for your input.
    JD

    C#:
    public class UserControl1 : WebControl
        {
     
            private RadListBox _RlbItemSelect = new RadListBox();
            private RadListBox _RlbItemDestination = new RadListBox();
            private Panel _ListDiv = new Panel();
            private Button _Button = new Button();
            private Label _Label1 = new Label();
            private Button _Button2 = new Button();
     
            HtmlGenericControl _TestList = new HtmlGenericControl("ul");
            HtmlButton _TestButton = new HtmlButton();
     
            void _Button_Click(object sender, EventArgs e)
            {
                _Label1.Text = "Postback";
                _RlbItemSelect.Items.Add(new RadListBoxItem("This is another item, added after postback"));
            }
     
            protected override void OnInit(EventArgs e)
            {
                base.OnInit(e);
     
                _Label1.ID = "_Label1";
                _Label1.Text = "Initial Load";
     
                _Button.Text = "RefreshPage";
                _Button.ID = "_Button";
                _Button.Click += _Button_Click;
     
                this.Page.Form.Controls.Add(_Button);
                this._ListDiv.Controls.Add(_Label1);
     
                this.Controls.Add(_ListDiv);
     
                this._ListDiv.Controls.Add(new LiteralControl("<br/><br/><span id style=\"text-align:left;\">Title</span><br/>"));
                this._RlbItemSelect.ID = "_RlbItemSelect";
                this._RlbItemSelect.Height = Unit.Pixel(200);
                this._RlbItemSelect.Width = Unit.Pixel(800);
                this._RlbItemSelect.AllowTransfer = true;
                this._RlbItemSelect.AllowReorder = false;
                this._RlbItemSelect.AllowTransferOnDoubleClick = true;
                this._RlbItemSelect.TransferToID = "_RlbItemDestination";
                this._RlbItemSelect.ButtonSettings.Position = ListBoxButtonPosition.Bottom;
                this._RlbItemSelect.ButtonSettings.HorizontalAlign = ListBoxHorizontalAlign.Center;
                this._RlbItemSelect.ButtonSettings.RenderButtonText = true;
                this._RlbItemSelect.CssClass += " PopDualListHgSelect";
     
     
                this._RlbItemDestination.ClientIDMode = System.Web.UI.ClientIDMode.Static;
                this._RlbItemDestination.ID = "_RlbItemDestination";
                this._RlbItemDestination.Height = Unit.Pixel(200);
                this._RlbItemDestination.Width = Unit.Pixel(800);
                this._RlbItemDestination.EmptyMessage = "Must choose at least one gateway pop";
                this._RlbItemDestination.CheckBoxes = true;
                this._RlbItemDestination.CssClass += " PopDualListHgDestination";
                this._RlbItemDestination.SelectionMode = ListBoxSelectionMode.Single;
                this._RlbItemDestination.OnClientItemChecking = "singleSelectionInHgDestLb";
                this._RlbItemDestination.PersistClientChanges = true;
                this._RlbItemDestination.EnableViewState = true;
     
                this._ListDiv.Controls.Add(this._RlbItemSelect);
                this._ListDiv.Controls.Add(new LiteralControl("<br/>"));
                this._ListDiv.Controls.Add(this._RlbItemDestination);
                this._ListDiv.Controls.Add(new LiteralControl("<br/>"));
     
                if (!Page.IsPostBack)
                {
                    _RlbItemSelect.Items.Add(new RadListBoxItem("This is item 1"));
                    _RlbItemSelect.Items.Add(new RadListBoxItem("This is item 2"));
                    _RlbItemSelect.Items.Add(new RadListBoxItem("This is item 3"));
                    _RlbItemSelect.Items.Add(new RadListBoxItem("This is item 4"));
                }
     
                Page.ClientScript.RegisterClientScriptInclude("scripts/listBox.js""scripts/listBox.js");
            }
     
     
        }


    Javascript:
    function singleSelectionInHgDestLb(sender, args) {
        var item = args.get_item();
        var lb = item.get_listBox();
        lb.trackChanges();
        var items = sender.get_items();
        var checked = item.get_checked();
        var ele = $(item.get_element());
        if (checked == false) {
            clearChecks(items);
            ele.closest(".rlbItem").find("label").SetHgSpanText(true);
        }
        else {
            ele.closest(".rlbItem").find("label").SetHgSpanText(false);
        }
     
        lb.commitChanges();
    }
     
     
    function clearChecks(items) {
        items.forEach(function (itm) {
            itm.set_checked(false);
            var ele = $(itm.get_element());
            ele.closest(".rlbItem").find("label").SetHgSpanText(false);
        });
    }
     
     
    (function ($) {
        $.fn.SetHgSpanText = function (isPrimary) {
            var setText = "SECONDARY";
            var color = "blue";
            if (isPrimary) { setText = "PRIMARY"; color = "red"; }
            if ($(this).find(".hgInd").length) {
                $(this).find(".hgInd").text("(" + setText + ") ");
                $(this).find(".hgInd").attr("style""color: " + color + "; font-size: 8pt");
            else {
     
                $(this).find(".rlbCheck").after("<span class='hgInd' style='color: "
                     + color + "; font-size: 8pt' class='rlbSpan'>(" + setText + ") </span>");
            }
            $(this).find(".rlbText").removeAttr("style");
        };
    })(jQuery);
     
     
    $(function () {
        $("#main").on("DOMNodeInserted"".PopDualListHgDestination .rlbList"function (e) {
            if ($(e.target).is(".rlbItem")) {
                var checked = $(e.target).find(".rlbCheck[checked='checked']").length > 0;
                $(e.target).find("label").SetHgSpanText(checked);
            }
        });
    });
     
    ////This cleanup does method not work
    //$(function () {
    //    $("#main").on("DOMNodeInserted", ".PopDualListHgSelect .rlbList", function (e) {
    //        if ($(e.target).is(".rlbItem")) {
    //            $(e.target).find(".hgInd").remove();
    //            $(e.target).find(".rlbText").removeAttr("style");
    //        }
    //    });
    //});
     
    $(document).ready(function () {
        $("#main").find(".PopDualListHgDestination .rlbCheck[checked='checked']").closest("label").SetHgSpanText(true);
        $("#main").find(".PopDualListHgDestination .rlbCheck[checked!='checked']").closest("label").SetHgSpanText(false);
    });
  2. Answer
    Nencho
    Admin
    Nencho avatar
    1458 posts

    Posted 11 Oct 2013 Link to this post

    Hello Justyn,

    I was able to replicate the faced problems. For the styling issues, I would suggest you to define the css classes for both RadListBoxes, where you could specify the needed styles rules, instead of applying styles to each transferred/checked item.

    As for you other inquiry, regarding the checked state of the transferred Item, you could handle the OnClientTransferring client-side event and use the set_checked() method, in order to manage it state. Please consider the following approach :
    function onClientTransferring(sender, args) {
        var itemsToBeTransferred = args.get_items();
        var itemsCount = itemsToBeTransferred.length;
     
        for (var i = 0; i < itemsCount; i++) {
            if (itemsToBeTransferred[i].get_checked())
                itemsToBeTransferred[i].set_checked(false);
        }
    }


    Regards,
    Nencho
    Telerik
    If you want to get updates on new releases, tips and tricks and sneak peeks at our product labs directly from the developers working on the RadControls for ASP.NET AJAX, subscribe to the blog feed now.
  3. UI for ASP.NET Ajax is Ready for VS 2017
  4. JD
    JD avatar
    22 posts
    Member since:
    Jul 2013

    Posted 11 Oct 2013 Link to this post

    Thanks, Nencho, nice call.  I had not considered using a style to insert the text.  All this worked great with one exception: IE9 or higher is required.  

    This manipulates the text in the destination list items and also only allows a single item to be Checked in the destination list.

    Here's the final code:
    public class UserControl1 : WebControl
        {
     
            private RadListBox _RlbItemSelect = new RadListBox();
            private RadListBox _RlbItemDestination = new RadListBox();
            private Panel _ListDiv = new Panel();
            private Button _Button = new Button();
            private Label _Label1 = new Label();
            private Button _Button2 = new Button();
     
            HtmlGenericControl _TestList = new HtmlGenericControl("ul");
            HtmlButton _TestButton = new HtmlButton();
     
            void _Button_Click(object sender, EventArgs e)
            {
                _Label1.Text = "Postback";
                _RlbItemSelect.Items.Add(new RadListBoxItem("This is another item, added after postback"));
            }
     
            protected override void OnInit(EventArgs e)
            {
                base.OnInit(e);
                Table tab = new Table();
                tab.Rows.Add(new TableRow());
                tab.Rows[0].Cells.Add(new TableCell());
                TextBox t = new TextBox();
                t.CssClass = " SiteIdSearchTextbox";
                tab.Rows[0].Cells[0].Controls.Add(t);
                //this._ListDiv.Controls.Add(t);
     
                Button b = new Button();
                b.Text = "View This Pop";
                b.CssClass += " ViewIndividualPopButton";
                //this._ListDiv.Controls.Add(b);
                tab.Rows[0].Cells[0].Controls.Add(b);
     
                this._ListDiv.Controls.Add(tab);
     
                _Label1.ID = "Label1";
                _Label1.Text = "Initial Load";
     
                _Button.Text = "RefreshPage";
                _Button.ID = "_Button";
                _Button.Click += _Button_Click;
     
                this.Page.Form.Controls.Add(_Button);
                this._ListDiv.Controls.Add(_Label1);
     
                this.Controls.Add(_ListDiv);
     
                this._ListDiv.Controls.Add(new LiteralControl("<br/><br/><span id style=\"text-align:left;\">Title</span><br/>"));
                this._RlbItemSelect.ID = "_RlbItemSelect";
                this._RlbItemSelect.Height = Unit.Pixel(200);
                this._RlbItemSelect.Width = Unit.Pixel(800);
                this._RlbItemSelect.AllowTransfer = true;
                this._RlbItemSelect.AllowReorder = false;
                this._RlbItemSelect.AllowTransferOnDoubleClick = true;
                this._RlbItemSelect.TransferToID = "_RlbItemDestination";
                this._RlbItemSelect.ButtonSettings.Position = ListBoxButtonPosition.Bottom;
                this._RlbItemSelect.ButtonSettings.HorizontalAlign = ListBoxHorizontalAlign.Center;
                this._RlbItemSelect.ButtonSettings.RenderButtonText = true;
                this._RlbItemSelect.CssClass += " PopDualListHgSelect";
                this._RlbItemSelect.OnClientTransferring = "onClientTransferringInHgSelectLb";
                this._RlbItemSelect.SelectionMode = ListBoxSelectionMode.Multiple;
     
                this._RlbItemDestination.ClientIDMode = System.Web.UI.ClientIDMode.Static;
                this._RlbItemDestination.ID = "_RlbItemDestination";
                this._RlbItemDestination.Height = Unit.Pixel(200);
                this._RlbItemDestination.Width = Unit.Pixel(800);
                this._RlbItemDestination.EmptyMessage = "Must choose at least one gateway pop";
                this._RlbItemDestination.CheckBoxes = true;
                this._RlbItemDestination.CssClass += " PopDualListHgDestination";
                this._RlbItemDestination.OnClientItemChecking = "singleSelectionInHgDestLb";
                this._RlbItemDestination.PersistClientChanges = true;
                this._RlbItemDestination.EnableViewState = true;
                this._RlbItemDestination.SelectionMode = ListBoxSelectionMode.Multiple;
     
                this._ListDiv.Controls.Add(this._RlbItemSelect);
                this._ListDiv.Controls.Add(new LiteralControl("<br/>"));
                this._ListDiv.Controls.Add(this._RlbItemDestination);
                this._ListDiv.Controls.Add(new LiteralControl("<br/>"));
     
                if (!Page.IsPostBack)
                {
                    _RlbItemSelect.Items.Add(new RadListBoxItem("This is item 1"));
                    _RlbItemSelect.Items.Add(new RadListBoxItem("This is item 2"));
                    _RlbItemSelect.Items.Add(new RadListBoxItem("This is item 3"));
                    _RlbItemSelect.Items.Add(new RadListBoxItem("This is item 4"));
                }
     
                Page.ClientScript.RegisterClientScriptInclude("scripts/listBox.js", "scripts/listBox.js");
            }
        }

    Much simpler Javascript:
    function onClientTransferringInHgSelectLb(sender, args) {
        var itemsToBeTransferred = args.get_items();
        var itemsCount = itemsToBeTransferred.length;
     
        for (var i = 0; i < itemsCount; i++) {
            if (itemsToBeTransferred[i].get_checked())
                itemsToBeTransferred[i].set_checked(false);
        }
    }
     
    function singleSelectionInHgDestLb(sender, args) {
        var item = args.get_item();
        var lb = item.get_listBox();
        lb.trackChanges();
        var items = sender.get_items();
        var checked = item.get_checked();
        var ele = $(item.get_element());
        if (checked == false) {
            clearChecks(items);
        }
     
        lb.commitChanges();
    }
     
    function clearChecks(items) {
        items.forEach(function (itm) {
            itm.set_checked(false);
            var ele = $(itm.get_element());
        });
    }

    And Stylesheet (here's the magic):
    .PopDualListHgDestination input[type=checkbox]:enabled + span.rlbText:before {
       /* :enabled (not really needed) is used to detect IE8.  If < IE9, the :checked
           psuedo-selector is not supported so we want to NOT style either checked or unchecked. */
       content: "(SECONDARY) ";
       color: blue;
       font-size: 8pt;
    }
     
    .PopDualListHgDestination input[type=checkbox]:checked + span.rlbText:before {
       content: "(PRIMARY) ";
       color: red;
       font-size: 8pt;
    }
Back to Top