Select the Folder Path When Clicking a TreeList Node
Environment
Product | TreeList for Progress® Telerik® UI for ASP.NET MVC |
Description
How can I bind the TreeList to Hierarchical data and select the folder path when a specified node is clicked?
Solution
To achieve the desired scenario:
- Customize the TreeList rows by using the
RowTemplateId
andAltRowTemplateId
methods. - Enable the
Selectable
option to allow multiple row selection:.Selectable(s => s.Mode(TreeListSelectionMode.Multiple))
. - Handle the
change
event of the TreeList, get the selected node, and manually select its parent nodes.
@(Html.Kendo().TreeList<HierarchicalViewModel>()
.Name("treelist")
.Columns(columns =>
{
columns.Add().Field(e => e.ID);
})
.Selectable(s => s.Mode(TreeListSelectionMode.Multiple))
.RowTemplateId("rowTemplate")
.AltRowTemplateId("altRowTemplate")
.DataSource(dataSource => dataSource
.Read(read => read.Action("All", "Home"))
.Model(m =>
{
m.Id(f => f.ID);
m.ParentId(f => f.ParentID);
m.Expanded(true);
})
)
.Events(ev => ev.Change("onChange"))
)
<script id="rowTemplate" type="text/x-kendo-template">
<tr data-uid='#: data.model.uid #' role="row" class='#=data.hasChildren? 'parentRow' : 'childRow'#'>
<td role="gridcell">
#for(var i = 0; i < (hasChildren ? level : (level + 1)); i++){#
<span class="k-icon k-i-none"></span>
#}#
#if(data.hasChildren){#
# if(data.model.expanded) { #
#= kendo.ui.icon("caret-alt-down") #
# } else { #
#= kendo.ui.icon("caret-alt-right") #
# } #
#}#
<span class="k-sprite #: data.model.SpriteCssClass #"></span>
<span> #: data.model.Name # </span>
</td>
</tr>
</script>
<script id="altRowTemplate" type="text/x-kendo-template">
<tr data-uid='#: data.model.uid #' role="row" class="k-alt #=data.hasChildren? 'parentRow' : 'childRow'#">
<td role="gridcell">
#for(var i = 0; i < (hasChildren ? level : (level + 1)); i++){#
<span class="k-icon k-i-none"></span>
#}#
#if(data.hasChildren){#
# if(data.model.expanded) { #
#= kendo.ui.icon("caret-alt-down") #
# } else { #
#= kendo.ui.icon("caret-alt-right") #
# } #
#}#
<span class="k-sprite #: data.model.SpriteCssClass #"></span>
<span> #: data.model.Name # </span>
</td>
</tr>
</script>
<script>
function findParentItems(allParentRows, selectedDataItem, selectedParentRows, level) {
var treeList = $("#treelist").data("kendoTreeList");
for(var i = 0; i < allParentRows.length; i++) {
var currentDataItem = treeList.dataItem(allParentRows[i]);
var addedItem = $.inArray( allParentRows[i], selectedParentRows );
var currentLevel = $(allParentRows[i]).find(".k-icon").length; //get the current item level
if(currentDataItem.ParentID != null && addedItem == -1 && currentLevel < level){
for(var j = 0; j < selectedParentRows.length; j++) { //loop through the already stored items
var dt = treeList.dataItem(selectedParentRows[j]);
if(currentDataItem.ID == dt.ParentID) { //check if the parent is a direct parent of the stored item
selectedParentRows.push(allParentRows[i]); //store it
findParentItems(allParentRows,currentDataItem, selectedParentRows, currentLevel);
break;
}
}
}
}
return selectedParentRows;
}
function onChange(e) {
var treeList = e.sender;
var selectedRow = $("#treelist .k-grid-content table tbody").find("tr.k-selected");
var rootLevel = $("#treelist .k-grid-content table tbody").find("tr:first").find(".k-icon").length;
var level = $(selectedRow).find(".k-icon").length;
var selectedRowDataItem = treeList.dataItem($(selectedRow));
var prevParentRows = $(selectedRow).prevAll(".parentRow");
if(rootLevel < level){ //selecting the root folder
$("#treelist .k-grid-content table tbody").find("tr:first").addClass("k-selected").attr("aria-selected", true);
}
if(prevParentRows.length > 0) {
var selectedParentRows = [];
prevParentRows = $.grep(prevParentRows, function(n, i) { //get the direct parent of the selected item
var dataItem = treeList.dataItem($(n));
return (dataItem.ID == selectedRowDataItem.ParentID);
});
selectedParentRows.push(prevParentRows[0]); //store it
var result = findParentItems($(selectedRow).prevAll(".parentRow"), selectedRowDataItem, selectedParentRows, level);
for(var i = 0; i < result.length; i++) {
$(result[i]).addClass("k-selected").attr("aria-selected", true); //select the parent folder
}
}
}
</script>
public ActionResult Index()
{
return View();
}
public JsonResult All([DataSourceRequest] DataSourceRequest request)
{
var result = GetHierarchicalData().ToTreeDataSourceResult(request,
e => e.ID,
e => e.ParentID,
e => e
);
return Json(result);
}
//Populate Hierarchical data
public static IList<HierarchicalViewModel> GetHierarchicalData()
{
var result = new List<HierarchicalViewModel>()
{
new HierarchicalViewModel() { ID = 1, ParentID = null, HasChildren = true, Name = "My Documents", Expanded = true, SpriteCssClass = "folder" },
new HierarchicalViewModel() { ID = 2, ParentID = 1, HasChildren = true, Name = "Test Directory 1", Expanded = true, SpriteCssClass = "folder" },
new HierarchicalViewModel() { ID = 3, ParentID = 2, HasChildren = true, Name = "Test Directory 1.1", Expanded = true, SpriteCssClass = "folder" },
new HierarchicalViewModel() { ID = 301, ParentID = 3, HasChildren = true, Name = "Test Directory 1.1.1", Expanded = true, SpriteCssClass = "folder" },
new HierarchicalViewModel() { ID = 302, ParentID = 3, HasChildren = false, Name = "Test Directory 1.1.2", SpriteCssClass = "folder" },
new HierarchicalViewModel() { ID = 3021, ParentID = 301, HasChildren = false, Name = "Test Directory 1.1.1.1", SpriteCssClass = "folder" },
new HierarchicalViewModel() { ID = 3022, ParentID = 301, HasChildren = true, Name = "Test Directory 1.1.1.2", Expanded = true, SpriteCssClass = "folder" },
new HierarchicalViewModel() { ID = 3023, ParentID = 3022, HasChildren = false, Name = "Test Directory 1.1.1.2.1", SpriteCssClass = "folder" },
new HierarchicalViewModel() { ID = 3024, ParentID = 3022, HasChildren = false, Name = "Test Directory 1.1.1.2.2", SpriteCssClass = "folder" },
new HierarchicalViewModel() { ID = 4, ParentID = 1, HasChildren = true, Name = "New Web Site", Expanded = true, SpriteCssClass = "folder" },
new HierarchicalViewModel() { ID = 5, ParentID = 4, HasChildren = true, Name = "mockup.jpg", Expanded = true, SpriteCssClass = "folder" },
new HierarchicalViewModel() { ID = 100, ParentID = 5, HasChildren = false, Name = "mockup100.jpg", SpriteCssClass = "folder" },
new HierarchicalViewModel() { ID = 101, ParentID = 5, HasChildren = false, Name = "mockup101.jpg", SpriteCssClass = "folder" }
};
return result;
}
public class HierarchicalViewModel
{
public int ID { get; set; }
public int? ParentID { get; set; }
public bool HasChildren { get; set; }
public string Name { get; set; }
public string SpriteCssClass { get; set; }
public string ImageUrl { get; set; }
public bool Expanded { get; set; }
}