Skip to content

Commit 6ecb251

Browse files
authored
feat(TreeView): add OnBeforeTreeItemClick parameter (#7375)
* feat: 增加 OnBeforeTreeItemClick 方法 * refactor: 代码格式化 * test: 增加单元测试 * test: 更新单元测试 * doc: 增加说明文档
1 parent 1f1ac65 commit 6ecb251

6 files changed

Lines changed: 70 additions & 21 deletions

File tree

src/BootstrapBlazor.Server/Components/Samples/TreeViews.razor

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
@page "/tree-view"
1+
@page "/tree-view"
22
@inject IStringLocalizer<TreeViews> Localizer
33
@inject IStringLocalizer<Foo> LocalizerFoo
44

@@ -15,6 +15,7 @@
1515
<li>@((MarkupString)Localizer["TreeViewsTips6"].Value)</li>
1616
<li>@((MarkupString)Localizer["TreeViewsTips7"].Value)</li>
1717
<li>@((MarkupString)Localizer["TreeViewsTips8"].Value)</li>
18+
<li>@((MarkupString)Localizer["TreeViewsTipsOnBeforeTreeItemClick"].Value)</li>
1819
</ul>
1920
</Tips>
2021

src/BootstrapBlazor.Server/Components/Samples/TreeViews.razor.cs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Licensed to the .NET Foundation under one or more agreements.
1+
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the Apache 2.0 License
33
// See the LICENSE file in the project root for more information.
44
// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
@@ -319,9 +319,9 @@ private static AttributeItem[] GetAttributes() =>
319319
{
320320
Name = "Items",
321321
Description = "menu data set",
322-
Type = "IEnumerable<TreeViewItem>",
322+
Type = "IEnumerable<TreeViewItem<TItem>>",
323323
ValueList = " — ",
324-
DefaultValue = "new List<TreeViewItem>(20)"
324+
DefaultValue = "new List<TreeViewItem<TItem>>(20)"
325325
},
326326
new()
327327
{
@@ -359,23 +359,31 @@ private static AttributeItem[] GetAttributes() =>
359359
{
360360
Name = nameof(TreeView<string>.OnTreeItemClick),
361361
Description = "Callback delegate when tree control node is clicked",
362-
Type = "Func<TreeViewItem, Task>",
362+
Type = "Func<TreeViewItem<TItem>, Task>",
363+
ValueList = " — ",
364+
DefaultValue = " — "
365+
},
366+
new()
367+
{
368+
Name = nameof(TreeView<string>.OnBeforeTreeItemClick),
369+
Description = "点击节点前回调方法",
370+
Type = "Func<TreeViewItem<TItem>, Task<bool>>",
363371
ValueList = " — ",
364372
DefaultValue = " — "
365373
},
366374
new()
367375
{
368376
Name = nameof(TreeView<string>.OnTreeItemChecked),
369377
Description = "Callback delegate when tree control node is selected",
370-
Type = "Func<TreeViewItem, Task>",
378+
Type = "Func<TreeViewItem<TItem>, Task>",
371379
ValueList = " — ",
372380
DefaultValue = " — "
373381
},
374382
new()
375383
{
376384
Name = nameof(TreeView<string>.OnExpandNodeAsync),
377385
Description = "Tree control node expand callback delegate",
378-
Type = "Func<TreeViewItem, Task>",
386+
Type = "Func<TreeViewItem<TItem>, Task>",
379387
ValueList = " — ",
380388
DefaultValue = " — "
381389
},

src/BootstrapBlazor.Server/Locales/en-US.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,7 @@
673673
"TreeViewsTips6": "Set whether the node is <b>expanded</b> state through <code>TreeViewItem&lt;TItem&gt;.IsExpand</code>",
674674
"TreeViewsTips7": "Set whether the node is <b>selected</b> state through <code>TreeViewItem&lt;TItem&gt;.IsActive</code>",
675675
"TreeViewsTips8": "Through <code>TreeViewItem&lt;TItem&gt;.Checked</code>, set whether the node is in <b>checked/single selection</b> state",
676+
"TreeViewsTipsOnBeforeTreeItemClick": "You can prevent a node click by setting the <code>OnBeforeTreeItemClick</code> callback method, and cancel the click action when it returns <code>false</code>.",
676677
"TreeViewsTips9": "Step 1: Set the <code>TItem</code> generic model",
677678
"TreeViewsTips10": "Step 2: Set <code>Items</code> to get the component data source <b>Note</b> The data source type is <code>IEnumerable&lt;TreeViewItem&lt;TItem&gt;&gt;</code>",
678679
"TreeViewsTips11": "Step 3: Set the <code>OnExpandNodeAsync</code> callback delegate to expand the response node to get the child data source collection",

src/BootstrapBlazor.Server/Locales/zh-CN.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,7 @@
673673
"TreeViewsTips6": "通过 <code>TreeViewItem&lt;TItem&gt;.IsExpand</code> 设置节点是否 <b>展开</b> 状态",
674674
"TreeViewsTips7": "通过 <code>TreeViewItem&lt;TItem&gt;.IsActive</code> 设置节点是否 <b>选中</b> 状态",
675675
"TreeViewsTips8": "通过 <code>TreeViewItem&lt;TItem&gt;.Checked</code> 设置节点是否 <b>复选/单选</b> 状态",
676+
"TreeViewsTipsOnBeforeTreeItemClick": "通过设置 <code>OnBeforeTreeItemClick</code> 回调方法可以阻止点击节点动作,返回 <code>false</code> 时取消点击动作",
676677
"TreeViewsTips9": "第一步:设置 <code>TItem</code> 泛型模型",
677678
"TreeViewsTips10": "第二步:设置 <code>Items</code> 获得组件数据源 <b>注意</b> 数据源类型为 <code>IEnumerable&lt;TreeViewItem&lt;TItem&gt;&gt;</code>",
678679
"TreeViewsTips11": "第三步:设置 <code>OnExpandNodeAsync</code> 回调委托响应节点展开获取子项数据源集合",

src/BootstrapBlazor/Components/TreeView/TreeView.razor.cs

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Licensed to the .NET Foundation under one or more agreements.
1+
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the Apache 2.0 License
33
// See the LICENSE file in the project root for more information.
44
// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
@@ -152,6 +152,12 @@ public partial class TreeView<TItem> : IModelEqualityComparer<TItem>
152152
[Parameter]
153153
public Func<TreeViewItem<TItem>, Task>? OnTreeItemClick { get; set; }
154154

155+
/// <summary>
156+
/// 获得/设置 点击节点前回调方法
157+
/// </summary>
158+
[Parameter]
159+
public Func<TreeViewItem<TItem>, Task<bool>>? OnBeforeTreeItemClick { get; set; }
160+
155161
/// <summary>
156162
/// Gets or sets the callback method when a tree item is checked.
157163
/// </summary>
@@ -379,7 +385,7 @@ protected override async Task OnAfterRenderAsync(bool firstRender)
379385
await InvokeVoidAsync("scroll", Id, ScrollIntoViewOptions);
380386
}
381387

382-
if(!firstRender && AllowDrag)
388+
if (!firstRender && AllowDrag)
383389
{
384390
await InvokeVoidAsync("resetTreeViewRow", Id);
385391
}
@@ -590,24 +596,33 @@ private async Task<IEnumerable<IExpandableNode<TItem>>> GetChildrenRowAsync(Tree
590596

591597
private async Task OnClick(TreeViewItem<TItem> item)
592598
{
593-
_activeItem = item;
594-
if (ClickToggleNode && item.CanTriggerClickNode(IsDisabled, CanExpandWhenDisabled))
599+
var confirm = true;
600+
if (OnBeforeTreeItemClick != null)
595601
{
596-
await OnToggleNodeAsync(item);
602+
confirm = await OnBeforeTreeItemClick(item);
597603
}
598604

599-
if (OnTreeItemClick != null)
605+
if (confirm)
600606
{
601-
await OnTreeItemClick(item);
602-
}
607+
_activeItem = item;
608+
if (ClickToggleNode && item.CanTriggerClickNode(IsDisabled, CanExpandWhenDisabled))
609+
{
610+
await OnToggleNodeAsync(item);
611+
}
603612

604-
if (ShowCheckbox && ClickToggleCheck)
605-
{
606-
var state = ToggleCheckState(item.CheckedState);
607-
await OnCheckStateChanged(item, state);
608-
}
613+
if (OnTreeItemClick != null)
614+
{
615+
await OnTreeItemClick(item);
616+
}
609617

610-
StateHasChanged();
618+
if (ShowCheckbox && ClickToggleCheck)
619+
{
620+
var state = ToggleCheckState(item.CheckedState);
621+
await OnCheckStateChanged(item, state);
622+
}
623+
624+
StateHasChanged();
625+
}
611626
}
612627

613628
private async Task OnEnterAsync(string? searchText)

test/UnitTest/Components/TreeViewTest.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -822,6 +822,29 @@ public async Task ClickToggleNode_Ok()
822822
Assert.True(clicked);
823823
}
824824

825+
[Fact]
826+
public async Task OnBeforeTreeItemClick_Ok()
827+
{
828+
var clicked = false;
829+
var cut = Context.Render<TreeView<TreeFoo>>(pb =>
830+
{
831+
pb.Add(a => a.ClickToggleNode, true);
832+
pb.Add(a => a.Items, TreeFoo.GetTreeItems());
833+
pb.Add(a => a.OnTreeItemClick, node =>
834+
{
835+
clicked = true;
836+
return Task.CompletedTask;
837+
});
838+
pb.Add(a => a.OnBeforeTreeItemClick, node =>
839+
{
840+
return Task.FromResult(false);
841+
});
842+
});
843+
var node = cut.FindAll(".tree-node").Skip(1).First();
844+
await cut.InvokeAsync(() => node.Click());
845+
Assert.False(clicked);
846+
}
847+
825848
[Fact]
826849
public void KeyAttribute_Ok()
827850
{

0 commit comments

Comments
 (0)