Hello,
I am trying to fill the TreeView using an async method. The first level is loaded an expanded. Subsequent levels are not. Or so it seams. They are loaded, but when expanding a node it expands and immediately collapses. Expanding a second time reveals the nodes loaded earlier.
I included a demo project. Open http://localhost:{port}/tree.
Best regards,
Marcel Gelijk
If i collapse/expand any item of treeview then each item of collapsed/expanded branch will be rendered twice.
Clicking in or away from the treeview re-renders all nodes too.
The issue manifests both when
Happens in 2.14.1 first.
*** Thread created by admin on customer behalf ***
I need to be able to multiselect items in a treeview and drag n drop to reorder items.
(Same as RadTreeView AJAX component)
I would like a node click event exposed from the treeview.
At the moment, you need to use a template. Example and considerations are available in the following forum thread: https://www.telerik.com/forums/row-click-and-double-click-events#PQpO8DcbzkCArF3UqoLcWA.
I have an extensive WPF background and so I naturally use ObservableCollection for virtually all UI type binding scenarios.
However I noticed that it seems the TreeView control doesn't seem to work when bound that way.
I switched the property to an array instead and it worked with no other modifications.
Add the following Razor component and run. Click around tree, especially from disclosure icon to node to 'plus' icon. Error will occur.
=====================================
@page "/poopy"
@using Microsoft.AspNetCore.Components
@using Telerik.Blazor
@using Telerik.Blazor.Components
@using Telerik.Blazor.Components.Button
<style>
.k-mid:hover .showme {
display: block;
}
.showme {
display: none;
margin-left: 10px;
}
.showhim:hover .showme {
display: block;
}
</style>
@using Telerik.Blazor.Components.TreeView
<TelerikTreeView Data="@TreeData">
<TelerikTreeViewBindings>
<TelerikTreeViewBinding IdField="Id" ParentIdField="ParentIdValue" ExpandedField="Expanded" HasChildrenField="HasChildren">
<ItemTemplate>
<div @onclick="@(_ => NodeClicked((context as TreeItem).Text))" style="cursor: pointer">@((context as TreeItem).Text)</div>
<div class="showme" @onclick="SayHelloHandler" style="cursor: pointer">
<TelerikIcon IconName="@IconName.Plus" />
</div>
</ItemTemplate>
</TelerikTreeViewBinding>
</TelerikTreeViewBindings>
</TelerikTreeView>
@helloString
@code {
MarkupString helloString;
void NodeClicked(string node)
{
helloString = new MarkupString(node);
}
void SayHelloHandler()
{
string msg = $"Hello from <strong>Telerik Blazor</strong> at {DateTime.Now}.<br /> Now you can use C# to write front-end!";
helloString = new MarkupString(msg);
}
public class TreeItem
{
public int Id { get; set; }
public string Text { get; set; }
public int? ParentIdValue { get; set; }
public bool HasChildren { get; set; }
public bool Expanded { get; set; }
}
public IEnumerable<TreeItem> TreeData { get; set; }
protected override void OnInitialized()
{
LoadTreeData();
}
private void LoadTreeData()
{
List<TreeItem> items = new List<TreeItem>();
items.Add(new TreeItem()
{
Id = 1,
Text = "Project",
ParentIdValue = null,
HasChildren = true,
Expanded = true
});
items.Add(new TreeItem()
{
Id = 2,
Text = "Design",
ParentIdValue = 1,
HasChildren = false,
Expanded = true
});
items.Add(new TreeItem()
{
Id = 3,
Text = "Implementation",
ParentIdValue = 1,
HasChildren = false,
Expanded = true
});
TreeData = items;
}
}
======================================
Microsoft.JSInterop.JSException
HResult=0x80131500@
using
Telerik.Blazor.Components.TreeView
<button
class
=
"btn btn-primary"
@onclick=
"@(() => ChangeTreeData(false))"
>Change tree data</button>
<TelerikTreeView Data=
"@FlatData"
>
<TelerikTreeViewBindings>
<TelerikTreeViewBinding ParentIdField=
"Parent"
ExpandedField=
"IsExpanded"
></TelerikTreeViewBinding>
</TelerikTreeViewBindings>
</TelerikTreeView>
@code {
public
List<TreeItem> FlatData {
get
;
set
; } =
new
List<TreeItem>();
public
class
TreeItem
//most fields use the default names and will bind automatically in this example
{
public
int
Id {
get
;
set
; }
public
string
Text {
get
;
set
; }
public
int
? Parent {
get
;
set
; }
//this is a non-default field name
public
bool
HasChildren {
get
;
set
; }
public
bool
IsExpanded {
get
;
set
; }
//this is a non-default field name
}
protected
override
void
OnInit()
{
ChangeTreeData(
true
);
}
int
currIndex {
get
;
set
; } = 0;
void
ChangeTreeData(
bool
expandItems)
{
currIndex++;
FlatData.Clear();
List<TreeItem> data =
new
List<TreeItem>();
data.Add(
new
TreeItem { Id = currIndex, HasChildren =
true
, IsExpanded = expandItems, Parent =
null
, Text = $
"root {currIndex}"
});
data.Add(
new
TreeItem { Id = currIndex + 1, HasChildren =
false
, IsExpanded = expandItems, Parent = currIndex, Text = $
"root {currIndex}: child one"
});
FlatData.AddRange(data);
}
}
When using load-on-demand, you may not know how much data there is and how many levels deep it will go. You need the OnExpand event to fire for each node so you can call your services and retrieve data.
Unfortunately, it does not fire for the second level of nodes, so you cannot load data for them.