Skip to content

Commit 0f7f076

Browse files
authored
Merge pull request #102 from telerik/treeview-rename-node
Treeview rename node
2 parents 39ab46b + cbe06c7 commit 0f7f076

31 files changed

+1464
-0
lines changed

treeview/rename-node/readme.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Rename TreeView Node
2+
3+
Tree TreeView component is a data visualization component, and it does not provide editing capabilities out-of-the-box. If your users need to perform CRUD operations a lot, you may want to consider using <a href="https://demos.telerik.com/blazor-ui/treelist/editing-inline" target="_blank">the TreeList component that offers built-in editing</a> (in fact, it offers three different edit modes and UX).
4+
5+
If you want to add editing capabilities to your treeview, the most straight forward way to implement them is to:
6+
7+
1. Create a component that will provide the desired item rendering and editing UX.
8+
* In this sample, it is the `~/Shared/EditableTreeNode.razor` component.
9+
1. Put that component in the <a href="https://docs.telerik.com/blazor-ui/components/treeview/templates" target="_blank">`ItemTemplate`</a> of your treeview.
10+
1. Pass to that component the current item that it will render and edit.
11+
* We pass it as a parameter to the child component.
12+
1. Raise an event after an item was edited so the parent treeview can re-render.
13+
* In this sample we fetch the data from the mock database every time to ensure the TreeView is up-to-date and shows other people's edits. In your case you can choose when and how to make updates.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 16
4+
VisualStudioVersion = 16.0.31313.79
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "rename_node", "rename-node\rename_node.csproj", "{5BA11479-F113-4C80-804A-C1FC7AFFF5B9}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|Any CPU = Debug|Any CPU
11+
Release|Any CPU = Release|Any CPU
12+
EndGlobalSection
13+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
14+
{5BA11479-F113-4C80-804A-C1FC7AFFF5B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15+
{5BA11479-F113-4C80-804A-C1FC7AFFF5B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
16+
{5BA11479-F113-4C80-804A-C1FC7AFFF5B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
17+
{5BA11479-F113-4C80-804A-C1FC7AFFF5B9}.Release|Any CPU.Build.0 = Release|Any CPU
18+
EndGlobalSection
19+
GlobalSection(SolutionProperties) = preSolution
20+
HideSolutionNode = FALSE
21+
EndGlobalSection
22+
GlobalSection(ExtensibilityGlobals) = postSolution
23+
SolutionGuid = {F4DB2B5B-F48B-4C6F-AF60-2BF3F0663C20}
24+
EndGlobalSection
25+
EndGlobal
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<Router AppAssembly="typeof(Program).Assembly">
2+
<Found Context="routeData">
3+
<RouteView RouteData="routeData" DefaultLayout="typeof(MainLayout)" />
4+
</Found>
5+
<NotFound>
6+
<h1>Page not found</h1>
7+
<p>Sorry, but there's nothing here!</p>
8+
</NotFound>
9+
</Router>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Threading.Tasks;
5+
6+
namespace rename_node.Models
7+
{
8+
/// <summary>
9+
/// Sample tree item model, uses the default field names.
10+
/// </summary>
11+
public class TreeItem
12+
{
13+
public int Id { get; set; }
14+
public string Text { get; set; }
15+
public int? ParentId { get; set; }
16+
public bool HasChildren { get; set; }
17+
public string Icon { get; set; }
18+
public bool Expanded { get; set; }
19+
}
20+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
@page "/"
2+
3+
@using rename_node.Models
4+
@using rename_node.Services
5+
@using rename_node.Shared
6+
@inject TreeDataService DataService
7+
8+
<TelerikTreeView Data="@FlatData">
9+
<TreeViewBindings>
10+
<TreeViewBinding>
11+
<ItemTemplate>
12+
@* A component in the Shared folder where we define the desired rendering and UX for editing *@
13+
<EditableTreeNode Item="@(context as TreeItem)" ItemTextChanged="@UpdateData"></EditableTreeNode>
14+
</ItemTemplate>
15+
</TreeViewBinding>
16+
</TreeViewBindings>
17+
</TelerikTreeView>
18+
19+
@code {
20+
List<TreeItem> FlatData { get; set; }
21+
22+
protected override async Task OnInitializedAsync()
23+
{
24+
await FetchData();
25+
}
26+
27+
async Task UpdateData()
28+
{
29+
await FetchData();
30+
}
31+
32+
async Task FetchData()
33+
{
34+
FlatData = await DataService.GetData();
35+
}
36+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
@page "/"
2+
@namespace rename_node.Pages
3+
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
4+
5+
<!DOCTYPE html>
6+
<html lang="en">
7+
<head>
8+
<meta charset="utf-8" />
9+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
10+
<title>rename_node</title>
11+
<base href="~/" />
12+
<link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
13+
<link href="css/site.css" rel="stylesheet" />
14+
<link rel="stylesheet" href="_content/Telerik.UI.for.Blazor/css/kendo-theme-default/all.css" />
15+
<script src="_content/Telerik.UI.for.Blazor/js/telerik-blazor.js" defer></script>
16+
</head>
17+
<body>
18+
<component type="typeof(App)" render-mode="ServerPrerendered" />
19+
20+
<div id="blazor-error-ui">
21+
<environment include="Staging,Production">
22+
An error has occurred. This application may no longer respond until reloaded.
23+
</environment>
24+
<environment include="Development">
25+
An unhandled exception has occurred. See browser dev tools for details.
26+
</environment>
27+
<a href class="reload">Reload</a>
28+
<a class="dismiss">🗙</a>
29+
</div>
30+
31+
<script src="_framework/blazor.server.js"></script>
32+
</body>
33+
</html>
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using Microsoft.AspNetCore;
2+
using Microsoft.AspNetCore.Hosting;
3+
using Microsoft.Extensions.Configuration;
4+
using Microsoft.Extensions.Hosting;
5+
using Microsoft.Extensions.Logging;
6+
using System;
7+
using System.Collections.Generic;
8+
using System.IO;
9+
using System.Linq;
10+
using System.Threading.Tasks;
11+
12+
namespace rename_node
13+
{
14+
public class Program
15+
{
16+
public static void Main(string[] args)
17+
{
18+
CreateHostBuilder(args).Build().Run();
19+
}
20+
21+
public static IHostBuilder CreateHostBuilder(string[] args) =>
22+
Host.CreateDefaultBuilder(args)
23+
.ConfigureWebHostDefaults(webBuilder =>
24+
{
25+
webBuilder.UseStaticWebAssets();
26+
webBuilder.UseStartup<Startup>();
27+
});
28+
}
29+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"iisSettings": {
3+
"windowsAuthentication": false,
4+
"anonymousAuthentication": true,
5+
"iisExpress": {
6+
"applicationUrl": "http://localhost:55276/",
7+
"sslPort": 44398
8+
}
9+
},
10+
"profiles": {
11+
"IIS Express": {
12+
"commandName": "IISExpress",
13+
"launchBrowser": true,
14+
"environmentVariables": {
15+
"ASPNETCORE_ENVIRONMENT": "Development"
16+
}
17+
},
18+
"rename_node": {
19+
"commandName": "Project",
20+
"launchBrowser": true,
21+
"environmentVariables": {
22+
"ASPNETCORE_ENVIRONMENT": "Development"
23+
},
24+
"applicationUrl": "https://localhost:5001;http://localhost:5000"
25+
}
26+
}
27+
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
using rename_node.Models;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Threading.Tasks;
6+
7+
namespace rename_node.Services
8+
{
9+
/// <summary>
10+
/// Simulates real data source (database) operations in memory. Replace with actual storage and logic.
11+
/// </summary>
12+
public class TreeDataService
13+
{
14+
List<TreeItem> items = new List<TreeItem>();
15+
16+
public async Task<List<TreeItem>> GetData()
17+
{
18+
EnsureData();
19+
return await Task.FromResult(new List<TreeItem>(items));
20+
}
21+
22+
public async Task UpdateNode(TreeItem itemToUpdate)
23+
{
24+
int itmIndex = items.FindIndex(itm => itm.Id == itemToUpdate.Id);
25+
if(itmIndex > -1)
26+
{
27+
items[itmIndex] = itemToUpdate;
28+
}
29+
}
30+
31+
private void EnsureData()
32+
{
33+
if (items == null || !items.Any())
34+
{
35+
GenerateData();
36+
}
37+
}
38+
39+
private void GenerateData()
40+
{
41+
items = new List<TreeItem>();
42+
43+
items.Add(new TreeItem()
44+
{
45+
Id = 1,
46+
Text = "Project",
47+
ParentId = null,
48+
HasChildren = true,
49+
Icon = "folder",
50+
Expanded = true
51+
});
52+
53+
items.Add(new TreeItem()
54+
{
55+
Id = 2,
56+
Text = "Design",
57+
ParentId = 1,
58+
HasChildren = true,
59+
Icon = "brush",
60+
Expanded = true
61+
});
62+
items.Add(new TreeItem()
63+
{
64+
Id = 3,
65+
Text = "Implementation",
66+
ParentId = 1,
67+
HasChildren = true,
68+
Icon = "folder",
69+
Expanded = true
70+
});
71+
72+
items.Add(new TreeItem()
73+
{
74+
Id = 4,
75+
Text = "site.psd",
76+
ParentId = 2,
77+
HasChildren = false,
78+
Icon = "psd",
79+
Expanded = true
80+
});
81+
items.Add(new TreeItem()
82+
{
83+
Id = 5,
84+
Text = "index.js",
85+
ParentId = 3,
86+
HasChildren = false,
87+
Icon = "js"
88+
});
89+
items.Add(new TreeItem()
90+
{
91+
Id = 6,
92+
Text = "index.html",
93+
ParentId = 3,
94+
HasChildren = false,
95+
Icon = "html"
96+
});
97+
items.Add(new TreeItem()
98+
{
99+
Id = 7,
100+
Text = "styles.css",
101+
ParentId = 3,
102+
HasChildren = false,
103+
Icon = "css"
104+
});
105+
}
106+
}
107+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
@using rename_node.Models
2+
@using rename_node.Services
3+
@inject TreeDataService DataService
4+
5+
@if (!string.IsNullOrEmpty(Item.Icon))
6+
{
7+
<TelerikIcon Icon="@Item.Icon"></TelerikIcon>
8+
}
9+
@if (!IsEditing)
10+
{
11+
<span style="margin-right: 1em;">@Item.Text</span>
12+
<TelerikButton Icon="pencil" OnClick="@Edit" Class="k-flat"></TelerikButton>
13+
}
14+
else
15+
{
16+
<span @onclick:stopPropagation="true">@* Stop the treenode from taking focus when you click in the textbox *@
17+
<TelerikTextBox @bind-Value="@Item.Text" @ref="@tbRef"></TelerikTextBox>
18+
</span>
19+
<TelerikButton Icon="save" OnClick="@Save"></TelerikButton>
20+
}
21+
22+
23+
@code {
24+
[Parameter]
25+
public TreeItem Item { get; set; }
26+
[Parameter]
27+
public EventCallback ItemTextChanged { get; set; }
28+
29+
TelerikTextBox tbRef { get; set; }
30+
bool IsEditing { get; set; }
31+
32+
async Task Edit()
33+
{
34+
IsEditing = true;
35+
36+
//give rendering time to put the markup in and populate the reference
37+
await InvokeAsync(StateHasChanged);
38+
await Task.Delay(20);
39+
40+
if (tbRef != null)
41+
{
42+
await tbRef.FocusAsync();
43+
}
44+
}
45+
46+
async Task Save()
47+
{
48+
IsEditing = false;
49+
await DataService.UpdateNode(Item);
50+
await ItemTextChanged.InvokeAsync();
51+
}
52+
}

0 commit comments

Comments
 (0)