This is a migrated thread and some comments may be shown as answers.

TreeView bound to key/value pairs?

2 Answers 80 Views
TreeView
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Shane Milton
Top achievements
Rank 2
Shane Milton asked on 28 Mar 2011, 06:45 PM
Similar to a combobox/dropdown, I'd like to use a TreeView as a "Picker" object. While this isn't my example exactly, it applies well. Imagine that I'm trying to pick major cities in countries. My data might look like this (numbers are IDs but are not displayed, parent nodes are Country entities while child nodes are City entities):

- USA [1] (EXPANDED)
|___ Chicago [1]
|___ New York City [2] (SELECTED)
|___ Seattle [3]
|___ Paris [4]
+ France [2] (COLLAPSED)
|___ Paris [5] (HIDDEN)
|___ Marseille [6] (HIDDEN)

Right now, I understand the TreeView can be used as a picker but it doesn't really have the concept of IDs and TextValues like any normal "Picker" object would. Is there a standard way to get this to work like every other picker object in the world where we can work with IDs but display TextValues without writing a bunch of crappy hacky code?

In my current scenario, I'd LIKE for the groups to be bound via AJAX and to use jquery to put the "SelectedID" into a HiddenFor, which is bound to Model.SelectedCityID. All of this works great now, except, there is no concept of IDs as far as I can tell. Is there a way to easily add this concept to the TreeView? And if not, can we PLEASE PLEASE PLEASE get this added soon? Having a "Picker" that doesn't understand the concept of an ID makes the picker VERY difficult to use and requires us to waste time writing hacky code that we shouldn't have to write.

Thanks!
-Shane

2 Answers, 1 is accepted

Sort by
0
Shane Milton
Top achievements
Rank 2
answered on 28 Mar 2011, 06:55 PM
Oh, and this should definitely understand the difference in "Paris" [4] in Indiana, USA and "Paris" [5] in France.
0
Shane Milton
Top achievements
Rank 2
answered on 28 Mar 2011, 08:32 PM
Apparently there is a key/value pair concept in its most fundamental form although I'm unable to identify any API to call into it. Therefore, I hacked my own code.

First off, here is what was rendering once I had populated a node of my TreeView:

<LI class="t-item t-first">
    <DIV class="t-top t-top">
        <SPAN class=t-in>Foo</SPAN>
        <INPUT class=t-input value=14 type=hidden name=itemValue>
    </DIV>
</LI>
<LI class="t-item t-last">
    <DIV class=t-bot>
        <SPAN class=t-in>Bar</SPAN>
        <INPUT class=t-input value=1 type=hidden name=itemValue>
    </DIV>
</LI>

Armed with this, and some very bad jQuery skills, I created the following grid:

                <%=Html.HiddenFor(m => m.SelectedExpressionID)%>
                <%
        Html.Telerik().TreeView()
            .Name(ViewData.TemplateInfo.GetFullHtmlFieldId("CurrentExpressions").Replace('.', '_'))
            .DataBinding(dataBinding => dataBinding.Ajax().Select("GetExpressions", "xxx"))
            .ClientEvents(events =>
                              {
                                  events.OnSelect(() =>
                                                      {%>
    function(e){
        var treeView = $('#<%= ViewData.TemplateInfo.GetFullHtmlFieldId("CurrentExpressions").Replace('.', '_') %>').data('tTreeView');
        var expressionID = treeView.getItemValue(e.item);
        $('#<%=Html.IdFor(m => m.SelectedExpressionID)%>').val(expressionID);
    }
                                                    <%});
                                  events.OnDataBound(() =>
                                                         {%>
    function(e){
        var $expressionObject = $('#<%=Html.IdFor(m => m.SelectedExpressionID)%>');
        var expressionID = $expressionObject.val();
        if (expressionID && expressionID != "" && !isNaN(expressionID) && parseInt(expressionID) > 0) {
            var $treeViewElement = $('#<%= ViewData.TemplateInfo.GetFullHtmlFieldId("CurrentExpressions").Replace('.', '_') %>');
            var nodeToSelect = EG.Mvc.Controls.TreeView.findNodeByText($treeViewElement, expressionID);
            if (nodeToSelect) {
                EG.Mvc.Controls.TreeView.selectNode($treeViewElement, nodeToSelect);
            }
        }
    }
                                                       <%});
                              })
            .Render();
%>

and it refers to the following jquery/javascript (again, horrible right now):

    findNodeByText: function ($treeViewElement, text) {
        var itemsToLookThrough = $treeViewElement.find("li > div > span.t-in").siblings('input.t-input');
        for (var j = 0; j < itemsToLookThrough.length; j++) {
            if (itemsToLookThrough[j].value == text) {
                return $(itemsToLookThrough[j].parentElement.parentElement);
            }
        }
 
        return null;
    }
        ,
    selectNode: function ($treeViewElement, $node) {
        $treeViewElement.removeClass("t-state-selected");
        $node.find("> div > span.t-in").addClass("t-state-selected");
    }

Issues:
  1. This is nasty code and I hate it. However, we're confident that Telerik will make the need for this code go away soon, so it might make its way into production.
  2. This DOES distinguish Paris, France from Paris, USA. This does NOT, however, distinguish "USA" [1] from "Chicago" [1]. This simply assumes all IDs in the tree are unique and selects the first one that matches.
  3. Did I say that I hate this code?
  4. Yeah, this is bad code.

I hope this helps somebody out there. And by help, I mean that I hope it shows you something so you can write good code to do this! ;-)
Tags
TreeView
Asked by
Shane Milton
Top achievements
Rank 2
Answers by
Shane Milton
Top achievements
Rank 2
Share this question
or