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

[Solved] Connecting two treeview controls

10 Answers 287 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.
Eugene
Top achievements
Rank 1
Eugene asked on 24 Mar 2010, 05:31 PM
How can clicking on one treeview control cause updating of another treecontrol?  The second treeview control contains data that is associated with a node of the first treeview control.  For example, if the first tree contains a list of articles, then clicking on an article in the first tree will display a list of documents that are contained within the selected article.
The first article tree's definition is as follows:

 

<div id="TreeViewArticle">

 

<%

= Html.Telerik().TreeView()

 

.Name(

"TreeView")

 

.DragAndDrop(settings => settings

.DropTargets(

".drop-container")

 

)

.ClientEvents(events => events

.OnNodeDrop(

"onNodeDrop")

 

.OnSelect(

"onSelect")

 

)

.BindTo(Model, (item, Article) =>

{

 

// bind initial data - can be omitted if there is none

 

item.Text = Article.Name;

item.Value = Article.ID.ToString();

item.LoadOnDemand =

true;

 

 

})

.DataBinding(dataBinding =>

{

dataBinding.Ajax()

.Enabled(

true)

 

.Select(

"LoadArticlesOnDemand", "Home");

 

})

%>

 

 

</div>

 



The second tree, which will contain the documents associated with the selected article of the first tree is as follows:

<%

= Html.Telerik().TreeView()

 

.Name(

"TreeViewRelArticle")

 

.DragAndDrop(settings => settings

.DropTargets(

".drop-container")

 

)

.ClientEvents(events => events

.OnNodeDrop(

"onNodeDropRel")

 

 

// .OnSelect("onSelectRel")

 

)

.BindTo(Model, (item, Article) =>

{

 

// bind initial data - can be omitted if there is none

 

item.Text =

"Related Documents";

 

item.Value =

"0";

 

item.LoadOnDemand =

true;

 

 

})

.DataBinding(dataBinding =>

{

dataBinding.Ajax()

.Enabled(

true)

 

.Select(

"LoadRelArticlesOnDemand", "Home");

 

})

%>


The problem is that the LoadRelArticlesOnDemand method is only called to load the second tree when a node is expanded on the second tree by clicking on it's expansion icon.  The data needs to change after selecting a node on the first tree.

Thanks in advance

10 Answers, 1 is accepted

Sort by
0
Alex Gyoshev
Telerik team
answered on 25 Mar 2010, 10:02 AM
Hi Eugene,

Indeed, the Ajax data-binding isn't suitable for this scenario. You should do the following:
  1. Attach an OnSelect event handler to the first TreeView.
  2. In the OnSelect handler, make an Ajax request using jQuery to get the related documents for the selected node
  3. Populate the second TreeView using client-side data-binding.

Sincerely yours,
Alex Gyoshev
the Telerik team

Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
0
Eugene
Top achievements
Rank 1
answered on 25 Mar 2010, 07:14 PM

Hi Alex
Thank you for your prompt reply.  Can you tell me what needs to be coded in the first tree's OnSelect method in order for the onbinding method to be called?  My onbinding method is not being called.  My two tree definitions are as follows:

 

<%

= Html.Telerik().TreeView()

 

 

 .Name(

"TreeView")

 

 

 .DragAndDrop(settings => settings

    .DropTargets(

".drop-container")

 

 

 )

.ClientEvents(events => events

    .OnNodeDrop(

"onNodeDrop")

 

    .OnSelect(

"onSelect")

 

 

 )

.BindTo(Model, (item, employee) =>

{

     

// bind initial data - can be omitted if there is none

 

     

 

item.Text = employee.FirstName + " " + employee.LastName;

 

     item.Value = employee.EmployeeID.ToString();

     item.LoadOnDemand =

true; // employee.Count == 0;

 

 

 

 

})

 

 

.DataBinding(dataBinding =>

{

    dataBinding.Ajax()

        .Enabled(

true)

 

         .Select(

"_AjaxLoading", "Home");

 

 

 })

%>

 

  <%= Html.Telerik().TreeView() 
     .Name(
"TreeView2")
     .Items(item =>

 

    {

        item.Add()

        .Text(

"Related Items") .Expanded(true)

 

         .LoadOnDemand(

true);

 

     })

    .ClientEvents(events => events

        .OnSelect(

"onSelect2")

 

        .OnDataBinding(

"onDataBinding")

 

 

 )

%>

My onSelect and onbinding methods are as follows:
 

< script type="text/javascript">
function onSelect(e) {

 

 

 

 

var item = $(e.item);

 

 

 

var node = $(e.item).closest('.t-item').find(':input[name*="Value"]').val();

 

 

 alert(

"Clicked on employee: " + $(e.item).closest('.t-item').find(':input[name*="Value"]').val());

 

 

 $.getJSON(

"/Home/GetRelatedItems", { node: node }, function(result) {

 

 

 alert(

"Related Items: Text = " + result[0].Text + " Value = " + result[0].Value);

 

 

 });

}

 

 

 

function onDataBinding(e) {  

 

 

 

alert(

"onDataBinding says Hi"); //Control does not go here!

 

 

 

 

var treeview = $('#TreeView2').data('tTreeView');

 

 

 

var jsonObject = [{ Value: "1", Text: "Product 1", Expanded: true, Items: [{ Value: "4", Text: "Product 4" }, { Value: "5", Text: "Product 5" }, { Value: "6", Text: "Product 6" }, { Value: "7", Text: "Product 7"}] }, { Value: "2", Text: "Product 2 (unavailable)", Enabled: false }, { Value: "3", Text: "Product 3"}];

 

 

 treeview.bindTo(jsonObject);

}

 

function onSelect2() {  

 

 

alert(

"ok");

 

 

 }

 

 

 

</

 

script>
If I understand your answer correctly, the onSelect method must get the Json data from the controller and save it somewhere so that the onbinding function can use it to bind to the second tree.  But what causes the onbinding method to be called?

Thanks for your help,
Sincerely,
Eugene

 

 

 

 

 

 

 

0
Alex Gyoshev
Telerik team
answered on 26 Mar 2010, 01:58 PM
Hi Eugene,

You can find attached a sample application that demonstrates the previously described approach. Please note that it uses a newer version of the assembly, which addresses a bug with the client-side binding of the TreeView. All you need to do is to wire the onSelect handler to make an AJAX call instead of generating the items.

All the best,
Alex Gyoshev
the Telerik team

Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
0
Eugene
Top achievements
Rank 1
answered on 26 Mar 2010, 04:35 PM
Hi Alex,
I follow your example for the related trees and the code works for populating the related tree with a list of items.  However, when I try to add children to the related tree, the tree disappears.  Can you please tell me what is wrong with my code?  Also, how does the format code block for code snippets work?  If I simply paste code in this window, which I have done again, it looks terrible and is hard to read so I apologize for it's appearance.
Thanks,
Eugene

 

public ActionResult GetRelatedItems(string node)

 

{

 

TreeViewItemModel tvItem0, tvItem;

 

 

List<Employee> viewdata = (List<Employee>)Session["viewdata"];

 

 

List<Employee> viewdata2 = (List<Employee>)Session["viewdata2"];

 

 

// Root node

 

tvItem0 =

new TreeViewItemModel();

 

tvItem0.Text =

"Related Items";

 

tvItem0.Value =

"0";

 

tvItem0.Expanded =

true;

 

tvItem0.LoadOnDemand =

false;

 

tvItem0.Enabled =

true;

 

 

switch (node)

 

{

 

case null:

 

tvItem =

new TreeViewItemModel();

 

tvItem.Text =

"related items";

 

tvItem.Value =

"75";

 

tvItem.Expanded =

false;

 

tvItem.LoadOnDemand =

false;

 

tvItem.Enabled =

true;

 

tvItem0.Items.Add(tvItem);

 

break;

 

 

case "100":

 

 

foreach (Company company in viewdata[0].arrCompanies)

 

{

tvItem =

new TreeViewItemModel();

 

tvItem.Text = company.CompanyName;

tvItem.Value = company.CompanyID;

tvItem.Expanded =

false;

 

tvItem.LoadOnDemand =

false;

 

tvItem.Enabled =

true;

 

tvItem0.Items.Add(tvItem);

}

 

break;

 

 

case "90":

 

 

foreach (Company company in viewdata2[0].arrCompanies)

 

{

tvItem =

new TreeViewItemModel();

 

tvItem.Text = company.CompanyName;

tvItem.Value = company.CompanyID;

tvItem.Expanded =

false;

 

tvItem.LoadOnDemand =

false;

 

tvItem.Enabled =

true;

 

tvItem0.Items.Add(tvItem);

}

 

break;

 

 

case "75":

 

 

foreach (Company company in viewdata2[1].arrCompanies)

 

{

tvItem =

new TreeViewItemModel();

 

tvItem.Text = company.CompanyName;

tvItem.Value = company.CompanyID;

tvItem.Expanded =

false;

 

tvItem.LoadOnDemand =

false;

 

tvItem.Enabled =

true;

 

tvItem0.Items.Add(tvItem);

}

 

break;

 

}

 

return new JsonResult { Data = tvItem0 };    // What is wrong with this json result?

 

 

function onSelect(e) {

 

 

var item = $(e.item);

 

 

var node = $(e.item).closest('.t-item').find(':input[name*="Value"]').val();

 

 

 

 

$.getJSON(

"/Home/GetRelatedItems", { node: node }, function(result) {

 

 

$('#TreeView2').data('tTreeView').bindTo(result);

 

});

 

<%

= Html.Telerik().TreeView()

 

.Name(

"TreeView")

 

 

)

 

.ClientEvents(events => events

 

.OnSelect("onSelect")

 

)

.BindTo(Model, (item, employee) =>

{

 

// bind initial data - can be omitted if there is none

 

 

 

 

item.Text = employee.FirstName +

" " + employee.LastName;

 

item.Value = employee.EmployeeID.ToString();

item.LoadOnDemand =

true; // employee.Count == 0;

 

 

 

 

 

})

.DataBinding(dataBinding =>

{

dataBinding.Ajax()

.Enabled(

true)

 

.Select(

"_AjaxLoading", "Home");

 

})

%>

 

 

 

 

 

 

 

 

 

<%

= Html.Telerik().TreeView()

 

.Name(

"TreeView2")

 

.Items(item =>

{

item.Add()

.Text(

"Related Items");

 

})

%>

0
Alex Gyoshev
Telerik team
answered on 29 Mar 2010, 09:44 AM
Hi Eugene,

I think that the problem lies in the JavaScript, namely

$('#TreeView2').data('tTreeView').bindTo(result);

should be

$('#TreeView2').data('tTreeView').bindTo([result]);

because the TreeView wants an array of items that it can bind to.

In order to illustrate this, I've adjusted the sample application so that it uses a JSON call to load the related items in the second TreeView.

I understand that the whole client-side binding is a bit frustrating, and I'll try to improve it for the next release.

Sincerely yours,
Alex Gyoshev
the Telerik team

Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
0
Eugene
Top achievements
Rank 1
answered on 29 Mar 2010, 03:11 PM
Hi Alex,
    Thank you so much for your prompt and correct answer.
Best Regards,
Eugene
0
Donna Stewart
Top achievements
Rank 1
answered on 25 Jan 2011, 04:52 PM
I am trying to do something similar and have looked at the attached solution and incoproated the code, but i am getting an error in telerik.treeview.min.js.  The error is Microsoft JScript runtime error: 'Text' is null or not an object.  We are using the latest version of the mvc extensions - Q3 2010.  Your help is very much appreciated!!  Thank you!

Below are the pretinent code snippets:

Javascript:
  
       function getUserGroupsForTaskGroup(e) {
            var taskGroupTree = $('#WTGroupNames').data('tTreeView');
            var selectedValue = taskGroupTree.getItemValue(e.item);
            var userGroupTree = $('#UGsForTGs');
 
            $.post('<%= Url.Action("GetUserGroupsForTaskGroup", "WebTask") %>', // The url of the /Home/Grid action method
                 {
                 id: selectedValue
             },  // arguments which need to be passed to the Grid action method
                 function (result, textStatus) { //JavaScript callback executed when the ajax request finishes
                     userGroupTree.data('tTreeView').bindTo([result]); // update the DIV which contains the grid
                 },
                 "json"
            );
    }
The 2 treeviews:
            <%= Html.Telerik().TreeView().Name("WTGroupNames").ShowCheckBox(True).HtmlAttributes(New With {.style = "width:250px; height:550px;"}) _
                .ClientEvents(Function(evt) evt.OnSelect("getUserGroupsForTaskGroup")) _
                .BindTo(CType(Model.wtGoupNames, IEnumerable(Of SelectListItem)),
                            Sub(mappings)
                                mappings.For(Of SelectListItem)(
                                Sub(binding)
                                    binding _
                                        .ItemDataBound(
                                            Sub(item, linkGroup)
                                                item.Text = linkGroup.Text
                                                item.Value = linkGroup.Value
                                                item.LoadOnDemand = True
                                            End Sub)
                                End Sub)
                            End Sub) _
               .DataBinding(Function(dataBinding) dataBinding.Ajax().Select("GetTasksForGroup", "WebTask"))
            %>
  
           <div id="usergroupsfortaskgroups">
                <%= Html.Telerik().TreeView().Name("UGsForTGs").HtmlAttributes(New With {.style = "width:250px; height:550px;"}) _
                                        .Items(Function(treeview) treeview.Add().Text("Related user groups")) _
                                        .DataBinding(Function(dataBinding) dataBinding.Ajax().Select("GetUsersForUserGroups", "WebTask"))
                %>
            </div>
Controller:     
  
    <AcceptVerbs(HttpVerbs.Post)> _
    Public Function GetUserGroupsForTaskGroup(ByVal id As Integer) As JsonResult
   Dim gmcPermissions As New GMCPermissions
        Dim userGroups As List(Of WebUserGroupName) = gmcPermissions.GetUserGroupNamesForTaskGroupNameKey(id)
        Dim nodes As New List(Of TreeViewItem)
        For Each userGrp In userGroups
            nodes.Add(New TreeViewItem With {.Text = userGrp.UserGroupName, .Value = userGrp.UserGroupNameKey, .LoadOnDemand = True})
        Next
        Return New JsonResult() With {.Data = nodes}
    End Function
 
0
Donna Stewart
Top achievements
Rank 1
answered on 25 Jan 2011, 05:13 PM
I forgot to note that I am using a new treeview js file I got from another post.  I have attached the file here.

Thank you,
Donna
0
T. Tsonev
Telerik team
answered on 26 Jan 2011, 11:15 AM
Hello Eugene,

Thank you for sending the relevant code. The only potential problem I can spot is that you're wrapping the response in an array:
userGroupTree.data('tTreeView').bindTo([result]);

Try binding to the result itself:
userGroupTree.data('tTreeView').bindTo(result);

If this doesn't help, can you please send us a sample project that we can debug locally? Thank you.

Best regards,
Tsvetomir Tsonev
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
0
Donna Stewart
Top achievements
Rank 1
answered on 26 Jan 2011, 04:25 PM
Thank you!  That worked!

Donna
Tags
TreeView
Asked by
Eugene
Top achievements
Rank 1
Answers by
Alex Gyoshev
Telerik team
Eugene
Top achievements
Rank 1
Donna Stewart
Top achievements
Rank 1
T. Tsonev
Telerik team
Share this question
or