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

Set treeview hierarchy from javascript

3 Answers 254 Views
TreeView
This is a migrated thread and some comments may be shown as answers.
Sam
Top achievements
Rank 1
Sam asked on 24 Oct 2019, 01:20 PM

My requirements are such that on initial load, the tree is empty and a user can do a search which would then load the results into the treeview.  Once the view is loaded, the user will navigate the tree with the expand functions.  It's possible that the user searches for a result that is at an arbitrary depth in the tree (not a top-level node) so I query all nodes from the root down to the search result.  I need help figuring out how to set this hierarchy of nodes into the tree correctly.  Currently, only the top-level node displays with no expander.

 

The object to be displayed in tree:

public class LocationModel
 {
     public string Id { get; set; }
     public string ParentId { get; set; }
     public string Name { get; set; }
     public List<LocationModel> Children { get; set; } = new List<LocationModel>();
     public bool HasChildren => true;
 }

 

The controller:

public JsonResult GetLocationHierarchy(string locationId)
{
    if (string.IsNullOrEmpty(locationId))
        return new JsonResult();
    //string id;
    var results = new List<LocationModel>();
 
    using (var ctx = _docStore.OpenSession())
    {
        // recursively step up the tree, adding each node to the list
        while (!string.IsNullOrWhiteSpace(locationId))
        {
            var thisNode = (from l in ctx.Query<Location>()
                            where l.Id.Equals(locationId)
                            select new LocationModel
                            {
                                Id = l.Id,
                                Name = l.FriendlyName,
                                ParentId = l.ParentId
                            }).SingleOrDefault();
 
            if (thisNode != null)
            {
                results.Add(thisNode);
                locationId = thisNode.ParentId;
            }
            else
                locationId = string.Empty;
        }
    }
             
    // set the children on the nodes
    foreach (var node in results)
        node.Children = results.Where(x => x.ParentId == node.Id).ToList();
 
    //return only the top level node (hierachy is in place)
    return Json(results.Where(x=> x.ParentId == string.Empty).ToList(), JsonRequestBehavior.AllowGet);

 

The tree view:

<div id="treeview">
     <div class="demo-section k-content">
         @(Html.Kendo().TreeView()
                           .Name("treeView")
                           .LoadOnDemand(true)
                           .DataTextField("Name")
                           .Events(events => events
                               .Select("onSelect")
                               .Expand("onExpand")
                           )
                           .DataSource(dataSource => dataSource
                           .Model(m =>
                           {
                               m.Id("Id");
                               m.Field("Name", typeof(string));
                               m.Children("Children");
                               m.HasChildren("HasChildren");
                           })
                             .Read(read => read
                               .Action("GetLocationChildren", "Home", new { locationId = Model.SelectedLocation.Id })
                           )
                           )
         )
     </div>
 </div>

 

The search button method:

function onSearchButtonClick(e) {
        if ($("#SelectedLocation_Name").val() == "") {
            console.log("No SelectedLocation Name");
            return;
        }
         var u = '@Url.Action("GetLocationHierarchy")';
        $.post(u,
            {
                locationId: $("#SelectedLocation_Id").val()
            },
            function (data) {
                console.log("onSearchButtonClick returned...");
                var treeView = $("#treeView").data("kendoTreeView");
                if (treeView == null) {
                    console.log("treeView is null!");
                    return;
                }
 
                console.log(e);
 
                treeView.setDataSource(data);
              });
           }

 

 

3 Answers, 1 is accepted

Sort by
0
Veselin Tsvetanov
Telerik team
answered on 28 Oct 2019, 01:34 PM

Hi Sam,

In order to properly build the full hierarchy on the client, you will have to createHerarchicalDataSource object and pass it to the setDataSource() call:

var dataSource = new kendo.data.HierarchicalDataSource({
	data: data,
	schema: {
		model: {
			id: "Id",
			children: "Children",
			hasChildren: "HasChildren",
			fields: {
				Name: { type: "string" }
			}
		}
	}
});

treeView.setDataSource(dataSource);

Attached you will find a small sample implementing the above.

Regards,
Veselin Tsvetanov
Progress Telerik

Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
0
Sam
Top achievements
Rank 1
answered on 28 Oct 2019, 04:56 PM
Thank you.  That was the missing part.  However, after this initial load of the tree, I want the user to be able to expand other nodes and load them on demand.  It seems that's not working now as the id field isn't getting passed to the controller method.
0
Veselin Tsvetanov
Telerik team
answered on 30 Oct 2019, 11:26 AM

Hello Sam,

I am afraid that you won't be allowed to mix remote DataSource configuration with a local one. Initially, the TreeView is configured to read its items from the GetLocationChildren() action of the Home controller. After resetting the DataSource to use the items obtained with the manual AJAX call, the initial DataSource is no longer assigned to the TreeView. Instead, the local data returned from the above AJAX call will be used in the widget.

If you need to keep the Read endpoint configuration, you will have to approach the scenario in a different way. Instead of manually calling a controller action, you should set the AutoBind() option of the TreeView helper to false. Then upon a button click, you should trigger Read() on the TreeView DataSource. With that request, you should also send the search parameter to the remote, so that the returned items should be filtered. Also, do not return their nested child items, as those will be requested upon parent expand.

Attached you will find a small sample implementing the above changes.

Regards,
Veselin Tsvetanov
Progress Telerik

Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
Tags
TreeView
Asked by
Sam
Top achievements
Rank 1
Answers by
Veselin Tsvetanov
Telerik team
Sam
Top achievements
Rank 1
Share this question
or