mirror of
https://gitee.com/ant-design-blazor/ant-design-blazor.git
synced 2024-11-29 18:48:50 +08:00
merge master to feature
This commit is contained in:
commit
3ac7701da4
@ -14,6 +14,34 @@ timeline: true
|
||||
- Major version release is not included in this schedule for breaking change and new features.
|
||||
|
||||
---
|
||||
### 0.11.0
|
||||
|
||||
`2022-06-16`
|
||||
|
||||
🌈Every cloud has a silver lining.
|
||||
|
||||
- Table
|
||||
- 🔥 support for Table virtualization [#2143](https://github.com/ant-design-blazor/ant-design-blazor/pull/2143) [@anranruye](https://github.com/anranruye)
|
||||
- 🔥 Support to control/restore table filter/sorter state using existing QueryModel [#2129](https://github.com/ant-design-blazor/ant-design-blazor/pull/2129) [@AnaNikolasevic](https://github.com/AnaNikolasevic)
|
||||
- 🆕 support setting table scrollbar width using `ScrollBarWidth` parameter. [#2451](https://github.com/ant-design-blazor/ant-design-blazor/pull/2451) [@ElderJames](https://github.com/ElderJames)
|
||||
- 🆕 support for using built-in logic when defining the PaginationTemplate. [#2220](https://github.com/ant-design-blazor/ant-design-blazor/pull/2220) [@anranruye](https://github.com/anranruye)
|
||||
- 🛠 make Responsive default to false (with a breaking change). [#2419](https://github.com/ant-design-blazor/ant-design-blazor/pull/2419) [@ElderJames](https://github.com/ElderJames)
|
||||
- 🛠 Use Small size Pagination to fit compact Table [#2246](https://github.com/ant-design-blazor/ant-design-blazor/pull/2246) [@anranruye](https://github.com/anranruye)
|
||||
|
||||
- TreeSelect
|
||||
- 🐞 Fixed TreeSelect expressions and selection [#2507](https://github.com/ant-design-blazor/ant-design-blazor/pull/2507) [@ElderJames](https://github.com/ElderJames)
|
||||
- 🐞 Fixed TreeSelect binding default where it did not show selected items [#2134](https://github.com/ant-design-blazor/ant-design-blazor/pull/2134) [@gmij](https://github.com/gmij)
|
||||
|
||||
- 🆕 Add Upload support for incorporating build-in InputFile [#2443](https://github.com/ant-design-blazor/ant-design-blazor/pull/2443) [@ElderJames](https://github.com/ElderJames)
|
||||
- 🆕 Add Select search debounce. [#2275](https://github.com/ant-design-blazor/ant-design-blazor/pull/2275) [@tompru](https://github.com/tompru)
|
||||
- 🆕 Component library added .net 6 target framework [#2484](https://github.com/ant-design-blazor/ant-design-blazor/pull/2484) [@ElderJames](https://github.com/ElderJames)
|
||||
- ⌨️ Add Form Feedback Icon when Invalid [#2418](https://github.com/ant-design-blazor/ant-design-blazor/pull/2418) [@bweissronin](https://github.com/bweissronin)
|
||||
- ⌨️ Add Checkbox supports trigger check when clicking label [#2296](https://github.com/ant-design-blazor/ant-design-blazor/pull/2296) [@bweissronin](https://github.com/bweissronin)
|
||||
- ⌨️ Add Icon `Alt` Parameter to set the alt attribute that pairs with role="img" [#2302](https://github.com/ant-design-blazor/ant-design-blazor/pull/2302) [@bweissronin](https://github.com/bweissronin)
|
||||
- ⌨️ Add Button `AriaLabel` Parameter [#2278](https://github.com/ant-design-blazor/ant-design-blazor/pull/2278) [@bweissronin](https://github.com/bweissronin)
|
||||
- 🐞 Fixed Tree incorrect checking during initialization. [#2506](https://github.com/ant-design-blazor/ant-design-blazor/pull/2506) [@ElderJames](https://github.com/ElderJames)
|
||||
- 🐞 Fixed DatePicker that week selection issue when unable to click date selection. [#2463](https://github.com/ant-design-blazor/ant-design-blazor/pull/2463) [@WhyILoveSpringRoll](https://github.com/WhyILoveSpringRoll)
|
||||
- 📖 docs(faq): add CSS isolation explanation. [#2158](https://github.com/ant-design-blazor/ant-design-blazor/pull/2158) [@dennisrahmen](https://github.com/dennisrahmen)
|
||||
|
||||
### 0.10.7
|
||||
|
||||
|
@ -14,6 +14,39 @@ timeline: true
|
||||
- 主版本号:含有破坏性更新和新特性,不在发布周期内。
|
||||
|
||||
---
|
||||
|
||||
### 0.11.0
|
||||
|
||||
`2022-06-16`
|
||||
|
||||
🌈守得云开见月明~
|
||||
|
||||
- Table
|
||||
- 🔥 支持虚拟化[#2143](https://github.com/ant-design-blazor/ant-design-blazor/pull/2143) [@anranruye](https://github.com/anranruye)
|
||||
- 🔥 支持使用已有的 QueryModel 控制/恢复表格筛选排序状态[#2129](https://github.com/ant-design-blazor/ant-design-blazor/pull/2129) [@AnaNikolasevic](https://github.com/AnaNikolasevic)
|
||||
- 🆕 支持用 `ScrollBarWidth` 属性来设置滚动条的宽度。[#2451](https://github.com/ant-design-blazor/ant-design-blazor/pull/2451) [@ElderJames](https://github.com/ElderJames)
|
||||
- 🆕 允许在定义 `PaginationTemplate` 时使用组件内置逻辑。[#2220](https://github.com/ant-design-blazor/ant-design-blazor/pull/2220) [@anranruye](https://github.com/anranruye)
|
||||
- 🛠 修改 Responsive 属性默认值为false,需要响应式样式时需要设为true。[#2419](https://github.com/ant-design-blazor/ant-design-blazor/pull/2419) [@ElderJames](https://github.com/ElderJames)
|
||||
- 🛠 使用 Small 大小的Pagination来适配紧凑型Table[#2246](https://github.com/ant-design-blazor/ant-design-blazor/pull/2246) [@anranruye](https://github.com/anranruye)
|
||||
|
||||
- 🆕 增加 Upload 支持结合原生 InputFile 组件。[#2443](https://github.com/ant-design-blazor/ant-design-blazor/pull/2443) [@ElderJames](https://github.com/ElderJames)
|
||||
|
||||
- 🆕 增加 Select 搜索框防抖延时绑定。[#2275](https://github.com/ant-design-blazor/ant-design-blazor/pull/2275) [@tompru](https://github.com/tompru)
|
||||
- 🆕 组件库增加 .NET 6 目标框架。[#2484](https://github.com/ant-design-blazor/ant-design-blazor/pull/2484) [@ElderJames](https://github.com/ElderJames)
|
||||
|
||||
- TreeSelect
|
||||
- 🐞 修复表达式和选择功能。[#2507](https://github.com/ant-design-blazor/ant-design-blazor/pull/2507) [@ElderJames](https://github.com/ElderJames)
|
||||
- 🐞 修复绑定默认值时,没有显示选中项。[#2134](https://github.com/ant-design-blazor/ant-design-blazor/pull/2134) [@gmij](https://github.com/gmij)
|
||||
|
||||
- 🐞 修复 DatePicker 点击日期时,不能选中周的问题[#2463](https://github.com/ant-design-blazor/ant-design-blazor/pull/2463) [@WhyILoveSpringRoll](https://github.com/WhyILoveSpringRoll)
|
||||
- 🐞 修复 Tree 初始化时 checkbox 不能正常选中的问题。[#2506](https://github.com/ant-design-blazor/ant-design-blazor/pull/2506) [@ElderJames](https://github.com/ElderJames)
|
||||
|
||||
- ⌨️ 增加 Form 支持当验证失败时显示Feedback图标。[#2418](https://github.com/ant-design-blazor/ant-design-blazor/pull/2418) [@bweissronin](https://github.com/bweissronin)
|
||||
- ⌨️ 增加 Checkbox 支持点击标签时触发勾选[#2296](https://github.com/ant-design-blazor/ant-design-blazor/pull/2296) [@bweissronin](https://github.com/bweissronin)
|
||||
- ⌨️ 增加 Icon Alt 属性,与原来的`role="img"` 搭配[#2302](https://github.com/ant-design-blazor/ant-design-blazor/pull/2302) [@bweissronin](https://github.com/bweissronin)
|
||||
- ⌨️ 增加 Button AriaLabel 属性[#2278](https://github.com/ant-design-blazor/ant-design-blazor/pull/2278) [@bweissronin](https://github.com/bweissronin)
|
||||
- 📖 常用问答增加 CSS 隔离的组件样式修改方式[#2158](https://github.com/ant-design-blazor/ant-design-blazor/pull/2158) [@dennisrahmen](https://github.com/dennisrahmen)
|
||||
|
||||
### 0.10.7
|
||||
|
||||
`2022-05-22`
|
||||
|
@ -1,6 +1,6 @@
|
||||
<p align="center">
|
||||
<a href="https://yangshunjie.com/ant-design-blazor/">
|
||||
<img src="https://raw.githubusercontent.com/ant-design-blazor/ant-design-blazor/logo.svg?sanitize=true">
|
||||
<img src="https://raw.githubusercontent.com/ant-design-blazor/ant-design-blazor/master/logo.svg?sanitize=true">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
@ -52,7 +52,7 @@ WebAssembly 静态托管页面示例
|
||||
- 可直接运行在 [.NET MAUI](https://dotnet.microsoft.com/zh-cn/apps/maui?WT.mc_id=DT-MVP-5003987)、[WPF](https://docs.microsoft.com/en-us/aspnet/core/blazor/hybrid/tutorials/wpf?view=aspnetcore-6.0&WT.mc_id=DT-MVP-5003987)、[Windows Forms](https://docs.microsoft.com/en-us/aspnet/core/blazor/hybrid/tutorials/windows-forms?view=aspnetcore-6.0) 等 Blazor 混合客户端环境中。
|
||||
- 可直接运行在 [Electron](http://electron.atom.io/) 等基于 Web 标准的环境上。
|
||||
|
||||
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br> Edge / IE | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/src/opera/opera_48x48.png" alt="Opera" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Opera | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/src/electron/electron_48x48.png" alt="Electron" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Electron |
|
||||
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br> Edge / IE | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/opera/opera_48x48.png" alt="Opera" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Opera | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/electron/electron_48x48.png" alt="Electron" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Electron |
|
||||
| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
|
||||
| Edge 16 / IE 11† | 522 | 57 | 11 | 44 | Chromium 57 |
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
<p align="center">
|
||||
<a href="https://yangshunjie.com/ant-design-blazor/">
|
||||
<img src="https://raw.githubusercontent.com/ant-design-blazor/ant-design-blazor/logo.svg?sanitize=true">
|
||||
<img src="https://raw.githubusercontent.com/ant-design-blazor/ant-design-blazor/master/logo.svg?sanitize=true">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
@ -51,7 +51,7 @@ WebAssembly static hosting examples:
|
||||
- Run directly on [.NET MAUI](https://dotnet.microsoft.com/zh-cn/apps/maui?WT.mc_id=DT-MVP-5003987) / [WPF](https://docs.microsoft.com/en-us/aspnet/core/blazor/hybrid/tutorials/wpf?view=aspnetcore-6.0&WT.mc_id=DT-MVP-5003987) / [Windows Forms](https://docs.microsoft.com/en-us/aspnet/core/blazor/hybrid/tutorials/windows-forms?view=aspnetcore-6.0) and other Blazor Hybrid workloads.
|
||||
- Run directly on [Electron](http://electron.atom.io/) and other Web standards-based environments.
|
||||
|
||||
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br> Edge / IE | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/src/opera/opera_48x48.png" alt="Opera" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Opera | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/src/electron/electron_48x48.png" alt="Electron" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Electron |
|
||||
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br> Edge / IE | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/opera/opera_48x48.png" alt="Opera" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Opera | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/electron/electron_48x48.png" alt="Electron" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Electron |
|
||||
| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
|
||||
| Edge 16 / IE 11† | 522 | 57 | 11 | 44 | Chromium 57 |
|
||||
|
||||
@ -166,7 +166,7 @@ Options for the template:
|
||||
- Clone to local development
|
||||
|
||||
```bash
|
||||
$ git clone git@github.com:ant-design-blazor/ant-design-blazor.git
|
||||
$ git clone https://github.com/ant-design-blazor/ant-design-blazor.git
|
||||
$ cd ant-design-blazor
|
||||
$ npm install
|
||||
$ dotnet build ./site/AntDesign.Docs.Build/AntDesign.Docs.Build.csproj
|
||||
@ -221,7 +221,7 @@ If you encounter any problems in the process, feel free to ask for help via foll
|
||||
|
||||
<details>
|
||||
<summary>Scan QR Code with DingTalk</summary>
|
||||
<img src="https://raw.githubusercontent.com/ant-design-blazor/ant-design-blazor/docs/assets/dingtalk.jpg" width="300">
|
||||
<img src="https://raw.githubusercontent.com/ant-design-blazor/ant-design-blazor/master/docs/assets/dingtalk.jpg" width="300">
|
||||
</details>
|
||||
|
||||
## Code of Conduct
|
||||
|
@ -121,6 +121,7 @@ namespace AntDesign
|
||||
{
|
||||
base.OnValueChange(value);
|
||||
RefreshNodeValue(value);
|
||||
RefreshDisplayText();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -178,13 +179,16 @@ namespace AntDesign
|
||||
/// <summary>
|
||||
/// 清除已选择项
|
||||
/// </summary>
|
||||
private void ClearSelected()
|
||||
private async Task ClearSelected()
|
||||
{
|
||||
_selectedNodes.Clear();
|
||||
_hoverSelectedNodes.Clear();
|
||||
_displayText = string.Empty;
|
||||
SetValue(string.Empty);
|
||||
_dropdownOpened = false;
|
||||
|
||||
_searchValue = string.Empty;
|
||||
await this.FocusAsync(_inputRef);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -25,15 +25,58 @@ namespace AntDesign
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// 是否显示右上角的关闭按钮
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Whether a close (x) button is visible on top right of the Drawer dialog or not.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool Closable { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// 点击蒙层是否允许关闭
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Clicking on the mask (area outside the Drawer) to close the Drawer or not.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool MaskClosable { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// 是否显示蒙层
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Whether to show mask or not.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool Mask { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// 蒙层样式
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Style for Drawer's mask element.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string MaskStyle { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// 是否支持键盘 esc 关闭
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Whether to support keyboard esc off
|
||||
/// </para>
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool Keyboard { get; set; } = true;
|
||||
|
||||
@ -43,6 +86,14 @@ namespace AntDesign
|
||||
|
||||
private OneOf<RenderFragment, string> _title;
|
||||
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// 标题
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The title for Drawer.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public OneOf<RenderFragment, string> Title
|
||||
{
|
||||
@ -63,20 +114,68 @@ namespace AntDesign
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// "left" | "right" | "top" | "bottom"
|
||||
/// <para>
|
||||
/// Drawer 的位置,字符串, "left" | "right" | "top" | "bottom"
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The placement of the Drawer, option could be left, top, right, bottom
|
||||
/// </para>
|
||||
/// </summary>
|
||||
[Parameter] public string Placement { get; set; } = "right";
|
||||
[Parameter]
|
||||
public string Placement { get; set; } = "right";
|
||||
|
||||
[Parameter] public string MaskStyle { get; set; }
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// Drawer body 样式
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Body style for modal body element. Such as height, padding etc.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string BodyStyle { get; set; }
|
||||
|
||||
[Parameter] public string BodyStyle { get; set; }
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// Drawer对话框外层容器的类名
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The class name of the container of the Drawer dialog.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string WrapClassName { get; set; }
|
||||
|
||||
[Parameter] public string WrapClassName { get; set; }
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// 宽度,仅当 <see cref="Placement"/> 为 "left" 或 "right" 时生效
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Width of the Drawer dialog, only when placement is 'left' or 'right'.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public int Width { get; set; } = 256;
|
||||
|
||||
[Parameter] public int Width { get; set; } = 256;
|
||||
|
||||
[Parameter] public int Height { get; set; } = 256;
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// 高度,仅当 <see cref="Placement"/> 为 "top" 或 "bottom" 时生效
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Height of the Drawer dialog, only when placement is 'top' or 'bottom'.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public int Height { get; set; } = 256;
|
||||
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// 设置 Drawer 的 z-index
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The z-index of the Drawer.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public int ZIndex
|
||||
{
|
||||
@ -93,10 +192,36 @@ namespace AntDesign
|
||||
|
||||
private string InnerZIndexStyle => (_status.IsOpen() || _status == ComponentStatus.Closing) ? _zIndexStyle : "z-index:-9999;";
|
||||
|
||||
[Parameter] public int OffsetX { get; set; } = 0;
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// X 轴方向的偏移量,只在方向为 'left'或'right' 时生效.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The the X coordinate offset(px), only when placement is 'left' or 'right'.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public int OffsetX { get; set; } = 0;
|
||||
|
||||
[Parameter] public int OffsetY { get; set; } = 0;
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// Y 轴方向的偏移量,只在方向为 'top'或'bottom' 时生效
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The the Y coordinate offset(px), only when placement is 'top' or 'bottom'.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public int OffsetY { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// Drawer 是否可见
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Whether the Drawer dialog is visible or not.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool Visible
|
||||
{
|
||||
@ -115,10 +240,30 @@ namespace AntDesign
|
||||
}
|
||||
}
|
||||
|
||||
[Parameter] public EventCallback OnClose { get; set; }
|
||||
[Parameter] public RenderFragment Handler { get; set; }
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// 在 Drawer 打开前的回调事件
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Specify a callback that will be called before drawer displayed
|
||||
/// </para>
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public Func<Task> OnOpen { get; set; }
|
||||
|
||||
#endregion
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// 在 关闭 前的回调事件,应当在 OnClose 将 <see cref="Visible"/> 设置为false
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Specify a callback that will be called when a user clicks mask, close button or Cancel button.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public EventCallback OnClose { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public RenderFragment Handler { get; set; }
|
||||
|
||||
private OneOf<RenderFragment, string> _content;
|
||||
|
||||
@ -126,6 +271,8 @@ namespace AntDesign
|
||||
|
||||
private RenderFragment ContentTemplate { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
private ComponentStatus _status;
|
||||
private bool _hasInvokeClosed;
|
||||
private bool _isOpen = default;
|
||||
@ -257,6 +404,12 @@ namespace AntDesign
|
||||
case ComponentStatus.Opening:
|
||||
{
|
||||
_status = ComponentStatus.Opened;
|
||||
|
||||
if (OnOpen != null)
|
||||
{
|
||||
await OnOpen.Invoke();
|
||||
}
|
||||
|
||||
_hasInvokeClosed = false;
|
||||
if (string.IsNullOrWhiteSpace(Style))
|
||||
{
|
||||
|
@ -22,6 +22,7 @@
|
||||
OffsetX="@drawerConfig.OffsetX"
|
||||
OffsetY="@drawerConfig.OffsetY"
|
||||
Visible="@drawerConfig.Visible"
|
||||
OnOpen="@drawerRef.OnOpen"
|
||||
OnClose="@drawerRef.CloseAsync">
|
||||
@drawerConfig.ChildContent
|
||||
</Drawer>
|
||||
|
@ -50,8 +50,6 @@ namespace AntDesign
|
||||
public override async Task OpenAsync()
|
||||
{
|
||||
await _service.OpenAsync(this);
|
||||
if (OnOpen != null)
|
||||
await OnOpen.Invoke();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -1,29 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
|
||||
namespace AntDesign
|
||||
{
|
||||
public class DrawerClosingEventArgs
|
||||
{
|
||||
private bool _rejected;
|
||||
|
||||
public DrawerClosingEventArgs() { }
|
||||
|
||||
public DrawerClosingEventArgs(bool reject)
|
||||
{
|
||||
_rejected = reject;
|
||||
}
|
||||
|
||||
internal bool Rejected { get => _rejected; }
|
||||
|
||||
/// <summary>
|
||||
/// Reject to close
|
||||
/// </summary>
|
||||
public void Reject()
|
||||
{
|
||||
_rejected = true;
|
||||
}
|
||||
}
|
||||
}
|
17
components/drawer/config/DrawerOpenEventArgs.cs
Normal file
17
components/drawer/config/DrawerOpenEventArgs.cs
Normal file
@ -0,0 +1,17 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
#nullable enable
|
||||
namespace AntDesign;
|
||||
|
||||
public class DrawerOpenEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置一个值,该值指示是否应取消事件。
|
||||
/// 返回结果: true 如果应取消事件;否则为 false。
|
||||
/// Gets or sets a value indicating whether the event should be cancelled.
|
||||
/// Return result: true if the event should be cancelled; otherwise false.
|
||||
/// </summary>
|
||||
public bool Cancel { get; set; }
|
||||
}
|
@ -30,7 +30,7 @@ namespace AntDesign
|
||||
{
|
||||
_step = value;
|
||||
NumberFormatInfo nfi = CultureInfo.NumberFormat;
|
||||
var stepStr = _step.ToString();
|
||||
var stepStr = Convert.ToDecimal(_step).ToString(nfi);
|
||||
if (string.IsNullOrEmpty(_format))
|
||||
{
|
||||
_format = string.Join('.', stepStr.Split(nfi.NumberDecimalSeparator).Select(n => new string('0', n.Length)));
|
||||
|
@ -333,6 +333,7 @@ namespace AntDesign
|
||||
{
|
||||
if (CurrentValueAsString != args?.Value?.ToString())
|
||||
{
|
||||
CurrentValueAsString = args?.Value?.ToString();
|
||||
if (OnChange.HasDelegate)
|
||||
{
|
||||
await OnChange.InvokeAsync(Value);
|
||||
@ -636,11 +637,12 @@ namespace AntDesign
|
||||
}
|
||||
|
||||
// onchange 和 onblur 事件会导致点击 OnSearch 按钮时不触发 Click 事件,暂时取消这两个事件
|
||||
if (!IgnoreOnChangeAndBlur)
|
||||
{
|
||||
//2022-8-3 去掉if后,search也能正常工作
|
||||
//if (!IgnoreOnChangeAndBlur)
|
||||
//{
|
||||
builder.AddAttribute(70, "onchange", CallbackFactory.Create(this, OnChangeAsync));
|
||||
builder.AddAttribute(71, "onblur", CallbackFactory.Create(this, OnBlurAsync));
|
||||
}
|
||||
//}
|
||||
|
||||
builder.AddAttribute(72, "onkeypress", CallbackFactory.Create(this, OnKeyPressAsync));
|
||||
builder.AddAttribute(73, "onkeydown", CallbackFactory.Create(this, OnkeyDownAsync));
|
||||
|
@ -44,6 +44,9 @@ namespace AntDesign
|
||||
}
|
||||
}
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<bool> CollapsedChanged { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<bool> OnCollapse { get; set; }
|
||||
|
||||
@ -132,6 +135,11 @@ namespace AntDesign
|
||||
{
|
||||
OnCollapse.InvokeAsync(_isCollapsed);
|
||||
}
|
||||
|
||||
if (CollapsedChanged.HasDelegate)
|
||||
{
|
||||
CollapsedChanged.InvokeAsync(_isCollapsed);
|
||||
}
|
||||
}
|
||||
|
||||
private void OptimizeSize(decimal windowWidth)
|
||||
@ -165,6 +173,11 @@ namespace AntDesign
|
||||
{
|
||||
OnCollapse.InvokeAsync(_isCollapsed);
|
||||
}
|
||||
|
||||
if (CollapsedChanged.HasDelegate)
|
||||
{
|
||||
CollapsedChanged.InvokeAsync(_isCollapsed);
|
||||
}
|
||||
}
|
||||
|
||||
StateHasChanged();
|
||||
|
@ -312,6 +312,21 @@ namespace AntDesign
|
||||
return style;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// clear ant-model enter class, which will disable user-select.
|
||||
/// more details see style/mixins/modal-mask.less
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal async Task CleanShowAnimationAsync()
|
||||
{
|
||||
var animationTimeMs = 300;
|
||||
await Task.Delay(animationTimeMs);
|
||||
_maskAnimationClsName = "";
|
||||
_modalAnimationClsName = "";
|
||||
await InvokeStateHasChangedAsync();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Hide Dialog through animation
|
||||
/// </summary>
|
||||
|
@ -102,6 +102,7 @@ namespace AntDesign
|
||||
_hideDone = false;
|
||||
_hasDestroy = false;
|
||||
|
||||
await _dialog.CleanShowAnimationAsync();
|
||||
if (OnAfterShow.HasDelegate)
|
||||
{
|
||||
await OnAfterShow.InvokeAsync(null);
|
||||
|
@ -6,7 +6,7 @@ namespace AntDesign
|
||||
{
|
||||
public sealed class ModalAnimation
|
||||
{
|
||||
public const string ModalEnter = " ant-zoom-enter ant-zoom-enter-active ant-zoom-enter";
|
||||
public const string ModalEnter = " ant-zoom-enter ant-zoom-enter-active ant-zoom";
|
||||
public const string ModalLeave = " ant-zoom-leave ant-zoom-leave-active ant-zoom";
|
||||
|
||||
public const string MaskEnter = " ant-fade-enter ant-fade-enter-active ant-fade";
|
||||
|
@ -209,6 +209,7 @@
|
||||
Page="@key"
|
||||
Active="@(_current == key)"
|
||||
ShowTitle="ShowTitle"
|
||||
Class=""
|
||||
ItemRender="@ItemRender"/>
|
||||
);
|
||||
}
|
||||
@ -239,7 +240,7 @@
|
||||
Page="@right"
|
||||
Active="@(_current == right)"
|
||||
ShowTitle="ShowTitle"
|
||||
Class="@($"{PrefixCls}-item-after-jump-prev")"
|
||||
Class="@($"{PrefixCls}-item-before-jump-next")"
|
||||
ItemRender="@ItemRender"/>;
|
||||
pagerList.AddLast(jumpNext);
|
||||
}
|
||||
|
@ -46,7 +46,6 @@
|
||||
var prefixCls = $"{RootPrefixCls}-item";
|
||||
ClassMapper.Add(prefixCls).Add($"{prefixCls}-{Page}")
|
||||
.If($"{prefixCls}-active", () => Active)
|
||||
.If(Class, () => !string.IsNullOrWhiteSpace(Class))
|
||||
.If($"{prefixCls}-disabled", () => Page == 0);
|
||||
|
||||
base.OnInitialized();
|
||||
|
@ -737,8 +737,8 @@ namespace AntDesign
|
||||
{
|
||||
if (!updateSelectOption.IsSelected)
|
||||
{
|
||||
updateSelectOption.IsSelected = isSelected;
|
||||
SelectedOptionItems.Add(updateSelectOption);
|
||||
//updateSelectOption.IsSelected = isSelected;
|
||||
//SelectedOptionItems.Add(updateSelectOption);
|
||||
}
|
||||
processedSelectedCount--;
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using OneOf;
|
||||
|
||||
#endregion
|
||||
#endregion using block
|
||||
|
||||
namespace AntDesign
|
||||
{
|
||||
@ -34,7 +34,6 @@ namespace AntDesign
|
||||
internal ElementReference _inputRef;
|
||||
protected bool _isInitialized;
|
||||
|
||||
|
||||
protected bool _isPrimitive;
|
||||
|
||||
/// <summary>
|
||||
@ -50,7 +49,6 @@ namespace AntDesign
|
||||
protected string _prevSearchValue = string.Empty;
|
||||
protected string _searchValue = string.Empty;
|
||||
|
||||
|
||||
protected SelectContent<TItemValue, TItem> _selectContent;
|
||||
|
||||
protected IEnumerable<TItemValue> _selectedValues;
|
||||
@ -58,77 +56,93 @@ namespace AntDesign
|
||||
protected Action<TItem, string> _setLabel;
|
||||
|
||||
protected Action<TItem, TItemValue> _setValue;
|
||||
|
||||
/// <summary>
|
||||
/// Show clear button. Has no effect if <see cref="AntInputComponentBase{TValue}.Value"/> type default
|
||||
/// is also in the list of <see cref="SelectOption{TItemValue, TItem}"/>,
|
||||
/// Show clear button. Has no effect if <see cref="AntInputComponentBase{TValue}.Value"/> type default
|
||||
/// is also in the list of <see cref="SelectOption{TItemValue, TItem}"/>,
|
||||
/// unless used with <see cref="ValueOnClear"/>.
|
||||
/// </summary>
|
||||
[Parameter] public bool AllowClear { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether the current search will be cleared on selecting an item.
|
||||
/// </summary>
|
||||
[Parameter] public bool AutoClearSearchValue { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the Select component is disabled.
|
||||
/// </summary>
|
||||
[Parameter] public bool Disabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Set mode of Select - default | multiple | tags
|
||||
/// </summary>
|
||||
[Parameter] public string Mode { get; set; } = "default";
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the search function is active or not. Always true for mode tags.
|
||||
/// </summary>
|
||||
[Parameter] public bool EnableSearch { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Delays the processing of the search input event until the user has stopped
|
||||
/// Delays the processing of the search input event until the user has stopped
|
||||
/// typing for a predetermined amount of time
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public int SearchDebounceMilliseconds { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Show loading indicator. You have to write the loading logic on your own.
|
||||
/// </summary>
|
||||
[Parameter] public bool Loading { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Controlled open state of dropdown.
|
||||
/// </summary>
|
||||
[Parameter] public bool Open { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Placeholder of select.
|
||||
/// </summary>
|
||||
[Parameter] public string Placeholder { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Called when focus.
|
||||
/// </summary>
|
||||
[Parameter] public EventCallback OnFocus { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The name of the property to be used as a group indicator.
|
||||
/// If the value is set, the entries are displayed in groups.
|
||||
/// The name of the property to be used as a group indicator.
|
||||
/// If the value is set, the entries are displayed in groups.
|
||||
/// Use additional SortByGroup and SortByLabel.
|
||||
/// </summary>
|
||||
[Parameter] public SortDirection SortByGroup { get; set; } = SortDirection.None;
|
||||
|
||||
/// <summary>
|
||||
/// Sort items by label value. None | Ascending | Descending
|
||||
/// </summary>
|
||||
[Parameter] public SortDirection SortByLabel { get; set; } = SortDirection.None;
|
||||
|
||||
/// <summary>
|
||||
/// Hides the selected items when they are selected.
|
||||
/// </summary>
|
||||
[Parameter] public bool HideSelected { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Used for the two-way binding.
|
||||
/// </summary>
|
||||
[Parameter] public override EventCallback<TItemValue> ValueChanged { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Used for the two-way binding.
|
||||
/// </summary>
|
||||
[Parameter] public EventCallback<IEnumerable<TItemValue>> ValuesChanged { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The custom suffix icon.
|
||||
/// </summary>
|
||||
[Parameter] public RenderFragment SuffixIcon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The custom prefix icon.
|
||||
/// </summary>
|
||||
@ -136,6 +150,7 @@ namespace AntDesign
|
||||
|
||||
protected IEnumerable<TItemValue> _defaultValues;
|
||||
protected bool _defaultValuesHasItems;
|
||||
|
||||
/// <summary>
|
||||
/// Used when Mode = multiple | tags - The values are used during initialization and when pressing the Reset button within Forms.
|
||||
/// </summary>
|
||||
@ -177,6 +192,7 @@ namespace AntDesign
|
||||
|
||||
internal HashSet<SelectOptionItem<TItemValue, TItem>> SelectOptionItems { get; } = new();
|
||||
internal List<SelectOptionItem<TItemValue, TItem>> SelectedOptionItems { get; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Called when the selected item changes.
|
||||
/// </summary>
|
||||
@ -187,8 +203,9 @@ namespace AntDesign
|
||||
/// </summary>
|
||||
[Parameter] public EventCallback<IEnumerable<TItem>> OnSelectedItemsChanged { get; set; }
|
||||
|
||||
internal virtual SelectMode SelectMode => Mode.ToSelectMode();
|
||||
[Parameter] public string Status { get; set; }
|
||||
|
||||
internal virtual SelectMode SelectMode => Mode.ToSelectMode();
|
||||
|
||||
/// <summary>
|
||||
/// Currently active (highlighted) option.
|
||||
@ -263,7 +280,6 @@ namespace AntDesign
|
||||
public Func<string, TItemValue> CustomTagLabelToValue { get; set; } =
|
||||
label => (TItemValue)TypeDescriptor.GetConverter(typeof(TItemValue)).ConvertFromInvariantString(label);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Determines if SelectOptions has any selected items
|
||||
/// </summary>
|
||||
@ -351,7 +367,7 @@ namespace AntDesign
|
||||
[Parameter] public int MaxTagTextLength { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether to embed label in value, turn the format of value from TItemValue to string (JSON)
|
||||
/// Whether to embed label in value, turn the format of value from TItemValue to string (JSON)
|
||||
/// e.g. { "value": TItemValue, "label": "Label value" }
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
@ -383,6 +399,7 @@ namespace AntDesign
|
||||
|
||||
private bool _hasValueOnClear;
|
||||
private TItemValue _valueOnClear;
|
||||
|
||||
/// <summary>
|
||||
/// When Clear button is pressed, Value will be set to
|
||||
/// whatever is set in ValueOnClear
|
||||
@ -404,14 +421,12 @@ namespace AntDesign
|
||||
/// <returns>true if SelectOptions has no values and the searchValue is empty; otherwise false </returns>
|
||||
protected bool ShowPlaceholder => !HasValue && string.IsNullOrEmpty(_searchValue);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The Method is called every time if the value of the @bind-Values was changed by the two-way binding.
|
||||
/// </summary>
|
||||
protected async Task OnValuesChangeAsync(IEnumerable<TItemValue> values)
|
||||
{
|
||||
if (
|
||||
!_isInitialized) // This is important because otherwise the initial value is overwritten by the EventCallback of ValueChanged and would be NULL.
|
||||
if (!_isInitialized) // This is important because otherwise the initial value is overwritten by the EventCallback of ValueChanged and would be NULL.
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -670,7 +685,6 @@ namespace AntDesign
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The method is called every time if the user select/de-select a item by mouse or keyboard.
|
||||
/// Don't change the IsSelected property outside of this function.
|
||||
@ -827,7 +841,6 @@ namespace AntDesign
|
||||
_prevSearchValue = string.Empty;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Method is called via EventCallBack after the user clicked on the Clear icon inside the Input element.
|
||||
/// Set the IsSelected and IsHidden properties for all items to False. It updates the overlay position if
|
||||
@ -943,8 +956,6 @@ namespace AntDesign
|
||||
{
|
||||
Focused = true;
|
||||
|
||||
SetClassMap();
|
||||
|
||||
await FocusAsync(_inputRef);
|
||||
|
||||
await OnFocus.InvokeAsync(Focused);
|
||||
@ -962,7 +973,6 @@ namespace AntDesign
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal async Task OnArrowClick(MouseEventArgs args)
|
||||
{
|
||||
await _dropDown.OnClickDiv(args);
|
||||
@ -985,7 +995,6 @@ namespace AntDesign
|
||||
_ = ClearSelectedAsync();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Clears the selectValue(s) property and send the null(default) value back through the two-way binding.
|
||||
/// </summary>
|
||||
@ -1005,4 +1014,4 @@ namespace AntDesign
|
||||
|
||||
protected abstract void SetClassMap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,297 +2,306 @@
|
||||
@namespace AntDesign.Select.Internal
|
||||
@typeparam TItemValue
|
||||
@typeparam TItem
|
||||
@inherits AntDomComponentBase
|
||||
|
||||
@if (ParentSelect.SelectMode == SelectMode.Default)
|
||||
{
|
||||
<div class="@Prefix-selector" @ref="@Ref" style="@(ParentSelect.PrefixIcon is null?"":"padding-left: 4px;")">
|
||||
@if (ParentSelect.PrefixIcon != null)
|
||||
{
|
||||
<span class="@Prefix-prefix" unselectable="on" aria-hidden="true" style="user-select: none;display:flex;align-items: center;padding-right: 4px;">
|
||||
@ParentSelect.PrefixIcon
|
||||
</span>
|
||||
}
|
||||
<span class="@Prefix-selection-search" style="@_inputWidth">
|
||||
<input @ref="ParentSelect._inputRef"
|
||||
@oninput="@OnInputChange"
|
||||
@onkeyup="OnKeyUp"
|
||||
@onkeydown="OnKeyDown"
|
||||
@attributes=@AdditonalAttributes()
|
||||
@bind-value="@SearchValue"
|
||||
id="@(ParentSelect.Id)_list"
|
||||
type="search"
|
||||
readonly="@(!ParentSelect.IsSearchEnabled)"
|
||||
unselectable="@(ParentSelect.IsSearchEnabled ? false : "on")"
|
||||
role="combobox"
|
||||
class="@Prefix-selection-search-input"
|
||||
autocomplete="off"
|
||||
aria-owns="@(ParentSelect.Id)_list"
|
||||
aria-expanded="@IsOverlayShow"
|
||||
aria-autocomplete="list"
|
||||
aria-controls="@(ParentSelect.Id)_list"
|
||||
aria-haspopup="listbox"
|
||||
style="@_inputStyle"/>
|
||||
</span>
|
||||
@if (ShowPlaceholder)
|
||||
{
|
||||
<span class="@Prefix-selection-placeholder">@Placeholder</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
var selectedItem = ParentSelect.SelectedOptionItems.FirstOrDefault();
|
||||
if (string.IsNullOrEmpty(SearchValue) && selectedItem != null)
|
||||
{
|
||||
@if (ParentLabelTemplate != null)
|
||||
{
|
||||
<CascadingValue Value="this" Name="SelectContent">
|
||||
<CascadingValue Value="@selectedItem" Name="SelectOption">
|
||||
@ParentLabelTemplate(selectedItem.Item)
|
||||
</CascadingValue>
|
||||
</CascadingValue>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="@Prefix-selection-item">
|
||||
@selectedItem.Label
|
||||
</span>
|
||||
}
|
||||
}
|
||||
}
|
||||
</div>
|
||||
|
||||
@if (ParentSelect.SuffixIcon != null)
|
||||
<div class="@Prefix-selector" @ref="@Ref" style="@(ParentSelect.PrefixIcon is null?"":"padding-left: 4px;")">
|
||||
@if (ParentSelect.PrefixIcon != null)
|
||||
{
|
||||
<span class="ant-select-arrow" unselectable="on" aria-hidden="true" style="user-select: none;" @onclick="@ParentSelect.OnArrowClick" @onclick:stopPropagation="true">
|
||||
@ParentSelect.SuffixIcon
|
||||
</span>
|
||||
<span class="@Prefix-prefix" unselectable="on" aria-hidden="true" style="user-select: none;display:flex;align-items: center;padding-right: 4px;">
|
||||
@ParentSelect.PrefixIcon
|
||||
</span>
|
||||
}
|
||||
else if (ParentSelect.Loading)
|
||||
<span class="@Prefix-selection-search" style="@_inputWidth">
|
||||
<input @ref="ParentSelect._inputRef"
|
||||
@oninput="@OnInputChange"
|
||||
@onkeyup="OnKeyUp"
|
||||
@onkeydown="OnKeyDown"
|
||||
@attributes=@AdditonalAttributes()
|
||||
@bind-value="@SearchValue"
|
||||
id="@(ParentSelect.Id)_list"
|
||||
type="search"
|
||||
readonly="@(!ParentSelect.IsSearchEnabled)"
|
||||
unselectable="@(ParentSelect.IsSearchEnabled ? false : "on")"
|
||||
role="combobox"
|
||||
class="@Prefix-selection-search-input"
|
||||
autocomplete="off"
|
||||
aria-owns="@(ParentSelect.Id)_list"
|
||||
aria-expanded="@IsOverlayShow"
|
||||
aria-autocomplete="list"
|
||||
aria-controls="@(ParentSelect.Id)_list"
|
||||
aria-haspopup="listbox"
|
||||
style="@_inputStyle" />
|
||||
</span>
|
||||
@if (ShowPlaceholder)
|
||||
{
|
||||
<span class="ant-select-arrow ant-select-arrow-loading" unselectable="on" aria-hidden="true" style="user-select: none;">
|
||||
<Icon Type="loading"></Icon>
|
||||
</span>
|
||||
<span class="@Prefix-selection-placeholder">@Placeholder</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ShowArrowIcon)
|
||||
var selectedItem = ParentSelect.SelectedOptionItems.FirstOrDefault();
|
||||
if (string.IsNullOrEmpty(SearchValue) && selectedItem != null)
|
||||
{
|
||||
@if (ParentLabelTemplate != null)
|
||||
{
|
||||
<span class="ant-select-arrow" unselectable="on" aria-hidden="true" style="user-select: none;" @onclick="@ParentSelect.OnArrowClick" @onclick:stopPropagation="true">
|
||||
@if (ParentSelect.IsSearchEnabled && IsOverlayShow)
|
||||
{
|
||||
if (ShowSearchIcon)
|
||||
{
|
||||
<Icon Type="search"></Icon>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
<Icon Type="down"></Icon>
|
||||
}
|
||||
</span>
|
||||
<CascadingValue Value="this" Name="SelectContent">
|
||||
<CascadingValue Value="@selectedItem" Name="SelectOption">
|
||||
@ParentLabelTemplate(selectedItem.Item)
|
||||
</CascadingValue>
|
||||
</CascadingValue>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="ant-select-arrow" unselectable="on" aria-hidden="true" style="user-select: none;" @onclick="@ParentSelect.OnArrowClick" @onclick:stopPropagation="true">
|
||||
@if (ParentSelect.IsSearchEnabled && IsOverlayShow)
|
||||
{
|
||||
if (ShowSearchIcon)
|
||||
{
|
||||
<Icon Type="search"></Icon>
|
||||
}
|
||||
}
|
||||
</span>
|
||||
}
|
||||
|
||||
@if (!ParentSelect.Disabled && ParentSelect.AllowClear && ParentSelect.HasValue)
|
||||
{
|
||||
<span class="ant-select-clear" unselectable="on" aria-hidden="true" style="user-select: none;" @onclick="OnClearClick" @onclick:stopPropagation="true">
|
||||
<Icon Type="close-circle" Theme="fill"></Icon>
|
||||
</span>
|
||||
<span class="@Prefix-selection-item">
|
||||
@getLabel(selectedItem)
|
||||
</span>
|
||||
}
|
||||
}
|
||||
}
|
||||
</div>
|
||||
|
||||
@if (ParentSelect.SuffixIcon != null)
|
||||
{
|
||||
<span class="ant-select-arrow" unselectable="on" aria-hidden="true" style="user-select: none;" @onclick="@ParentSelect.OnArrowClick" @onclick:stopPropagation="true">
|
||||
@ParentSelect.SuffixIcon
|
||||
</span>
|
||||
}
|
||||
else if (ParentSelect.Loading)
|
||||
{
|
||||
<span class="ant-select-arrow ant-select-arrow-loading" unselectable="on" aria-hidden="true" style="user-select: none;">
|
||||
<Icon Type="loading"></Icon>
|
||||
</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ShowArrowIcon)
|
||||
{
|
||||
<span class="ant-select-arrow" unselectable="on" aria-hidden="true" style="user-select: none;" @onclick="@ParentSelect.OnArrowClick" @onclick:stopPropagation="true">
|
||||
@if (ParentSelect.IsSearchEnabled && IsOverlayShow)
|
||||
{
|
||||
if (ShowSearchIcon)
|
||||
{
|
||||
<Icon Type="search"></Icon>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
<Icon Type="down"></Icon>
|
||||
}
|
||||
</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="ant-select-arrow" unselectable="on" aria-hidden="true" style="user-select: none;" @onclick="@ParentSelect.OnArrowClick" @onclick:stopPropagation="true">
|
||||
@if (ParentSelect.IsSearchEnabled && IsOverlayShow)
|
||||
{
|
||||
if (ShowSearchIcon)
|
||||
{
|
||||
<Icon Type="search"></Icon>
|
||||
}
|
||||
}
|
||||
</span>
|
||||
}
|
||||
|
||||
@if (!ParentSelect.Disabled && ParentSelect.AllowClear && ParentSelect.HasValue)
|
||||
{
|
||||
<span class="ant-select-clear" unselectable="on" aria-hidden="true" style="user-select: none;" @onclick="OnClearClick" @onclick:stopPropagation="true">
|
||||
<Icon Type="close-circle" Theme="fill"></Icon>
|
||||
</span>
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else //ParentSelect.SelectMode != SelectMode.Default
|
||||
{
|
||||
<div class="@Prefix-selector" @ref="@Ref" style="@(ParentSelect.PrefixIcon is null?"":"padding-left: 4px;")" >
|
||||
<div class="@Prefix-selection-overflow" @ref="@_overflow">
|
||||
@if (ParentSelect.PrefixIcon != null)
|
||||
{
|
||||
<div class="@Prefix-selection-overflow-item" style="opacity: 1;order:-100;">
|
||||
<span @ref="@_prefixRef" class="@Prefix-prefix" unselectable="on" aria-hidden="true" style="user-select: none;display:flex;align-items: center;padding-right: 4px;min-height:28px;">
|
||||
@ParentSelect.PrefixIcon
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
@if (!ShowPlaceholder)
|
||||
{
|
||||
var selectedItems = ParentSelect.SelectedOptionItems;
|
||||
@if (ParentSelect.HasTagCount)
|
||||
{
|
||||
@for (int i = 0; i < Math.Min(ParentSelect.MaxTagCount.AsT0, selectedItems.Count); i++)
|
||||
{
|
||||
var selectedOption = selectedItems[i];
|
||||
<div class="@Prefix-selection-overflow-item" style="@OverflowStyle(i)">
|
||||
@if (ParentLabelTemplate != null)
|
||||
{
|
||||
<CascadingValue Value="this" Name="SelectContent">
|
||||
<CascadingValue Value="@selectedOption" Name="SelectOption">
|
||||
@ParentLabelTemplate(selectedOption.Item)
|
||||
</CascadingValue>
|
||||
</CascadingValue>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="@Prefix-selection-item">
|
||||
<span class="@Prefix-selection-item-content">@FormatLabel(selectedOption.Label)</span>
|
||||
<span unselectable="on" aria-hidden="true" style="user-select: none;" class="@Prefix-selection-item-remove"
|
||||
@onmousedown="(e)=> RemoveClicked(e, selectedOption)" onclick="event.stopPropagation()">
|
||||
<Icon Type="close"></Icon>
|
||||
</span>
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
@if (selectedItems.Count > ParentSelect.MaxTagCount.AsT0)
|
||||
{
|
||||
<div class="@Prefix-selection-overflow-item @Prefix-selection-overflow-item-rest" style="opacity: 1; order: @(selectedItems.Count-1);">
|
||||
@if (ParentMaxTagPlaceholerTemplate != null)
|
||||
{
|
||||
<CascadingValue Value="this" Name="SelectContent">
|
||||
@ParentMaxTagPlaceholerTemplate(selectedItems.Skip(ParentSelect.MaxTagCount.AsT0).Select(i => i.Item))
|
||||
</CascadingValue>
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
<span class="@Prefix-selection-item">
|
||||
<span class="@Prefix-selection-item-content">+ @(selectedItems.Count - ParentSelect.MaxTagCount.AsT0)@Ellipse</span>
|
||||
</span>
|
||||
|
||||
}
|
||||
</div>
|
||||
}
|
||||
}
|
||||
else if (ParentSelect.IsResponsive)
|
||||
{
|
||||
@for (int i = 0; i < selectedItems.Count; i++)
|
||||
{
|
||||
var selectedOption = selectedItems[i];
|
||||
<div class="@Prefix-selection-overflow-item" @key="@selectedOption.InternalId" @ref="@selectedOption.SelectedTagRef" style="@OverflowStyle(i)">
|
||||
@if (ParentLabelTemplate != null)
|
||||
{
|
||||
<CascadingValue Value="this" Name="SelectContent">
|
||||
<CascadingValue Value="@selectedOption" Name="SelectOption">
|
||||
@ParentLabelTemplate(selectedOption.Item)
|
||||
</CascadingValue>
|
||||
</CascadingValue>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="@Prefix-selection-item">
|
||||
<span class="@Prefix-selection-item-content">@FormatLabel(selectedOption.Label)</span>
|
||||
<span unselectable="on" aria-hidden="true" style="user-select: none;" class="@Prefix-selection-item-remove"
|
||||
@onmousedown="(e)=> RemoveClicked(e, selectedOption)" onclick="event.stopPropagation()">
|
||||
<Icon Type="close"></Icon>
|
||||
</span>
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
@if (selectedItems.Count > _calculatedMaxCount)
|
||||
{
|
||||
<div class="@Prefix-selection-overflow-item @Prefix-selection-overflow-item-rest" @key="@_internalId" @ref="@_aggregateTag" style="opacity 1; order: @(_calculatedMaxCount-1);">
|
||||
@if (ParentMaxTagPlaceholerTemplate != null)
|
||||
{
|
||||
<CascadingValue Value="this" Name="SelectContent">
|
||||
@ParentMaxTagPlaceholerTemplate(selectedItems.Skip(_calculatedMaxCount).Select(i => i.Item))
|
||||
</CascadingValue>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="@Prefix-selection-item">
|
||||
<span class="@Prefix-selection-item-content">+ @(selectedItems.Count-_calculatedMaxCount)@Ellipse</span>
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string firstAfterPrefix = $"max-width: {GetFirstItemMaxWidth()}%;";
|
||||
@foreach (var selectedOption in selectedItems)
|
||||
{
|
||||
<div class="@Prefix-selection-overflow-item" style="opacity: 1;@firstAfterPrefix">
|
||||
@if (ParentLabelTemplate != null)
|
||||
{
|
||||
<CascadingValue Value="this" Name="SelectContent">
|
||||
<CascadingValue Value="@selectedOption" Name="SelectOption">
|
||||
@ParentLabelTemplate(selectedOption.Item)
|
||||
</CascadingValue>
|
||||
</CascadingValue>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="@Prefix-selection-item">
|
||||
<span class="@Prefix-selection-item-content">@FormatLabel(selectedOption.Label)</span>
|
||||
<span unselectable="on" aria-hidden="true" style="user-select: none;" class="@Prefix-selection-item-remove"
|
||||
@onmousedown="(e)=> RemoveClicked(e, selectedOption)" onclick="event.stopPropagation()">
|
||||
<Icon Type="close"></Icon>
|
||||
</span>
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
firstAfterPrefix = "max-width: 98%;";
|
||||
}
|
||||
}
|
||||
}
|
||||
<div class="@Prefix-selection-overflow-item @Prefix-selection-overflow-item-suffix" style="opacity: 1; order: @(ParentSelect.IsResponsive?_calculatedMaxCount-1:ParentSelect.SelectedOptionItems.Count)">
|
||||
<div class="@Prefix-selection-search" style="@_inputWidth">
|
||||
<input @ref="ParentSelect._inputRef"
|
||||
@oninput="OnInputChange"
|
||||
@onkeyup="OnKeyUp"
|
||||
@onkeydown="OnKeyDown"
|
||||
@attributes=@AdditonalAttributes()
|
||||
@bind-value="@SearchValue"
|
||||
id="@ParentSelect.Id"
|
||||
type="search"
|
||||
readonly="@(!ParentSelect.IsSearchEnabled)"
|
||||
unselectable="@(ParentSelect.IsSearchEnabled ? false : "on")"
|
||||
role="combobox"
|
||||
class="@Prefix-selection-search-input"
|
||||
autocomplete="off"
|
||||
aria-owns="@(ParentSelect.Id)_list"
|
||||
aria-expanded="@IsOverlayShow"
|
||||
aria-autocomplete="list"
|
||||
aria-controls="@(ParentSelect.Id)_list"
|
||||
aria-haspopup="listbox"
|
||||
style="@_inputStyle"/>
|
||||
<span class="@Prefix-selection-search-mirror" aria-hidden="true"> </span>
|
||||
</div>
|
||||
</div>
|
||||
@if (ShowPlaceholder)
|
||||
{
|
||||
<span class="@Prefix-selection-placeholder" style="@(ParentSelect.PrefixIcon != null?"margin-left: 7px;":"")">@Placeholder</span>
|
||||
}
|
||||
{
|
||||
<div class="@Prefix-selector" @ref="@Ref" style="@(ParentSelect.PrefixIcon is null?"":"padding-left: 4px;")">
|
||||
<div class="@Prefix-selection-overflow" @ref="@_overflow">
|
||||
@if (ParentSelect.PrefixIcon != null)
|
||||
{
|
||||
<div class="@Prefix-selection-overflow-item" style="opacity: 1;order:-100;">
|
||||
<span @ref="@_prefixRef" class="@Prefix-prefix" unselectable="on" aria-hidden="true" style="user-select: none;display:flex;align-items: center;padding-right: 4px;min-height:28px;">
|
||||
@ParentSelect.PrefixIcon
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if (!ShowPlaceholder)
|
||||
{
|
||||
var selectedItems = ParentSelect.SelectedOptionItems;
|
||||
@if (ParentSelect.HasTagCount)
|
||||
{
|
||||
@for (int i = 0; i < Math.Min(ParentSelect.MaxTagCount.AsT0, selectedItems.Count); i++)
|
||||
{
|
||||
var selectedOption = selectedItems[i];
|
||||
<div class="@Prefix-selection-overflow-item" style="@OverflowStyle(i)">
|
||||
@if (ParentLabelTemplate != null)
|
||||
{
|
||||
<CascadingValue Value="this" Name="SelectContent">
|
||||
<CascadingValue Value="@selectedOption" Name="SelectOption">
|
||||
@ParentLabelTemplate(selectedOption.Item)
|
||||
</CascadingValue>
|
||||
</CascadingValue>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="@Prefix-selection-item">
|
||||
<span class="@Prefix-selection-item-content">@getTagLabel(this,selectedOption)</span>
|
||||
<span unselectable="on" aria-hidden="true" style="user-select: none;" class="@Prefix-selection-item-remove"
|
||||
@onmousedown="(e)=> RemoveClicked(e, selectedOption)" onclick="event.stopPropagation()">
|
||||
<Icon Type="close"></Icon>
|
||||
</span>
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
@if (selectedItems.Count > ParentSelect.MaxTagCount.AsT0)
|
||||
{
|
||||
<div class="@Prefix-selection-overflow-item @Prefix-selection-overflow-item-rest" style="opacity: 1; order: @(selectedItems.Count-1);">
|
||||
@if (ParentMaxTagPlaceholerTemplate != null)
|
||||
{
|
||||
<CascadingValue Value="this" Name="SelectContent">
|
||||
@ParentMaxTagPlaceholerTemplate(selectedItems.Skip(ParentSelect.MaxTagCount.AsT0).Select(i => i.Item))
|
||||
</CascadingValue>
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@if (ParentSelect.SuffixIcon != null)
|
||||
{
|
||||
<span @ref="@_suffixRef" class="ant-select-arrow" unselectable="on" aria-hidden="true" style="user-select: none;" @onclick="@ParentSelect.OnArrowClick" @onclick:stopPropagation="true">
|
||||
@ParentSelect.SuffixIcon
|
||||
</span>
|
||||
}
|
||||
else if (ParentSelect.Loading)
|
||||
{
|
||||
<span @ref="@_suffixRef" class="ant-select-arrow ant-select-arrow-loading" unselectable="on" aria-hidden="true" style="user-select: none;">
|
||||
<Icon Type="loading"></Icon>
|
||||
</span>
|
||||
}
|
||||
@if (!ParentSelect.Disabled && ParentSelect.AllowClear && ParentSelect.HasValue)
|
||||
{
|
||||
<span @ref="@_suffixRef" class="ant-select-clear" unselectable="on" aria-hidden="true" style="user-select: none;" @onclick="OnClearClickAsync" @onclick:stopPropagation="true">
|
||||
<Icon Type="close-circle" Theme="fill"></Icon>
|
||||
</span>
|
||||
}
|
||||
<span class="@Prefix-selection-item">
|
||||
<span class="@Prefix-selection-item-content">+ @(selectedItems.Count - ParentSelect.MaxTagCount.AsT0)@Ellipse</span>
|
||||
</span>
|
||||
|
||||
}
|
||||
</div>
|
||||
}
|
||||
}
|
||||
else if (ParentSelect.IsResponsive)
|
||||
{
|
||||
@for (int i = 0; i < selectedItems.Count; i++)
|
||||
{
|
||||
var selectedOption = selectedItems[i];
|
||||
<div class="@Prefix-selection-overflow-item" @key="@selectedOption.InternalId" @ref="@selectedOption.SelectedTagRef" style="@OverflowStyle(i)">
|
||||
@if (ParentLabelTemplate != null)
|
||||
{
|
||||
<CascadingValue Value="this" Name="SelectContent">
|
||||
<CascadingValue Value="@selectedOption" Name="SelectOption">
|
||||
@ParentLabelTemplate(selectedOption.Item)
|
||||
</CascadingValue>
|
||||
</CascadingValue>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="@Prefix-selection-item">
|
||||
<span class="@Prefix-selection-item-content">@getTagLabel(this,selectedOption)</span>
|
||||
<span unselectable="on" aria-hidden="true" style="user-select: none;" class="@Prefix-selection-item-remove"
|
||||
@onmousedown="(e)=> RemoveClicked(e, selectedOption)" onclick="event.stopPropagation()">
|
||||
<Icon Type="close"></Icon>
|
||||
</span>
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
@if (selectedItems.Count > _calculatedMaxCount)
|
||||
{
|
||||
<div class="@Prefix-selection-overflow-item @Prefix-selection-overflow-item-rest" @key="@_internalId" @ref="@_aggregateTag" style="opacity 1; order: @(_calculatedMaxCount-1);">
|
||||
@if (ParentMaxTagPlaceholerTemplate != null)
|
||||
{
|
||||
<CascadingValue Value="this" Name="SelectContent">
|
||||
@ParentMaxTagPlaceholerTemplate(selectedItems.Skip(_calculatedMaxCount).Select(i => i.Item))
|
||||
</CascadingValue>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="@Prefix-selection-item">
|
||||
<span class="@Prefix-selection-item-content">+ @(selectedItems.Count-_calculatedMaxCount)@Ellipse</span>
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string firstAfterPrefix = $"max-width: {GetFirstItemMaxWidth()}%;";
|
||||
@foreach (var selectedOption in selectedItems)
|
||||
{
|
||||
<div class="@Prefix-selection-overflow-item" style="opacity: 1;@firstAfterPrefix">
|
||||
@if (ParentLabelTemplate != null)
|
||||
{
|
||||
<CascadingValue Value="this" Name="SelectContent">
|
||||
<CascadingValue Value="@selectedOption" Name="SelectOption">
|
||||
@ParentLabelTemplate(selectedOption.Item)
|
||||
</CascadingValue>
|
||||
</CascadingValue>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="@Prefix-selection-item">
|
||||
<span class="@Prefix-selection-item-content">@getTagLabel(this,selectedOption)</span>
|
||||
<span unselectable="on" aria-hidden="true" style="user-select: none;" class="@Prefix-selection-item-remove"
|
||||
@onmousedown="(e)=> RemoveClicked(e, selectedOption)" onclick="event.stopPropagation()">
|
||||
<Icon Type="close"></Icon>
|
||||
</span>
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
firstAfterPrefix = "max-width: 98%;";
|
||||
}
|
||||
}
|
||||
}
|
||||
<div class="@Prefix-selection-overflow-item @Prefix-selection-overflow-item-suffix" style="opacity: 1; order: @(ParentSelect.IsResponsive?_calculatedMaxCount-1:ParentSelect.SelectedOptionItems.Count)">
|
||||
<div class="@Prefix-selection-search" style="@_inputWidth">
|
||||
<input @ref="ParentSelect._inputRef"
|
||||
@oninput="OnInputChange"
|
||||
@onkeyup="OnKeyUp"
|
||||
@onkeydown="OnKeyDown"
|
||||
@attributes=@AdditonalAttributes()
|
||||
@bind-value="@SearchValue"
|
||||
id="@ParentSelect.Id"
|
||||
type="search"
|
||||
readonly="@(!ParentSelect.IsSearchEnabled)"
|
||||
unselectable="@(ParentSelect.IsSearchEnabled ? false : "on")"
|
||||
role="combobox"
|
||||
class="@Prefix-selection-search-input"
|
||||
autocomplete="off"
|
||||
aria-owns="@(ParentSelect.Id)_list"
|
||||
aria-expanded="@IsOverlayShow"
|
||||
aria-autocomplete="list"
|
||||
aria-controls="@(ParentSelect.Id)_list"
|
||||
aria-haspopup="listbox"
|
||||
style="@_inputStyle" />
|
||||
<span class="@Prefix-selection-search-mirror" aria-hidden="true"> </span>
|
||||
</div>
|
||||
</div>
|
||||
@if (ShowPlaceholder)
|
||||
{
|
||||
<span class="@Prefix-selection-placeholder" style="@(ParentSelect.PrefixIcon != null?"margin-left: 7px;":"")">@Placeholder</span>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (ParentSelect.SuffixIcon != null)
|
||||
{
|
||||
<span @ref="@_suffixRef" class="ant-select-arrow" unselectable="on" aria-hidden="true" style="user-select: none;" @onclick="@ParentSelect.OnArrowClick" @onclick:stopPropagation="true">
|
||||
@ParentSelect.SuffixIcon
|
||||
</span>
|
||||
}
|
||||
else if (ParentSelect.Loading)
|
||||
{
|
||||
<span @ref="@_suffixRef" class="ant-select-arrow ant-select-arrow-loading" unselectable="on" aria-hidden="true" style="user-select: none;">
|
||||
<Icon Type="loading"></Icon>
|
||||
</span>
|
||||
}
|
||||
@if (!ParentSelect.Disabled && ParentSelect.AllowClear && ParentSelect.HasValue)
|
||||
{
|
||||
<span @ref="@_suffixRef" class="ant-select-clear" unselectable="on" aria-hidden="true" style="user-select: none;" @onclick="OnClearClickAsync" @onclick:stopPropagation="true">
|
||||
<Icon Type="close-circle" Theme="fill"></Icon>
|
||||
</span>
|
||||
}
|
||||
}
|
||||
|
||||
@code {
|
||||
RenderFragment getLabel(SelectOptionItem<TItemValue, TItem> option) =>
|
||||
@<Template>@if (option.LabelTemplate != null)@option.LabelTemplate else @option.Label</Template>;
|
||||
|
||||
RenderFragment getTagLabel(SelectContent<TItemValue, TItem> content, SelectOptionItem<TItemValue, TItem> option)=>
|
||||
@<Template>@if (option.LabelTemplate != null) @option.LabelTemplate else @content.FormatLabel(option.Label)</Template>;
|
||||
}
|
@ -18,7 +18,7 @@ using Microsoft.JSInterop;
|
||||
|
||||
namespace AntDesign.Select.Internal
|
||||
{
|
||||
public partial class SelectContent<TItemValue, TItem> : IDisposable
|
||||
public partial class SelectContent<TItemValue, TItem> : AntDomComponentBase
|
||||
{
|
||||
[CascadingParameter(Name = "ParentSelect")] internal SelectBase<TItemValue, TItem> ParentSelect { get; set; }
|
||||
[CascadingParameter(Name = "ParentLabelTemplate")] internal RenderFragment<TItem> ParentLabelTemplate { get; set; }
|
||||
@ -64,21 +64,9 @@ namespace AntDesign.Select.Internal
|
||||
[Parameter] public EventCallback<MouseEventArgs> OnClearClick { get; set; }
|
||||
[Parameter] public EventCallback<SelectOptionItem<TItemValue, TItem>> OnRemoveSelected { get; set; }
|
||||
[Parameter] public string SearchValue { get; set; }
|
||||
[Parameter] public ForwardRef RefBack { get; set; } = new ForwardRef();
|
||||
[Parameter] public int SearchDebounceMilliseconds { get; set; }
|
||||
[Inject] protected IJSRuntime Js { get; set; }
|
||||
[Inject] private IDomEventListener DomEventListener { get; set; }
|
||||
|
||||
protected ElementReference Ref
|
||||
{
|
||||
get { return _ref; }
|
||||
set
|
||||
{
|
||||
_ref = value;
|
||||
RefBack?.Set(value);
|
||||
}
|
||||
}
|
||||
|
||||
private const char Ellipse = (char)0x2026;
|
||||
private const int ItemMargin = 4; //taken from each tag item
|
||||
private string _inputStyle = string.Empty;
|
||||
@ -450,9 +438,7 @@ namespace AntDesign.Select.Internal
|
||||
//TODO: Use built in @onblur once https://github.com/dotnet/aspnetcore/issues/30070 is solved
|
||||
private async void OnBlurInternal(JsonElement e) => await OnBlur.InvokeAsync(new());
|
||||
|
||||
public bool IsDisposed { get; private set; }
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (!_isReloading)
|
||||
{
|
||||
@ -466,22 +452,6 @@ namespace AntDesign.Select.Internal
|
||||
});
|
||||
}
|
||||
DomEventListener?.Dispose();
|
||||
|
||||
if (IsDisposed) return;
|
||||
|
||||
IsDisposed = true;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~SelectContent()
|
||||
{
|
||||
// Finalizer calls Dispose(false)
|
||||
Dispose(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ namespace AntDesign.Select.Internal
|
||||
public Guid InternalId { get; set; } = Guid.NewGuid();
|
||||
|
||||
private TItemValue _value;
|
||||
|
||||
public TItemValue Value
|
||||
{
|
||||
get => _value;
|
||||
@ -38,6 +39,7 @@ namespace AntDesign.Select.Internal
|
||||
}
|
||||
|
||||
private TItem _item;
|
||||
|
||||
public TItem Item
|
||||
{
|
||||
get => _item;
|
||||
@ -74,6 +76,8 @@ namespace AntDesign.Select.Internal
|
||||
}
|
||||
}
|
||||
|
||||
public RenderFragment LabelTemplate { get; set; }
|
||||
|
||||
private string _groupName = string.Empty;
|
||||
|
||||
public string GroupName
|
||||
@ -102,6 +106,7 @@ namespace AntDesign.Select.Internal
|
||||
}
|
||||
|
||||
private bool _isSelected;
|
||||
|
||||
public bool IsSelected
|
||||
{
|
||||
get => _isSelected;
|
||||
@ -118,6 +123,7 @@ namespace AntDesign.Select.Internal
|
||||
}
|
||||
|
||||
private bool _isActive;
|
||||
|
||||
public bool IsActive
|
||||
{
|
||||
get => _isActive;
|
||||
@ -134,6 +140,7 @@ namespace AntDesign.Select.Internal
|
||||
}
|
||||
|
||||
private bool _isDisabled;
|
||||
|
||||
public bool IsDisabled
|
||||
{
|
||||
get => _isDisabled;
|
||||
@ -150,6 +157,7 @@ namespace AntDesign.Select.Internal
|
||||
}
|
||||
|
||||
private bool _isHidden;
|
||||
|
||||
public bool IsHidden
|
||||
{
|
||||
get => _isHidden;
|
||||
@ -165,7 +173,6 @@ namespace AntDesign.Select.Internal
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public bool IsAddedTag { get; set; }
|
||||
|
||||
private SelectOption<TItemValue, TItem> _childComponent;
|
||||
|
@ -10,26 +10,50 @@ namespace AntDesign
|
||||
[Parameter]
|
||||
public string Format { get; set; } = "hh:mm:ss";
|
||||
|
||||
public override DateTime Value
|
||||
{
|
||||
get
|
||||
{
|
||||
return base.Value;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (base.Value != value)
|
||||
{
|
||||
base.Value = value;
|
||||
Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Parameter]
|
||||
public EventCallback OnFinish { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public int RefreshInterval { get; set; } = REFRESH_INTERVAL;
|
||||
|
||||
private Timer _timer;
|
||||
|
||||
private const int REFRESH_INTERVAL = 1000 / 30;
|
||||
private const int REFRESH_INTERVAL = 1000 / 10;
|
||||
|
||||
private TimeSpan _countDown = TimeSpan.Zero;
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
base.OnInitialized();
|
||||
|
||||
SetTimer();
|
||||
}
|
||||
|
||||
private void SetTimer()
|
||||
{
|
||||
_countDown = Value - DateTime.Now;
|
||||
_timer = new Timer(StartCountDownForTimeSpan);
|
||||
_timer.Change(0, REFRESH_INTERVAL);
|
||||
_timer.Change(0, RefreshInterval);
|
||||
}
|
||||
|
||||
private void StartCountDownForTimeSpan(object o)
|
||||
{
|
||||
_countDown = Value - DateTime.Now;
|
||||
_countDown = _countDown.Add(TimeSpan.FromMilliseconds(-RefreshInterval));
|
||||
if (_countDown.Ticks <= 0)
|
||||
{
|
||||
_countDown = TimeSpan.Zero;
|
||||
@ -39,8 +63,23 @@ namespace AntDesign
|
||||
InvokeAsync(() => OnFinish.InvokeAsync(o));
|
||||
}
|
||||
}
|
||||
|
||||
InvokeStateHasChanged();
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
//避免初始化时调用Reset
|
||||
if (_timer != null)
|
||||
{
|
||||
_timer.Dispose();
|
||||
SetTimer();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
_timer?.Dispose();
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -32,7 +32,7 @@ namespace AntDesign
|
||||
/// <summary>
|
||||
/// 数值内容
|
||||
/// </summary>
|
||||
[Parameter] public T Value { get; set; }
|
||||
[Parameter] public virtual T Value { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设置数值的样式
|
||||
|
@ -48,7 +48,12 @@ namespace AntDesign
|
||||
if (_pending.Value != value.Value)
|
||||
{
|
||||
_pending = value;
|
||||
|
||||
if (value.Value == null)
|
||||
{
|
||||
_pendingItem = null;
|
||||
SetItems();
|
||||
return;
|
||||
}
|
||||
_pendingItem = _pending.Value == null ? null : new TimelineItem()
|
||||
{
|
||||
Class = "ant-timeline-item-pending"
|
||||
|
@ -13,7 +13,7 @@
|
||||
@onfocusin="OnTriggerFocusIn"
|
||||
@onfocusout="OnTriggerFocusOut"
|
||||
@oncontextmenu:preventDefault
|
||||
tabindex="0">
|
||||
tabindex="@TabIndex">
|
||||
@ChildContent
|
||||
</div>
|
||||
}
|
||||
|
@ -20,6 +20,9 @@ namespace AntDesign
|
||||
[Parameter]
|
||||
public double MouseLeaveDelay { get; set; } = 0.1;
|
||||
|
||||
[Parameter]
|
||||
public int TabIndex { get; set; } = 0;
|
||||
|
||||
public Tooltip()
|
||||
{
|
||||
PrefixCls = "ant-tooltip";
|
||||
|
@ -1,45 +0,0 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace AntDesign
|
||||
{
|
||||
public class SimpleTreeSelect<TItem> : TreeSelect<TItem> where TItem : class
|
||||
{
|
||||
|
||||
|
||||
protected IEnumerable<TItem> RootData => ChildrenMethodExpression?.Invoke(DataSource, RootValue);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Specifies a method to return a child node
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public Func<IEnumerable<TItem>, string, IList<TItem>> ChildrenMethodExpression { get; set; }
|
||||
|
||||
protected override Func<TreeNode<TItem>, IList<TItem>> TreeNodeChildrenExpression => node => ChildrenMethodExpression(DataSource, TreeNodeKeyExpression(node));
|
||||
|
||||
|
||||
protected override Dictionary<string, object> TreeAttributes
|
||||
{
|
||||
get
|
||||
{
|
||||
return new()
|
||||
{
|
||||
{ "DataSource", RootData },
|
||||
{ "TitleExpression", TreeNodeTitleExpression },
|
||||
{ "DefaultExpandAll", TreeDefaultExpandAll },
|
||||
{ "KeyExpression", TreeNodeKeyExpression },
|
||||
{ "ChildrenExpression", TreeNodeChildrenExpression },
|
||||
{ "DisabledExpression", TreeNodeDisabledExpression },
|
||||
{ "IsLeafExpression", TreeNodeIsLeafExpression }
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -6,73 +6,88 @@
|
||||
@using AntDesign.Select.Internal
|
||||
|
||||
<CascadingValue Value="this" IsFixed>
|
||||
<CascadingValue Value=@("ant-select-dropdown") Name="PrefixCls" IsFixed>
|
||||
<div class="@ClassMapper.Class" style="@Style" id="@Id" tabindex="-1" @ref="Ref">
|
||||
<OverlayTrigger @ref="@_dropDown"
|
||||
Visible="Open"
|
||||
Disabled="Disabled"
|
||||
Trigger="new[] { Trigger.Click }"
|
||||
HiddenMode
|
||||
OnMouseEnter="@(() => { OnMouseEnter?.Invoke(); })"
|
||||
OnMouseLeave="@(() => { OnMouseLeave?.Invoke(); })"
|
||||
OnVisibleChange="@OnOverlayVisibleChangeAsync"
|
||||
PopupContainerSelector="@PopupContainerSelector"
|
||||
OverlayEnterCls="ant-slide-up-enter ant-slide-up-enter-active ant-slide-up"
|
||||
OverlayLeaveCls="ant-slide-up-leave ant-slide-up-leave-active ant-slide-up">
|
||||
<Overlay >
|
||||
<div style="@_dropdownStyle">
|
||||
<div class="" style="max-height: @PopupContainerMaxHeight; overflow-y: auto;">
|
||||
<div>
|
||||
<div class="" role="listbox" style="display: flex; flex-direction: column;">
|
||||
|
||||
<Tree TItem="TItem"
|
||||
BlockNode @ref="_tree" Multiple="Multiple"
|
||||
@attributes="TreeAttributes"
|
||||
SelectedKeys="SelectedKeys"
|
||||
OnClick="OnTreeNodeClick"
|
||||
OnUnSelect="OnTreeNodeUnSelect">
|
||||
<Nodes>
|
||||
@if (IsInnerModel)
|
||||
{
|
||||
<CascadingValue Name="Tree" Value="_tree" IsFixed="true">
|
||||
@ChildContent
|
||||
</CascadingValue>
|
||||
}
|
||||
</Nodes>
|
||||
|
||||
</Tree>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Overlay>
|
||||
<Unbound>
|
||||
<CascadingValue Value="this" Name=@("ParentSelect") IsFixed>
|
||||
<CascadingValue Value="@LabelTemplate" Name="ParentLabelTemplate">
|
||||
<CascadingValue Value="@ShowSearchIcon" Name="ShowSearchIcon">
|
||||
<CascadingValue Value="@ShowArrowIcon" Name="ShowArrowIcon">
|
||||
<SelectContent Prefix="ant-select"
|
||||
RefBack="@context"
|
||||
TItemValue="string"
|
||||
TItem="TItem"
|
||||
SearchValue="@_searchValue"
|
||||
SearchDebounceMilliseconds="@SearchDebounceMilliseconds"
|
||||
IsOverlayShow="@_dropDown.IsOverlayShow()"
|
||||
OnInput="@OnInputAsync"
|
||||
OnKeyUp="@OnKeyUpAsync"
|
||||
OnKeyDown="@OnKeyDownAsync"
|
||||
OnFocus="@OnInputFocusAsync"
|
||||
OnBlur="@OnInputBlurAsync"
|
||||
OnClearClick="@OnInputClearClickAsync"
|
||||
OnRemoveSelected="@OnRemoveSelectedAsync"
|
||||
Placeholder="@Placeholder"
|
||||
ShowPlaceholder="@ShowPlaceholder" />
|
||||
</CascadingValue>
|
||||
</CascadingValue>
|
||||
<CascadingValue Value=@("ant-select-dropdown") Name="PrefixCls" IsFixed>
|
||||
<div class="@ClassMapper.Class" style="@Style" id="@Id" tabindex="-1" @ref="Ref">
|
||||
<OverlayTrigger @ref="@_dropDown"
|
||||
Visible="Open"
|
||||
Disabled="Disabled"
|
||||
Trigger="new[] { Trigger.Click }"
|
||||
HiddenMode
|
||||
OnMouseEnter="@(() => { OnMouseEnter?.Invoke(); })"
|
||||
OnMouseLeave="@(() => { OnMouseLeave?.Invoke(); })"
|
||||
OnVisibleChange="@OnOverlayVisibleChangeAsync"
|
||||
PopupContainerSelector="@PopupContainerSelector"
|
||||
OverlayEnterCls="ant-slide-up-enter ant-slide-up-enter-active ant-slide-up"
|
||||
OverlayLeaveCls="ant-slide-up-leave ant-slide-up-leave-active ant-slide-up">
|
||||
<Overlay>
|
||||
<div style="@_dropdownStyle">
|
||||
<div class="" style="max-height: @PopupContainerMaxHeight; overflow-y: auto;">
|
||||
<div>
|
||||
<div class="" role="listbox" style="display: flex; flex-direction: column;">
|
||||
|
||||
<Tree @ref="_tree"
|
||||
TItem="TItem"
|
||||
BlockNode
|
||||
DataSource="DataSource"
|
||||
Multiple="Multiple"
|
||||
Selectable="!TreeCheckable"
|
||||
SelectedKeys="SelectedKeys"
|
||||
Checkable="TreeCheckable"
|
||||
OnClick="OnTreeNodeClick"
|
||||
OnUnselect="OnTreeNodeUnSelect"
|
||||
OnCheck="OnTreeCheck"
|
||||
ShowLeafIcon="ShowLeafIcon"
|
||||
ShowLine="ShowTreeLine"
|
||||
TitleExpression="TitleExpression"
|
||||
KeyExpression="KeyExpression"
|
||||
IconExpression="IconExpression"
|
||||
IsLeafExpression="IsLeafExpression"
|
||||
ChildrenExpression="ChildrenExpression"
|
||||
DisabledExpression="DisabledExpression"
|
||||
DefaultExpandAll="TreeDefaultExpandAll"
|
||||
>
|
||||
<Nodes>
|
||||
@if (IsTemplatedNodes)
|
||||
{
|
||||
<CascadingValue Name="Tree" Value="_tree" IsFixed="true">
|
||||
@ChildContent
|
||||
</CascadingValue>
|
||||
</CascadingValue>
|
||||
</Unbound>
|
||||
</OverlayTrigger>
|
||||
</div>
|
||||
</CascadingValue>
|
||||
}
|
||||
</Nodes>
|
||||
|
||||
</Tree>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Overlay>
|
||||
<Unbound>
|
||||
<CascadingValue Value="this" Name=@("ParentSelect") IsFixed>
|
||||
<CascadingValue Value="@LabelTemplate" Name="ParentLabelTemplate">
|
||||
<CascadingValue Value="@ShowSearchIcon" Name="ShowSearchIcon">
|
||||
<CascadingValue Value="@ShowArrowIcon" Name="ShowArrowIcon">
|
||||
<SelectContent Prefix="ant-select"
|
||||
RefBack="@context"
|
||||
TItemValue="string"
|
||||
TItem="TItem"
|
||||
SearchValue="@_searchValue"
|
||||
SearchDebounceMilliseconds="@SearchDebounceMilliseconds"
|
||||
IsOverlayShow="@_dropDown.IsOverlayShow()"
|
||||
OnInput="@OnInputAsync"
|
||||
OnKeyUp="@OnKeyUpAsync"
|
||||
OnKeyDown="@OnKeyDownAsync"
|
||||
OnFocus="@OnInputFocusAsync"
|
||||
OnBlur="@OnInputBlurAsync"
|
||||
OnClearClick="@OnInputClearClickAsync"
|
||||
OnRemoveSelected="@OnRemoveSelectedAsync"
|
||||
Placeholder="@Placeholder"
|
||||
ShowPlaceholder="@ShowPlaceholder" />
|
||||
</CascadingValue>
|
||||
</CascadingValue>
|
||||
</CascadingValue>
|
||||
</CascadingValue>
|
||||
</Unbound>
|
||||
</OverlayTrigger>
|
||||
</div>
|
||||
</CascadingValue>
|
||||
</CascadingValue>
|
@ -1,12 +1,13 @@
|
||||
using System;
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using AntDesign.Internal;
|
||||
using AntDesign.Select.Internal;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using AntDesign.Core.Helpers.MemberPath;
|
||||
using AntDesign.JsInterop;
|
||||
using OneOf;
|
||||
using System.Linq;
|
||||
@ -17,8 +18,6 @@ namespace AntDesign
|
||||
{
|
||||
[Parameter] public bool ShowExpand { get; set; } = true;
|
||||
|
||||
protected Tree<TItem> _tree;
|
||||
|
||||
[Parameter]
|
||||
public bool Multiple
|
||||
{
|
||||
@ -56,162 +55,87 @@ namespace AntDesign
|
||||
[Parameter] public bool TreeDefaultExpandAll { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public Func<IEnumerable<TItem>, string, TItem> DataItemExpression { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public Func<IList<TItem>, IEnumerable<string>, IEnumerable<TItem>> DataItemsExpression { get; set; }
|
||||
|
||||
[Parameter]
|
||||
|
||||
public string RootValue { get; set; } = "0";
|
||||
|
||||
protected Func<TreeNode<TItem>, string> TreeNodeTitleExpression
|
||||
{
|
||||
get
|
||||
{
|
||||
return node => TitleExpression(node.DataItem);
|
||||
}
|
||||
}
|
||||
[Parameter] public OneOf<bool, string> DropdownMatchSelectWidth { get; set; } = true;
|
||||
|
||||
[Parameter] public string DropdownMaxWidth { get; set; } = "auto";
|
||||
|
||||
[Parameter] public string PopupContainerMaxHeight { get; set; } = "256px";
|
||||
|
||||
//[Parameter] public IEnumerable<ITreeData<TItem>> TreeData { get; set; }
|
||||
|
||||
[Parameter] public string DropdownStyle { get; set; }
|
||||
|
||||
[Parameter] public bool ShowTreeLine { get; set; }
|
||||
|
||||
[Parameter] public bool ShowLeafIcon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies a method that returns the text of the node.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public Func<TItem, string> TitleExpression { get; set; }
|
||||
|
||||
|
||||
protected virtual Dictionary<string, object> TreeAttributes
|
||||
{
|
||||
get
|
||||
{
|
||||
return new()
|
||||
{
|
||||
{ "DataSource", DataSource },
|
||||
{ "TitleExpression", DataSource == null ? null : TreeNodeTitleExpression },
|
||||
{ "DefaultExpandAll", TreeDefaultExpandAll },
|
||||
{ "KeyExpression", DataSource == null ? null : TreeNodeKeyExpression },
|
||||
{ "ChildrenExpression", DataSource == null ? null : TreeNodeChildrenExpression },
|
||||
{ "DisabledExpression", DataSource == null ? null : TreeNodeDisabledExpression },
|
||||
{ "IsLeafExpression", DataSource == null ? null : TreeNodeIsLeafExpression }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected Func<TreeNode<TItem>, string> TreeNodeKeyExpression
|
||||
{
|
||||
get
|
||||
{
|
||||
return node => KeyExpression(node.DataItem);
|
||||
}
|
||||
}
|
||||
public Func<TreeNode<TItem>, string> TitleExpression { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies a method that returns the key of the node.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public Func<TItem, string> KeyExpression { get; set; }
|
||||
|
||||
|
||||
protected Func<TreeNode<TItem>, string> TreeNodeIconExpression
|
||||
{
|
||||
get
|
||||
{
|
||||
return node => IconExpression(node.DataItem);
|
||||
}
|
||||
}
|
||||
public Func<TreeNode<TItem>, string> KeyExpression { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies a method to return the node icon.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public Func<TItem, string> IconExpression { get; set; }
|
||||
|
||||
protected Func<TreeNode<TItem>, bool> TreeNodeIsLeafExpression
|
||||
{
|
||||
get
|
||||
{
|
||||
return node => IsLeafExpression(DataSource, node.DataItem);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private bool IsInnerModel => ChildContent != null;
|
||||
public Func<TreeNode<TItem>, string> IconExpression { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies a method that returns whether the expression is a leaf node.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public Func<IEnumerable<TItem>, TItem, bool> IsLeafExpression { get; set; }
|
||||
|
||||
|
||||
protected virtual Func<TreeNode<TItem>, IList<TItem>> TreeNodeChildrenExpression
|
||||
{
|
||||
get
|
||||
{
|
||||
return node => ChildrenExpression == null ? null : ChildrenExpression(node.DataItem);
|
||||
}
|
||||
}
|
||||
public Func<TreeNode<TItem>, bool> IsLeafExpression { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies a method to return a child node
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public virtual Func<TItem, IList<TItem>> ChildrenExpression { get; set; }
|
||||
|
||||
protected Func<TreeNode<TItem>, bool> TreeNodeDisabledExpression
|
||||
{
|
||||
get
|
||||
{
|
||||
return node => DisabledExpression != null && DisabledExpression(node.DataItem);
|
||||
}
|
||||
}
|
||||
|
||||
public Func<TreeNode<TItem>, IEnumerable<TItem>> ChildrenExpression { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies a method to return a disabled node
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public Func<TItem, bool> DisabledExpression { get; set; }
|
||||
|
||||
[Parameter] public OneOf<bool, string> DropdownMatchSelectWidth { get; set; } = true;
|
||||
[Parameter] public string DropdownMaxWidth { get; set; } = "auto";
|
||||
|
||||
[Parameter] public string PopupContainerMaxHeight { get; set; } = "256px";
|
||||
|
||||
|
||||
public Func<TreeNode<TItem>, bool> DisabledExpression { get; set; }
|
||||
|
||||
private bool IsMultiple => Multiple || TreeCheckable;
|
||||
|
||||
private bool IsTemplatedNodes => ChildContent != null;
|
||||
|
||||
internal override SelectMode SelectMode => IsMultiple ? SelectMode.Multiple : base.SelectMode;
|
||||
|
||||
private string[] SelectedKeys => Values?.ToArray();
|
||||
//private readonly IList<TreeNode<TItem>> _selectedNodes = new List<TreeNode<TItem>>();
|
||||
|
||||
private string _dropdownStyle = string.Empty;
|
||||
private bool _multiple;
|
||||
private readonly string _dir = "ltr";
|
||||
|
||||
|
||||
|
||||
private Tree<TItem> _tree;
|
||||
|
||||
public override string Value
|
||||
{
|
||||
get => base.Value;
|
||||
set
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
return;
|
||||
if (base.Value == value)
|
||||
return;
|
||||
|
||||
base.Value = value;
|
||||
|
||||
if (SelectOptionItems.Any(o => o.Value == value))
|
||||
if (value == null)
|
||||
{
|
||||
_ = SetValueAsync(SelectOptionItems.First(o => o.Value == value));
|
||||
}
|
||||
else
|
||||
{
|
||||
var data = DataItemExpression?.Invoke(DataSource, value);
|
||||
if (data != null)
|
||||
{
|
||||
var o = CreateOption(data, true);
|
||||
_ = SetValueAsync(o);
|
||||
}
|
||||
ClearOptions();
|
||||
}
|
||||
|
||||
|
||||
UpdateValueAndSelection();
|
||||
}
|
||||
}
|
||||
|
||||
@ -220,12 +144,6 @@ namespace AntDesign
|
||||
get => base.Values;
|
||||
set
|
||||
{
|
||||
if (!_isInitialized)
|
||||
return;
|
||||
|
||||
if (!Multiple)
|
||||
throw new NotImplementedException("not Multiple select, no die");
|
||||
|
||||
if (value != null && _selectedValues != null)
|
||||
{
|
||||
var hasChanged = !value.SequenceEqual(_selectedValues);
|
||||
@ -233,31 +151,24 @@ namespace AntDesign
|
||||
if (!hasChanged)
|
||||
return;
|
||||
|
||||
ClearOptions();
|
||||
|
||||
_selectedValues = value;
|
||||
CreateOptions(value);
|
||||
_ = OnValuesChangeAsync(value);
|
||||
}
|
||||
else if (value != null && _selectedValues == null)
|
||||
{
|
||||
_selectedValues = value;
|
||||
CreateOptions(value);
|
||||
_ = OnValuesChangeAsync(value);
|
||||
}
|
||||
else if (value == null && _selectedValues != null)
|
||||
{
|
||||
_selectedValues = default;
|
||||
|
||||
ClearOptions();
|
||||
|
||||
_ = OnValuesChangeAsync(default);
|
||||
}
|
||||
|
||||
UpdateValuesSelection();
|
||||
|
||||
if (_isNotifyFieldChanged && (Form?.ValidateOnChange == true))
|
||||
{
|
||||
EditContext?.NotifyFieldChanged(FieldIdentifier);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -265,41 +176,26 @@ namespace AntDesign
|
||||
{
|
||||
SelectOptionItems.Clear();
|
||||
SelectedOptionItems.Clear();
|
||||
_tree?._allNodes.ForEach(x => x.SetSelected(false));
|
||||
}
|
||||
|
||||
private void CreateOptions(IEnumerable<string> data)
|
||||
{
|
||||
if (IsInnerModel)
|
||||
if (IsTemplatedNodes)
|
||||
{
|
||||
var d1 = data.Where(d => !SelectOptionItems.Any(o => o.Value == d));
|
||||
CreateOptionsByTreeNode(d1);
|
||||
return;
|
||||
}
|
||||
|
||||
// 通过DataItemExpression来生成选中项
|
||||
if (DataItemExpression != null)
|
||||
data.ForEach(menuId =>
|
||||
{
|
||||
data.ForEach(menuId =>
|
||||
var d = _tree._allNodes.FirstOrDefault(m => m.Key == menuId);
|
||||
if (d != null)
|
||||
{
|
||||
var d = DataItemExpression?.Invoke(DataSource, menuId);
|
||||
if (d != null)
|
||||
{
|
||||
var o = CreateOption(d, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
// 通过目前的树节点,生成选中项,对于延时的节点,建议使用DataItemExpression来加载
|
||||
data.ForEach(menuId =>
|
||||
{
|
||||
var d = _tree._allNodes.FirstOrDefault(m => m.Key == menuId);
|
||||
if (d != null)
|
||||
{
|
||||
var o = CreateOption(d, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
var o = CreateOption(d, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void CreateOptionsByTreeNode(IEnumerable<string> data)
|
||||
@ -319,36 +215,30 @@ namespace AntDesign
|
||||
var o = new SelectOptionItem<string, TItem>()
|
||||
{
|
||||
Label = data.Title,
|
||||
LabelTemplate = data.TitleTemplate,
|
||||
Value = data.Key,
|
||||
Item = data.DataItem,
|
||||
IsAddedTag = SelectMode != SelectMode.Default
|
||||
IsAddedTag = SelectMode != SelectMode.Default,
|
||||
};
|
||||
if (append && !SelectOptionItems.Any(m => m.Value == o.Value))
|
||||
SelectOptionItems.Add(o);
|
||||
return o;
|
||||
}
|
||||
|
||||
private SelectOptionItem<string, TItem> CreateOption(TItem data, bool append = false)
|
||||
protected override Task OnFirstAfterRenderAsync()
|
||||
{
|
||||
var o = new SelectOptionItem<string, TItem>()
|
||||
if (Value != null)
|
||||
{
|
||||
Label = TitleExpression(data),
|
||||
Value = KeyExpression(data),
|
||||
Item = data,
|
||||
IsAddedTag = SelectMode != SelectMode.Default
|
||||
};
|
||||
if (append && !SelectOptionItems.Any(m => m.Value == o.Value))
|
||||
SelectOptionItems.Add(o);
|
||||
return o;
|
||||
}
|
||||
UpdateValueAndSelection();
|
||||
}
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
SelectOptions = "".ToRenderFragment();
|
||||
//_inputValue = Value;
|
||||
base.OnInitialized();
|
||||
}
|
||||
if (Values != null)
|
||||
{
|
||||
UpdateValuesSelection();
|
||||
}
|
||||
|
||||
return base.OnFirstAfterRenderAsync();
|
||||
}
|
||||
|
||||
private void OnKeyDownAsync(KeyboardEventArgs args)
|
||||
{
|
||||
@ -377,6 +267,7 @@ namespace AntDesign
|
||||
await SetDropdownStyleAsync();
|
||||
}
|
||||
}
|
||||
|
||||
protected async Task OnRemoveSelectedAsync(SelectOptionItem<string, TItem> selectOption)
|
||||
{
|
||||
if (selectOption == null) throw new ArgumentNullException(nameof(selectOption));
|
||||
@ -389,43 +280,56 @@ namespace AntDesign
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private async Task OnTreeNodeClick(TreeEventArgs<TItem> args)
|
||||
{
|
||||
if (!args.Node.Selected)
|
||||
var node = args.Node;
|
||||
|
||||
if (!TreeCheckable && !node.Selected)
|
||||
return;
|
||||
|
||||
var key = args.Node.Key;
|
||||
var key = node.Key;
|
||||
if (Value != null && Value.Equals(key))
|
||||
return;
|
||||
if (Values != null && Values.Contains(key))
|
||||
return;
|
||||
|
||||
var data = args.Node;
|
||||
SelectOptionItem<string, TItem> item;
|
||||
if (IsInnerModel)
|
||||
item = CreateOption(data, true);
|
||||
else
|
||||
item = CreateOption(data.DataItem, true);
|
||||
var option = CreateOption(node, true);
|
||||
|
||||
//_selectedNodes.Add(data);
|
||||
await SetValueAsync(option);
|
||||
|
||||
await SetValueAsync(item);
|
||||
if (!Multiple)
|
||||
{
|
||||
var unselectedNodes = _tree._allNodes.Where(x => x.Key != node.Key);
|
||||
unselectedNodes.ForEach(x => x.SetSelected(false));
|
||||
}
|
||||
|
||||
if (SelectMode == SelectMode.Default)
|
||||
{
|
||||
await CloseAsync();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void OnTreeNodeUnSelect(TreeEventArgs<TItem> args)
|
||||
protected async Task OnTreeNodeUnSelect(TreeEventArgs<TItem> args)
|
||||
{
|
||||
if (args == null) throw new ArgumentNullException(nameof(args));
|
||||
var key = args.Node.Key;
|
||||
var nodes = SelectOptionItems.Where(o => o.Value == key).ToArray();
|
||||
foreach (var item in nodes)
|
||||
// Prevent deselect in sigle selection mode
|
||||
if (!Multiple && args.Node.Key == Value)
|
||||
{
|
||||
_ = SetValueAsync(item);
|
||||
args.Node.SetSelected(true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Deselect in Multiple mode
|
||||
var node = SelectOptionItems.Where(o => o.Value == args.Node.Key).FirstOrDefault();
|
||||
if (node != null)
|
||||
{
|
||||
await SetValueAsync(node);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task OnTreeCheck(TreeEventArgs<TItem> args)
|
||||
{
|
||||
var option = CreateOption(args.Node, true);
|
||||
await SetValueAsync(option);
|
||||
}
|
||||
|
||||
protected async Task SetDropdownStyleAsync()
|
||||
@ -444,7 +348,7 @@ namespace AntDesign
|
||||
}
|
||||
if (!DropdownMaxWidth.Equals("auto", StringComparison.CurrentCultureIgnoreCase))
|
||||
maxWidth = $"max-width: {DropdownMaxWidth};";
|
||||
_dropdownStyle = minWidth + definedWidth + maxWidth;
|
||||
_dropdownStyle = minWidth + definedWidth + maxWidth + DropdownStyle ?? "";
|
||||
|
||||
if (Multiple)
|
||||
{
|
||||
@ -458,7 +362,6 @@ namespace AntDesign
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected override void SetClassMap()
|
||||
{
|
||||
var classPrefix = "ant-select";
|
||||
@ -466,17 +369,51 @@ namespace AntDesign
|
||||
.Add(classPrefix)
|
||||
.Add("ant-tree-select")
|
||||
.If("ant-select-lg", () => Size == "large")
|
||||
.If("ant-select-rtl", () => _dir == "rtl")
|
||||
.If("ant-select-sm", () => Size == "rtl")
|
||||
.If("ant-select-sm", () => Size == "small")
|
||||
.If("ant-select-rtl", () => RTL)
|
||||
.If("ant-select-disabled", () => Disabled)
|
||||
.If("ant-select-single", () => SelectMode == SelectMode.Default)
|
||||
.If($"ant-select-multiple", () => SelectMode != SelectMode.Default)
|
||||
.If("ant-select-multiple", () => SelectMode != SelectMode.Default)
|
||||
.If("ant-select-show-arrow", () => !IsMultiple)
|
||||
.If("ant-select-show-search", () => !IsMultiple)
|
||||
.If("ant-select-allow-clear", () => AllowClear)
|
||||
.If("ant-select-open", () => Open)
|
||||
.If("ant-select-focused", () => Open || Focused)
|
||||
.If("ant-select-status-error", () => Status == "error")
|
||||
.If("ant-select-status-warning", () => Status == "warning")
|
||||
;
|
||||
}
|
||||
|
||||
private void UpdateValueAndSelection()
|
||||
{
|
||||
if (SelectOptionItems.Any(o => o.Value == Value))
|
||||
{
|
||||
_ = SetValueAsync(SelectOptionItems.First(o => o.Value == Value));
|
||||
}
|
||||
else
|
||||
{
|
||||
var data = _tree?._allNodes.FirstOrDefault(x => x.Key == Value);
|
||||
if (data != null)
|
||||
{
|
||||
var o = CreateOption(data, true);
|
||||
_ = SetValueAsync(o);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateValuesSelection()
|
||||
{
|
||||
if (_tree == null)
|
||||
return;
|
||||
|
||||
if (_selectedValues?.Any() != true)
|
||||
{
|
||||
ClearOptions();
|
||||
return;
|
||||
}
|
||||
|
||||
CreateOptions(_selectedValues);
|
||||
_ = OnValuesChangeAsync(_selectedValues);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
21
components/tree/ITreeData.cs
Normal file
21
components/tree/ITreeData.cs
Normal file
@ -0,0 +1,21 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace AntDesign
|
||||
{
|
||||
public interface ITreeData<TItem>
|
||||
{
|
||||
public string Key { get; set; }
|
||||
|
||||
public string Title { get; set; }
|
||||
|
||||
public TItem Value { get; }
|
||||
|
||||
public IEnumerable<TItem> Children { get; set; }
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
@ -94,7 +94,7 @@ namespace AntDesign
|
||||
private bool _hasSetShowLeafIcon;
|
||||
|
||||
/// <summary>
|
||||
/// Specific the Icon type of switcher
|
||||
/// Specific the Icon type of switcher
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string SwitcherIcon { get; set; }
|
||||
@ -190,9 +190,9 @@ namespace AntDesign
|
||||
if (SelectedNodesDictionary.ContainsKey(treeNode.NodeId) == true)
|
||||
SelectedNodesDictionary.Remove(treeNode.NodeId);
|
||||
|
||||
if (OnUnSelect.HasDelegate)
|
||||
if (OnUnselect.HasDelegate)
|
||||
{
|
||||
OnUnSelect.InvokeAsync(new TreeEventArgs<TItem>(this, treeNode));
|
||||
OnUnselect.InvokeAsync(new TreeEventArgs<TItem>(this, treeNode));
|
||||
}
|
||||
}
|
||||
|
||||
@ -355,6 +355,14 @@ namespace AntDesign
|
||||
}
|
||||
}
|
||||
|
||||
public void SelectAll()
|
||||
{
|
||||
foreach (var item in ChildNodes)
|
||||
{
|
||||
item.SetSelected(true);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the keys of the default checked treeNodes
|
||||
/// </summary>
|
||||
@ -377,6 +385,7 @@ namespace AntDesign
|
||||
_checkedNodes.TryAdd(treeNode.NodeId, treeNode);
|
||||
else
|
||||
_checkedNodes.TryRemove(treeNode.NodeId, out TreeNode<TItem> _);
|
||||
|
||||
_checkedKeys = _checkedNodes.Select(x => x.Value.Key).ToArray();
|
||||
|
||||
if (!old.SequenceEqual(_checkedKeys) && CheckedKeysChanged.HasDelegate)
|
||||
@ -419,12 +428,6 @@ namespace AntDesign
|
||||
|
||||
private void SearchNodes()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(_searchValue))
|
||||
{
|
||||
_allNodes.ForEach(m => { m.Expand(true); m.Matched = false; });
|
||||
return;
|
||||
}
|
||||
|
||||
var allList = _allNodes.ToList();
|
||||
List<TreeNode<TItem>> searchDatas = null, exceptList = null;
|
||||
|
||||
@ -489,7 +492,7 @@ namespace AntDesign
|
||||
/// Specifies a method to return a child node
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public Func<TreeNode<TItem>, IList<TItem>> ChildrenExpression { get; set; }
|
||||
public Func<TreeNode<TItem>, IEnumerable<TItem>> ChildrenExpression { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies a method to return a disabled node
|
||||
@ -536,7 +539,7 @@ namespace AntDesign
|
||||
public EventCallback<TreeEventArgs<TItem>> OnSelect { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<TreeEventArgs<TItem>> OnUnSelect { get; set; }
|
||||
public EventCallback<TreeEventArgs<TItem>> OnUnselect { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Click the expansion tree node icon to call back
|
||||
@ -620,6 +623,33 @@ namespace AntDesign
|
||||
base.OnInitialized();
|
||||
}
|
||||
|
||||
protected override Task OnFirstAfterRenderAsync()
|
||||
{
|
||||
this.DefaultCheckedKeys?.ForEach(k =>
|
||||
{
|
||||
var node = this._allNodes.FirstOrDefault(x => x.Key == k);
|
||||
if (node != null)
|
||||
node.SetCheckedDefault(true);
|
||||
});
|
||||
|
||||
this.DefaultSelectedKeys?.ForEach(k =>
|
||||
{
|
||||
var node = this._allNodes.FirstOrDefault(x => x.Key == k);
|
||||
if (node != null)
|
||||
node.SetSelected(true);
|
||||
});
|
||||
if (!this.DefaultExpandAll)
|
||||
{
|
||||
this.DefaultExpandedKeys?.ForEach(k =>
|
||||
{
|
||||
var node = this._allNodes.FirstOrDefault(x => x.Key == k);
|
||||
if (node != null)
|
||||
node.OpenPropagation();
|
||||
});
|
||||
}
|
||||
return base.OnFirstAfterRenderAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find Node
|
||||
/// </summary>
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
@ -50,7 +50,7 @@ namespace AntDesign
|
||||
public int TreeLevel => (ParentNode?.TreeLevel ?? -1) + 1;
|
||||
|
||||
/// <summary>
|
||||
/// record the index in children nodes list of parent node.
|
||||
/// record the index in children nodes list of parent node.
|
||||
/// </summary>
|
||||
internal int NodeIndex { get; set; }
|
||||
|
||||
@ -157,7 +157,7 @@ namespace AntDesign
|
||||
_key = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private bool _disabled;
|
||||
|
||||
/// <summary>
|
||||
@ -193,11 +193,7 @@ namespace AntDesign
|
||||
public void SetSelected(bool value)
|
||||
{
|
||||
if (Disabled) return;
|
||||
if (!TreeComponent.Selectable && TreeComponent.Checkable)
|
||||
{
|
||||
SetChecked(!Checked);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_selected == value) return;
|
||||
_selected = value;
|
||||
if (value == true)
|
||||
@ -397,12 +393,11 @@ namespace AntDesign
|
||||
|
||||
#region Checkbox
|
||||
|
||||
private bool _checked;
|
||||
/// <summary>
|
||||
/// According to check the
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool Checked { get; set; }
|
||||
public bool Checked { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public bool Indeterminate { get; set; }
|
||||
@ -460,6 +455,24 @@ namespace AntDesign
|
||||
TreeComponent.AddOrRemoveCheckNode(this);
|
||||
StateHasChanged();
|
||||
}
|
||||
/// <summary>
|
||||
/// Set the checkbox state when ini
|
||||
/// </summary>
|
||||
/// <param name="check"></param>
|
||||
public void SetCheckedDefault(bool check)
|
||||
{
|
||||
if (TreeComponent.CheckStrictly)
|
||||
{
|
||||
this.Checked = check;
|
||||
}
|
||||
else
|
||||
{
|
||||
SetChildCheckedDefault(this, check);
|
||||
if (ParentNode != null)
|
||||
ParentNode.UpdateCheckStateDefault();
|
||||
}
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the checkbox status of child nodes
|
||||
@ -476,6 +489,20 @@ namespace AntDesign
|
||||
foreach (var child in subnode.ChildNodes)
|
||||
child?.SetChildChecked(child, check);
|
||||
}
|
||||
/// <summary>
|
||||
/// Sets the checkbox status of child nodes whern bind default
|
||||
/// </summary>
|
||||
/// <param name="subnode"></param>
|
||||
/// <param name="check"></param>
|
||||
private void SetChildCheckedDefault(TreeNode<TItem> subnode, bool check)
|
||||
{
|
||||
this.Checked = check;
|
||||
this.Indeterminate = false;
|
||||
TreeComponent.AddOrRemoveCheckNode(this);
|
||||
if (subnode.HasChildNodes)
|
||||
foreach (var child in subnode.ChildNodes)
|
||||
child?.SetChildCheckedDefault(child, check);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update check status
|
||||
@ -540,6 +567,66 @@ namespace AntDesign
|
||||
if (ParentNode == null)
|
||||
StateHasChanged();
|
||||
}
|
||||
/// <summary>
|
||||
/// Update check status when bind default
|
||||
/// </summary>
|
||||
/// <param name="halfChecked"></param>
|
||||
private void UpdateCheckStateDefault(bool? halfChecked = null)
|
||||
{
|
||||
if (halfChecked == true)
|
||||
{
|
||||
//If the child node is indeterminate, the parent node must is indeterminate.
|
||||
this.Checked = false;
|
||||
this.Indeterminate = true;
|
||||
}
|
||||
else if (HasChildNodes == true && !DisableCheckbox)
|
||||
{
|
||||
//Determines the selection status of the current node
|
||||
bool hasChecked = false;
|
||||
bool hasUnchecked = false;
|
||||
|
||||
foreach (var item in ChildNodes)
|
||||
{
|
||||
if (item.Indeterminate)
|
||||
{
|
||||
hasChecked = true;
|
||||
hasUnchecked = true;
|
||||
break;
|
||||
}
|
||||
else if (item.Checked)
|
||||
{
|
||||
hasChecked = true;
|
||||
}
|
||||
else if (!item.Checked)
|
||||
{
|
||||
hasUnchecked = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasChecked && !hasUnchecked)
|
||||
{
|
||||
this.Checked = true;
|
||||
this.Indeterminate = false;
|
||||
}
|
||||
else if (!hasChecked && hasUnchecked)
|
||||
{
|
||||
this.Checked = false;
|
||||
this.Indeterminate = false;
|
||||
}
|
||||
else if (hasChecked && hasUnchecked)
|
||||
{
|
||||
this.Checked = false;
|
||||
this.Indeterminate = true;
|
||||
}
|
||||
}
|
||||
TreeComponent.AddOrRemoveCheckNode(this);
|
||||
|
||||
if (ParentNode != null)
|
||||
ParentNode.UpdateCheckStateDefault(this.Indeterminate);
|
||||
|
||||
if (ParentNode == null)
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
#endregion Checkbox
|
||||
|
||||
@ -621,7 +708,7 @@ namespace AntDesign
|
||||
get
|
||||
{
|
||||
if (TreeComponent.ChildrenExpression != null)
|
||||
return TreeComponent.ChildrenExpression(this) ?? new List<TItem>();
|
||||
return TreeComponent.ChildrenExpression(this)?.ToList() ?? new List<TItem>();
|
||||
else
|
||||
return new List<TItem>();
|
||||
}
|
||||
@ -789,8 +876,6 @@ namespace AntDesign
|
||||
|
||||
#endregion Node data operation
|
||||
|
||||
bool _defaultBinding;
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
SetTreeNodeClassMapper();
|
||||
@ -817,73 +902,22 @@ namespace AntDesign
|
||||
if (TreeComponent.Selectable && TreeComponent.SelectedKeys != null)
|
||||
{
|
||||
this.Selected = TreeComponent.SelectedKeys.Any(k => k == this.Key);
|
||||
this.SetChecked(this.Selected);
|
||||
}
|
||||
|
||||
if (TreeComponent.Selectable && TreeComponent.SelectedKeys != null)
|
||||
{
|
||||
this.Selected = TreeComponent.SelectedKeys.Any(k => k == this.Key);
|
||||
}
|
||||
|
||||
if (this.Checked)
|
||||
this.SetChecked(true);
|
||||
if (!TreeComponent.DefaultExpandAll)
|
||||
{
|
||||
if (this.Expanded)
|
||||
this.OpenPropagation();
|
||||
}
|
||||
base.OnInitialized();
|
||||
}
|
||||
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
DefaultBinding();
|
||||
base.OnParametersSet();
|
||||
}
|
||||
private void DefaultBinding()
|
||||
{
|
||||
if (!_defaultBinding)
|
||||
{
|
||||
_defaultBinding = true;
|
||||
if (this.Checked)
|
||||
this.SetChecked(true);
|
||||
this.SetChecked(TreeComponent?.DefaultCheckedKeys?.Any(k => k == Key) ?? false);
|
||||
this.SetSelected(TreeComponent?.DefaultSelectedKeys?.Any(k => k == Key) ?? false);
|
||||
if (!TreeComponent.DefaultExpandAll)
|
||||
{
|
||||
if (this.Expanded)
|
||||
this.OpenPropagation();
|
||||
|
||||
if (TreeComponent.DefaultExpandedKeys != null)
|
||||
{
|
||||
if (TreeComponent.DefaultExpandedKeys.Contains(this.Key))
|
||||
{
|
||||
this.OpenPropagation();
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private void DefaultBindingold()
|
||||
{
|
||||
if (!_defaultBinding)
|
||||
{
|
||||
_defaultBinding = true;
|
||||
if (this.Checked)
|
||||
this.SetChecked(true);
|
||||
|
||||
TreeComponent.DefaultCheckedKeys?.ForEach(k =>
|
||||
{
|
||||
var node = TreeComponent._allNodes.FirstOrDefault(x => x.Key == k);
|
||||
if (node != null)
|
||||
node.SetChecked(true);
|
||||
});
|
||||
|
||||
TreeComponent.DefaultSelectedKeys?.ForEach(k =>
|
||||
{
|
||||
var node = TreeComponent._allNodes.FirstOrDefault(x => x.Key == k);
|
||||
if (node != null)
|
||||
node.SetSelected(true);
|
||||
});
|
||||
|
||||
if (!TreeComponent.DefaultExpandAll)
|
||||
{
|
||||
if (this.Expanded)
|
||||
this.OpenPropagation();
|
||||
TreeComponent.DefaultExpandedKeys?.ForEach(k =>
|
||||
{
|
||||
var node = TreeComponent._allNodes.FirstOrDefault(x => x.Key == k);
|
||||
if (node != null)
|
||||
node.OpenPropagation();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -39,11 +39,17 @@ namespace AntDesign
|
||||
return JsonSerializer.Deserialize<TResponseModel>(this.Response, options);
|
||||
}
|
||||
|
||||
public static string[] ImageExtensions { get; set; } = new[] { ".jpg", ".png", ".gif", ".ico", ".jfif", ".jpeg", ".bmp", ".tga", ".svg", ".tif", ".webp" };
|
||||
|
||||
public bool IsPicture()
|
||||
{
|
||||
string[] imageTypes = new[] { ".jpg", ".png", ".gif", ".ico",".jfif",".jpeg",".bmp",".tga",".svg",".tif" };
|
||||
Ext = FileName.Substring(FileName.LastIndexOf('.'));
|
||||
return imageTypes.Any(imageType => imageType.Equals(Ext, StringComparison.InvariantCultureIgnoreCase));
|
||||
if (string.IsNullOrEmpty(Ext))
|
||||
{
|
||||
var lastIndex = FileName.LastIndexOf('.');
|
||||
if (lastIndex < 0) return false;
|
||||
Ext = FileName[lastIndex..];
|
||||
}
|
||||
return ImageExtensions.Any(imageExt => imageExt.Equals(Ext, StringComparison.InvariantCultureIgnoreCase));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -47,6 +47,18 @@ $ dotnet publish -c release -o dist
|
||||
$ dotnet add package AntDesign
|
||||
```
|
||||
|
||||
### 注册依赖
|
||||
|
||||
在 `Startup.cs` 文件中注册 AntDesign 服务
|
||||
|
||||
```cs
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
...
|
||||
services.AddAntDesign();
|
||||
}
|
||||
```
|
||||
|
||||
### 引入样式
|
||||
|
||||
#### 使用样式与脚本
|
||||
|
@ -8,7 +8,7 @@ Following the Ant Design specification, we developed a Blazor Components library
|
||||
<div class="pic-plus">
|
||||
<img width="150" src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg">
|
||||
<span>+</span>
|
||||
<img height="150" src="https://raw.githubusercontent.com/ant-design-blazor/ant-design-blazor/docs/assets/blazor.svg">
|
||||
<img height="150" src="https://raw.githubusercontent.com/ant-design-blazor/ant-design-blazor/master/docs/assets/blazor.svg">
|
||||
</div>
|
||||
|
||||
<style>
|
||||
@ -49,7 +49,7 @@ WebAssembly static hosting examples:
|
||||
- Run directly on [.NET MAUI](https://dotnet.microsoft.com/zh-cn/apps/maui?WT.mc_id=DT-MVP-5003987) / [WPF](https://docs.microsoft.com/en-us/aspnet/core/blazor/hybrid/tutorials/wpf?view=aspnetcore-6.0&WT.mc_id=DT-MVP-5003987) / [Windows Forms](https://docs.microsoft.com/en-us/aspnet/core/blazor/hybrid/tutorials/windows-forms?view=aspnetcore-6.0) and other Blazor Hybrid workloads.
|
||||
- Run directly on [Electron](http://electron.atom.io/) and other Web standards-based environments.
|
||||
|
||||
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br> Edge / IE | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/src/opera/opera_48x48.png" alt="Opera" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Opera | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/src/electron/electron_48x48.png" alt="Electron" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Electron |
|
||||
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br> Edge / IE | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/opera/opera_48x48.png" alt="Opera" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Opera | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/electron/electron_48x48.png" alt="Electron" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Electron |
|
||||
| :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
|
||||
| Edge 16 / IE 11† | 522 | 57 | 11 | 44 | Chromium 57 |
|
||||
|
||||
@ -77,7 +77,7 @@ We have provided the `dotnet new` template to create a [Boilerplate](https://git
|
||||
- Install the template
|
||||
|
||||
```bash
|
||||
$ dotnet new --install AntDesign.Templates::0.1.0-*
|
||||
$ dotnet new --install AntDesign.Templates
|
||||
```
|
||||
|
||||
- Create the Boilerplate project with the template
|
||||
@ -101,7 +101,7 @@ Options for the template:
|
||||
- Go to the project folder of the application and install the Nuget package reference
|
||||
|
||||
```bash
|
||||
$ dotnet add package AntDesign --version 0.1.0-*
|
||||
$ dotnet add package AntDesign
|
||||
```
|
||||
|
||||
- Register the services
|
||||
@ -148,7 +148,7 @@ Options for the template:
|
||||
|
||||
## 🔨 Local Development
|
||||
|
||||
- Install [.NET Core SDK](https://dotnet.microsoft.com/download?WT.mc_id=DT-MVP-5003987) 5.0.100 or later.
|
||||
- Install [.NET Core SDK](https://dotnet.microsoft.com/download?WT.mc_id=DT-MVP-5003987) 6.0.x or later.
|
||||
- Install Node.js (only for building style files and interoperable TypeScript files)
|
||||
- Clone to local development
|
||||
|
||||
@ -161,7 +161,7 @@ Options for the template:
|
||||
|
||||
- Visit https://localhost:5001 in your supported browser and check [local development documentation](https://github.com/ant-design-blazor/ant-design-blazor/wiki) for details.
|
||||
|
||||
> Visual Studio 2019 is recommended for development.
|
||||
> Visual Studio 2022 is recommended for development.
|
||||
|
||||
## 🔗 Links
|
||||
|
||||
@ -169,10 +169,6 @@ Options for the template:
|
||||
- [Official Blazor Documentation](https://docs.microsoft.com/en-us/aspnet/core/blazor/?WT.mc_id=DT-MVP-5003987)
|
||||
- [MS Learn for Blazor Tutorial](https://docs.microsoft.com/en-us/learn/modules/build-blazor-webassembly-visual-studio-code/?WT.mc_id=DT-MVP-5003987)
|
||||
|
||||
## 🗺 Roadmap
|
||||
|
||||
Check out this [issue](https://github.com/ant-design-blazor/ant-design-blazor/issues/21) to learn about our development plans for 2020.
|
||||
|
||||
## 🤝 Contributing
|
||||
|
||||
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](https://github.com/ant-design-blazor/ant-design-blazor/pulls)
|
||||
|
@ -8,7 +8,7 @@ title: Ant Design of Blazor
|
||||
<div class="pic-plus">
|
||||
<img width="150" src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg">
|
||||
<span>+</span>
|
||||
<img height="150" src="https://raw.githubusercontent.com/ant-design-blazor/ant-design-blazor/docs/assets/blazor.svg">
|
||||
<img height="150" src="https://raw.githubusercontent.com/ant-design-blazor/ant-design-blazor/master/docs/assets/blazor.svg">
|
||||
</div>
|
||||
|
||||
<style>
|
||||
@ -48,7 +48,7 @@ title: Ant Design of Blazor
|
||||
- 可直接运行在 [.NET MAUI](https://dotnet.microsoft.com/zh-cn/apps/maui?WT.mc_id=DT-MVP-5003987)、[WPF](https://docs.microsoft.com/en-us/aspnet/core/blazor/hybrid/tutorials/wpf?view=aspnetcore-6.0&WT.mc_id=DT-MVP-5003987)、[Windows Forms](https://docs.microsoft.com/en-us/aspnet/core/blazor/hybrid/tutorials/windows-forms?view=aspnetcore-6.0) 等 Blazor 混合客户端环境中。
|
||||
- 可直接运行在 [Electron](http://electron.atom.io/) 等基于 Web 标准的环境上
|
||||
|
||||
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br> Edge / IE | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/src/opera/opera_48x48.png" alt="Opera" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Opera | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/src/electron/electron_48x48.png" alt="Electron" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Electron |
|
||||
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br> Edge / IE | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/opera/opera_48x48.png" alt="Opera" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Opera | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/electron/electron_48x48.png" alt="Electron" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Electron |
|
||||
| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
|
||||
| Edge 16 / IE 11† | 522 | 57 | 11 | 44 | Chromium 57 |
|
||||
|
||||
@ -76,7 +76,7 @@ title: Ant Design of Blazor
|
||||
- 安装模板
|
||||
|
||||
```bash
|
||||
$ dotnet new --install AntDesign.Templates::0.1.0-*
|
||||
$ dotnet new --install AntDesign.Templates
|
||||
```
|
||||
|
||||
- 从模板创建 Ant Design Blazor Pro 项目
|
||||
@ -98,7 +98,7 @@ title: Ant Design of Blazor
|
||||
- 进入应用的项目文件夹,安装 Nuget 包引用
|
||||
|
||||
```bash
|
||||
$ dotnet add package AntDesign --version 0.1.0-*
|
||||
$ dotnet add package AntDesign
|
||||
```
|
||||
|
||||
- 在项目中注册:
|
||||
@ -182,7 +182,7 @@ title: Ant Design of Blazor
|
||||
|
||||
- [![钉钉群](https://img.shields.io/badge/钉钉-AntBlazor-blue.svg?style=flat-square&logo=data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/Pg0KPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGNsYXNzPSJpY29uIiB2aWV3Qm94PSIwIDAgMTAyNCAxMDI0IiBmaWxsPSIjZmZmZmZmIj4NCiAgPHBhdGggZD0iTTU3My43IDI1Mi41QzQyMi41IDE5Ny40IDIwMS4zIDk2LjcgMjAxLjMgOTYuN2MtMTUuNy00LjEtMTcuOSAxMS4xLTE3LjkgMTEuMS01IDYxLjEgMzMuNiAxNjAuNSA1My42IDE4Mi44IDE5LjkgMjIuMyAzMTkuMSAxMTMuNyAzMTkuMSAxMTMuN1MzMjYgMzU3LjkgMjcwLjUgMzQxLjljLTU1LjYtMTYtMzcuOSAxNy44LTM3LjkgMTcuOCAxMS40IDYxLjcgNjQuOSAxMzEuOCAxMDcuMiAxMzguNCA0Mi4yIDYuNiAyMjAuMSA0IDIyMC4xIDRzLTM1LjUgNC4xLTkzLjIgMTEuOWMtNDIuNyA1LjgtOTcgMTIuNS0xMTEuMSAxNy44LTMzLjEgMTIuNSAyNCA2Mi42IDI0IDYyLjYgODQuNyA3Ni44IDEyOS43IDUwLjUgMTI5LjcgNTAuNSAzMy4zLTEwLjcgNjEuNC0xOC41IDg1LjItMjQuMkw1NjUgNzQzLjFoODQuNkw2MDMgOTI4bDIwNS4zLTI3MS45SDcwMC44bDIyLjMtMzguN2MuMy41LjQuOC40LjhTNzk5LjggNDk2LjEgODI5IDQzMy44bC42LTFoLS4xYzUtMTAuOCA4LjYtMTkuNyAxMC0yNS44IDE3LTcxLjMtMTE0LjUtOTkuNC0yNjUuOC0xNTQuNXoiLz4NCjwvc3ZnPg0K)](https://h5.dingtalk.com/circle/healthCheckin.html?corpId=dingf3df1949a4aa48627b0128d9a44ecb79&c5df5865-4f41-=be1b34c7-397b-&cbdbhh=qwertyuiop&origin=11) (中文)
|
||||
|
||||
<img src="https://raw.githubusercontent.com/ant-design-blazor/ant-design-blazor/docs/assets/dingtalk.jpg" width="300">
|
||||
<img src="https://raw.githubusercontent.com/ant-design-blazor/ant-design-blazor/master/docs/assets/dingtalk.jpg" width="300">
|
||||
|
||||
- 另外,我还创立了面向中文开发者的 Blazor 中文社区,高手如云,只讨论技术,无卖课广告。可以加我微信(JamesYeungMVP)拉进微信群,另外也有一个 QQ 群 1012762441。广告勿扰。
|
||||
|
||||
|
@ -57,7 +57,7 @@
|
||||
"husky": "^4.2.3",
|
||||
"inquirer": "^7.1.0",
|
||||
"jquery": "^3.4.1",
|
||||
"jsdom": "^16.0.0",
|
||||
"jsdom": "^16.5.0",
|
||||
"less": "^4.1.0",
|
||||
"less-plugin-clean-css": "^1.5.1",
|
||||
"less-plugin-npm-import": "^2.1.0",
|
||||
@ -76,4 +76,4 @@
|
||||
"dependencies": {
|
||||
"antblazor.js-ts.tests": "file:tests/AntDesign.Tests.Js"
|
||||
}
|
||||
}
|
||||
}
|
@ -22,7 +22,7 @@
|
||||
#if NET5_0_OR_GREATER
|
||||
var polyfillPath = "_framework/blazor.polyfill.min.js";
|
||||
#else
|
||||
var polyfillPath = "https://raw.githubusercontent.com/Daddoon/Blazor.Polyfill@3.0.8/Publish/Blazor.Polyfill.Publish/blazor.polyfill.min.js";
|
||||
var polyfillPath = "https://raw.githubusercontent.com/Daddoon/Blazor.Polyfill/3.0.8/Publish/Blazor.Polyfill.Publish/blazor.polyfill.min.js";
|
||||
#endif
|
||||
#if NET6_0
|
||||
var isNET6 = true;
|
||||
|
@ -1,17 +1,41 @@
|
||||
@inject DrawerService DrawerService
|
||||
@inject ConfirmService confirmService
|
||||
|
||||
<Input @bind-Value="@value" />
|
||||
<br />
|
||||
<br />
|
||||
<Button OnClick="OpenComponent" Type="primary">Use Component</Button>
|
||||
<Space Direction="DirectionVHType.Vertical">
|
||||
<SpaceItem>
|
||||
<Space>
|
||||
<SpaceItem>
|
||||
<Input @bind-Value="@value" />
|
||||
</SpaceItem>
|
||||
<SpaceItem>
|
||||
<Button OnClick="OpenComponent" Type="primary">Use Component</Button>
|
||||
</SpaceItem>
|
||||
</Space>
|
||||
</SpaceItem>
|
||||
|
||||
<SpaceItem>
|
||||
<div>
|
||||
<Button Type="primary" @onclick="@OpenDrawer">OpenDrawer</Button>
|
||||
<Drawer Closable="true"
|
||||
Visible="@visible"
|
||||
Placement="right"
|
||||
Title='("Basic Drawer")'
|
||||
OnOpen="@OnOpen"
|
||||
OnClose="@CloseDrawer">
|
||||
<p>Some contents...</p>
|
||||
<p>Some contents...</p>
|
||||
<p>Some contents...</p>
|
||||
</Drawer>
|
||||
</div>
|
||||
</SpaceItem>
|
||||
</Space>
|
||||
|
||||
|
||||
@code{
|
||||
|
||||
// #region use component
|
||||
private string value = "blazor";
|
||||
|
||||
|
||||
// use component
|
||||
private async Task OpenComponent()
|
||||
{
|
||||
var options = new DrawerOptions()
|
||||
@ -24,13 +48,13 @@
|
||||
|
||||
drawerRef.OnOpen = () =>
|
||||
{
|
||||
Console.WriteLine("OnAfterOpen");
|
||||
Console.WriteLine("drawerRef OnOpen");
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
drawerRef.OnClosing = async handle =>
|
||||
{
|
||||
Console.WriteLine("OnAfterClosing:");
|
||||
Console.WriteLine("drawerRef OnClosing");
|
||||
|
||||
if (await confirmService.Show("Drawer to close?", "Confirm?", ConfirmButtons.YesNo) == ConfirmResult.No)
|
||||
{
|
||||
@ -40,11 +64,38 @@
|
||||
|
||||
drawerRef.OnClosed = async result =>
|
||||
{
|
||||
Console.WriteLine("OnAfterClosed:" + result);
|
||||
Console.WriteLine("drawerRef OnClosed, value:" + result);
|
||||
if (result != null)
|
||||
value = result;
|
||||
await InvokeAsync(StateHasChanged);
|
||||
};
|
||||
|
||||
}
|
||||
//# endregion
|
||||
|
||||
|
||||
// #region use <Drawer></Drawer>
|
||||
|
||||
bool visible = false;
|
||||
|
||||
void OpenDrawer()
|
||||
{
|
||||
this.visible = true;
|
||||
}
|
||||
|
||||
async Task OnOpen()
|
||||
{
|
||||
var confirmResult = await confirmService.Show("OnOpen event: Are you sure to close the drawer?", "Question", ConfirmButtons.YesNo);
|
||||
if (confirmResult == ConfirmResult.Yes)
|
||||
{
|
||||
this.visible = false;
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void CloseDrawer()
|
||||
{
|
||||
this.visible = false;
|
||||
}
|
||||
// #endregion
|
||||
}
|
@ -9,7 +9,26 @@ title:
|
||||
|
||||
Drawer 的事件处理
|
||||
|
||||
对于 Drawer 组件:
|
||||
1. OnOpen: 在打开前执行,并可以通过参数的 `Cancel` 属性取消打开操作。
|
||||
2. OnClose: 在关闭前执行,你需要通过它来控制 Drawer 组件的 `Visible` 属性。
|
||||
|
||||
对于 DrawerService:
|
||||
1. DrawerRef.OnOpen: 在打开前执行,内部是在 `Drawe.OnOpen` 事件中调用该方法
|
||||
2. DrawerRef.OnClosing: 在关闭前执行
|
||||
3. DrawerRef.OnClosed: 在关闭后执行。
|
||||
|
||||
|
||||
|
||||
## en-US
|
||||
|
||||
Drawer event handling
|
||||
Drawer event handling
|
||||
|
||||
For Drawer component:
|
||||
1. OnOpen: Execute before opening, and you can cancel the opening operation through the `Cancel` attribute of the parameter.
|
||||
2. OnClose: Before closing, you need to control the `Visible` paramter of the Drawer component through it.
|
||||
|
||||
For DrawerService:
|
||||
1. DrawerRef.OnOpen: Execute before opening, and call this method in `Drawe.OnOpen` event internally.
|
||||
2. DrawerRef.OnClosing: Execute before closing
|
||||
3. DrawerRef.OnClosed: Execute after shutdown
|
@ -31,17 +31,18 @@ tasks can be achieved more efficiently within thesame context.
|
||||
| ChildContent | Subcomponent | object | - |
|
||||
| MaskClosable | Clicking on the mask (area outside the Drawer) to close the Drawer or not. | boolean | true |
|
||||
| MaskStyle | Style for Drawer's mask element. | object | - |
|
||||
| Mask | Whether to show mask or not. | boolean | true |
|
||||
| Placement | The placement of the Drawer, option could be `left` , `top`,`right`,`bottom` | string | `right` |
|
||||
| WrapClassName | The class name of the container of the Drawer dialog. | string | - |
|
||||
| Width | Width of the Drawer dialog. | | int |
|
||||
| Width | Width of the Drawer dialog, only when placement is 'left' or 'right'. | | int |
|
||||
| Height | placement is top or bottom, height of the Drawer dialog. | int | 256 |
|
||||
| ZIndex | The z-index of the Drawer. | int | - |
|
||||
| OffsetX | The the X coordinate offset(px), only when placement is `'left'` or `'right'`. | int | 0 |
|
||||
| OffsetY | The the Y coordinate offset(px), only when placement is `'top'` or `'bottom'`. | int | 0 |
|
||||
| Visible | Whether the Drawer dialog is visible or not. | boolean | - |
|
||||
| Keyboard | Whether support press esc to close | boolean | true |
|
||||
| OnClose | Specify a callback that will be called when a user clicks mask, close button or Cancel button. | function(e) | - |
|
||||
| OnViewInit | Specify a callback that will be called before drawer displayed | function(e) | - |
|
||||
| OnClose | Specify a callback that will be called when a user clicks mask, close button or Cancel button. | EventCallback | - |
|
||||
| OnOpen | Specify a callback that will be called after drawer rendered | Func<Task> | - |
|
||||
|
||||
### DrawerService
|
||||
|
||||
@ -62,7 +63,7 @@ tasks can be achieved more efficiently within thesame context.
|
||||
| CloseOnNavigation | Whether to close the drawer when the navigation history changes | `boolean` | `true` |
|
||||
| Keyboard | Whether to support keyboard esc off | `boolean` | `true` |
|
||||
| MaskStyle | Style for Drawer's mask element. | `string` | `{}` |
|
||||
| BodyStyle | Body style for modal body element. Such as height, padding etc. | `string` | `{}` |
|
||||
| BodyStyle | Body style for Drawer body element. Such as height, padding etc. | `string` | `{}` |
|
||||
| Title | The title for Drawer. | `OneOf<RenderFragment, string>` | - |
|
||||
| Width | Width of the Drawer dialog. | `int` | `256` |
|
||||
| Height | Height of the Drawer dialog, only when placement is `'top'` or `'bottom'`. | `int` | `256` |
|
||||
|
@ -22,22 +22,23 @@ cover: https://gw.alipayobjects.com/zos/alicdn/7z8NJQhFb/Drawer.svg
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| ------------- | ------------------------------------------------------- | -------------- | ------- |
|
||||
| Title | 标题 | string or slot | - |
|
||||
| BodyStyle | 可用于设置 Drawer 内容部分的样式 | object | - |
|
||||
| BodyStyle | 可用于设置 Drawer 内容部分的样式 | object | - |
|
||||
| Closable | 是否显示右上角的关闭按钮 | boolean | true |
|
||||
| ChildContent | 抽屉元素之间的子组件 | object | - |
|
||||
| MaskClosable | 点击蒙层是否允许关闭 | boolean | true |
|
||||
| MaskStyle | 遮罩样式 | object | - |
|
||||
| Placement | 抽屉的方向,可选值为 `left` , `top`,`right`,`bottom` | string | `right` |
|
||||
| Mask | 是否展示遮罩 | boolean | true |
|
||||
| Placement | 抽屉的方向,可选值为 `left` , `top`,`right`,`bottom` | string | right |
|
||||
| WrapClassName | 对话框外层容器的类名 | string | - |
|
||||
| Width | 宽度 | string\|int | 256 |
|
||||
| Width | 宽度 | string\|int | 256 |
|
||||
| Height | 高度, 在 placement 为 top 或 bottom 时使用 | | int |
|
||||
| ZIndex | 设置 Drawer 的 z-index | int | - |
|
||||
| ZIndex | 设置 Drawer 的 z-index | int | - |
|
||||
| OffsetX | X 轴方向的偏移量,只在方向为 `'left'`或`'right'` 时生效 | int | 0 |
|
||||
| OffsetY | Y 轴方向的偏移量,只在方向为 `'top'`或`'bottom'` 时生效 | int | 0 |
|
||||
| Visible | Drawer 是否可见 | boolean | - |
|
||||
| Keyboard | 是否支持键盘 esc 关闭 | boolean | true |
|
||||
| OnClose | 点击遮罩层或右上角叉或取消按钮的回调 | function(e) | - |
|
||||
| OnViewInit | 抽屉显示之前回调事件 | function(e) | - |
|
||||
| OnClose | 点击遮罩层或右上角叉或取消按钮的回调 | EventCallback | - |
|
||||
| OnOpen | 抽屉渲染之后回调事件 | Func<Task> | - |
|
||||
|
||||
### DrawerService
|
||||
|
||||
@ -58,7 +59,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/7z8NJQhFb/Drawer.svg
|
||||
| CloseOnNavigation | 导航历史变化时是否关闭抽屉组件 | `boolean` | `true` |
|
||||
| Keyboard | 是否支持键盘 esc 关闭 | `boolean` | `true` |
|
||||
| MaskStyle | 遮罩样式 | `string` | `{}` |
|
||||
| BodyStyle | Modal body 样式 | `string` | `{}` |
|
||||
| BodyStyle | Drawer body 样式 | `string` | `{}` |
|
||||
| Title | 标题 | `OneOf<RenderFragment, string>` | - |
|
||||
| Width | 宽度 | `int` | `256` |
|
||||
| Height | 高度, 只在方向为 `'top'`或`'bottom'` 时生效 | `int` | `256` |
|
||||
|
@ -15,7 +15,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/ORmcdeaoO/Form.svg
|
||||
- 需要对输入的数据类型进行校验时。
|
||||
|
||||
## API
|
||||
### From
|
||||
### Form
|
||||
| 名称 | 说明 | 类型 | 默认值 |
|
||||
| --- | --- | --- | --- |
|
||||
| Layout | 表单布局 | [FormLayout](https://github.com/ant-design-blazor/ant-design-blazor/blob/master/components/form/types/FormLayout.cs) | FormLayout.Horizontal |
|
||||
@ -32,7 +32,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/ORmcdeaoO/Form.svg
|
||||
| OnFinish | 提交事件 | EventCallback\<EditContext\> | - |
|
||||
| OnFinishFailed | 提交失败(校验失败)回调事件 | EventCallback\<EditContext\> | - |
|
||||
| ValidateOnChange | 是否在更改时校验 | bool | false |
|
||||
### FromItem
|
||||
### FormItem
|
||||
| 名称 | 说明 | 类型 | 默认值 |
|
||||
| --- | --- | --- | --- |
|
||||
| Label | **label** 标签的文本 | string | input组件的Display或者DisplayName特性 |
|
||||
|
@ -1,15 +1,18 @@
|
||||
@inject IconService iconService;
|
||||
|
||||
<div class="icons-list">
|
||||
<IconFont Type="icon-tuichu" />
|
||||
<IconFont Type="icon-facebook" />
|
||||
<IconFont Type="icon-twitter" />
|
||||
<IconFont Type="icon-tuichu" />
|
||||
<IconFont Type="icon-facebook" />
|
||||
<IconFont Type="icon-twitter" />
|
||||
</div>
|
||||
|
||||
@code
|
||||
{
|
||||
protected override async Task OnInitializedAsync()
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
await iconService.CreateFromIconfontCN("//at.alicdn.com/t/font_8d5l8fzk5b87iudi.js");
|
||||
await iconService.CreateFromIconfontCN("//at.alicdn.com/t/font_8d5l8fzk5b87iudi.js");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,17 +1,20 @@
|
||||
@inject IconService iconService;
|
||||
|
||||
<div class="icons-list">
|
||||
<IconFont Type="icon-javascript" />
|
||||
<IconFont Type="icon-java" />
|
||||
<IconFont Type="icon-shoppingcart" />
|
||||
<IconFont Type="icon-python" />
|
||||
<IconFont Type="icon-javascript" />
|
||||
<IconFont Type="icon-java" />
|
||||
<IconFont Type="icon-shoppingcart" />
|
||||
<IconFont Type="icon-python" />
|
||||
</div>
|
||||
|
||||
@code
|
||||
{
|
||||
protected override async Task OnInitializedAsync()
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
await iconService.CreateFromIconfontCN("//at.alicdn.com/t/font_1788044_0dwu4guekcwr.js");
|
||||
await iconService.CreateFromIconfontCN("//at.alicdn.com/t/font_1788592_a5xf2bdic3u.js");
|
||||
await iconService.CreateFromIconfontCN("//at.alicdn.com/t/font_1788044_0dwu4guekcwr.js");
|
||||
await iconService.CreateFromIconfontCN("//at.alicdn.com/t/font_1788592_a5xf2bdic3u.js");
|
||||
}
|
||||
}
|
||||
}
|
@ -9,6 +9,10 @@ title:
|
||||
|
||||
对于使用 [iconfont.cn](http://iconfont.cn/) 的用户,通过设置 `createFromIconfontCN` 方法参数对象中的 `scriptUrl` 字段, 即可轻松地使用已有项目中的图标。
|
||||
|
||||
> 注意:这个方法会涉及JS互操作,因此需要确保在 `firstRender=true` 时调用。
|
||||
|
||||
## en-US
|
||||
|
||||
If you are using [iconfont.cn](http://iconfont.cn/), you can use the icons in your project gracefully.
|
||||
If you are using [iconfont.cn](http://iconfont.cn/), you can use the icons in your project gracefully.
|
||||
|
||||
> Note: This method involves JS interope, so make sure you call it when 'firstRender=true'.
|
@ -7,8 +7,12 @@ title:
|
||||
|
||||
## zh-CN
|
||||
|
||||
`@ant-design/icons@4.1.0` 以后,`scriptUrl` 可引用多个资源,用户可灵活的管理 [iconfont.cn](http://iconfont.cn/) 图标。如果资源的图标出现重名,会按照数组顺序进行覆盖。
|
||||
使用`scriptUrl` 可引用多个资源,用户可灵活的管理 [iconfont.cn](http://iconfont.cn/) 图标。如果资源的图标出现重名,会按照数组顺序进行覆盖。
|
||||
|
||||
> 注意:这个方法会涉及JS互操作,因此需要确保在 `firstRender=true` 时调用。
|
||||
|
||||
## en-US
|
||||
|
||||
You can use `scriptUrl` as an array after `@ant-design/icons@4.1.0`, manage icons in one `<Icon />` from multiple [iconfont.cn](http://iconfont.cn/) resources. If icon with a duplicate name in resources, it will overrided in array order.
|
||||
You can use `scriptUrl` multiple times, manage icons in one `<Icon />` from multiple [iconfont.cn](http://iconfont.cn/) resources. If icon with a duplicate name in resources, it will overrided in array order.
|
||||
|
||||
> Note: This method involves JS interope, so make sure you call it when 'firstRender=true'
|
@ -1,15 +1,5 @@
|
||||
@code
|
||||
{
|
||||
bool collapsed;
|
||||
|
||||
void toggle()
|
||||
{
|
||||
collapsed = !collapsed;
|
||||
}
|
||||
}
|
||||
|
||||
<Layout>
|
||||
<Sider Collapsible Collapsed=@collapsed NoTrigger OnCollapse="OnCollapse">
|
||||
<Layout>
|
||||
<Sider @bind-Collapsed=@collapsed NoTrigger OnCollapse="OnCollapse">
|
||||
<div class="logo" />
|
||||
<Menu Theme="MenuTheme.Dark" Mode="MenuMode.Inline" DefaultSelectedKeys=@(new[]{"1"})>
|
||||
<MenuItem Key="1">
|
||||
@ -69,6 +59,12 @@
|
||||
|
||||
|
||||
@code{
|
||||
bool collapsed;
|
||||
|
||||
void toggle()
|
||||
{
|
||||
collapsed = !collapsed;
|
||||
}
|
||||
|
||||
void OnCollapse(bool isCollapsed)
|
||||
{
|
||||
|
@ -1,5 +0,0 @@
|
||||
<h3>CustomTriggerDebug</h3>
|
||||
|
||||
@code {
|
||||
|
||||
}
|
@ -1,12 +1,8 @@
|
||||
<Layout>
|
||||
<Sider Breakpoint="@BreakpointType.Lg"
|
||||
CollapsedWidth="64"
|
||||
OnBreakpoint="@(broken => {
|
||||
Console.WriteLine($"OnBreakpoint:{broken}");
|
||||
})"
|
||||
OnCollapse="@(collapsed => {
|
||||
Console.WriteLine($"collapsed:{collapsed}");
|
||||
})">
|
||||
@bind-Collapsed=@collapsed
|
||||
>
|
||||
<div class="logo" />
|
||||
<Menu Theme="MenuTheme.Dark" Mode="MenuMode.Inline" DefaultSelectedKeys=@(new[]{"4"})>
|
||||
<MenuItem Key="1">
|
||||
@ -38,6 +34,10 @@
|
||||
</Layout>
|
||||
</Layout>
|
||||
|
||||
@code{
|
||||
bool collapsed;
|
||||
}
|
||||
|
||||
<style>
|
||||
#components-layout-demo-responsive .logo {
|
||||
height: 32px;
|
||||
|
@ -1,11 +0,0 @@
|
||||
---
|
||||
order: 99
|
||||
title:
|
||||
zh-CN: 自定义触发器 Debug
|
||||
en-US: Custom trigger debug
|
||||
debug: true
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
修改内容前,请尝试此 Demo 查看样式是否抖动。
|
@ -0,0 +1,44 @@
|
||||
<Divider Orientation="left">Draggable</Divider>
|
||||
|
||||
<AntList Bordered DataSource="@data">
|
||||
<Header>Header</Header>
|
||||
<ChildContent Context="item">
|
||||
<ListItem>
|
||||
<div draggable="true" @ondrop="e=>OnDrop(e, item)" @ondragstart="e=>OnDragStart(e, item)" ondragover="event.preventDefault()">
|
||||
<span><Text Mark>[ITEM]</Text></span>@item
|
||||
</div>
|
||||
</ListItem>
|
||||
</ChildContent>
|
||||
|
||||
<Footer>Footer</Footer>
|
||||
</AntList>
|
||||
|
||||
@code {
|
||||
string _dragging;
|
||||
void OnDrop(DragEventArgs e, string s)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(s) && !string.IsNullOrEmpty(_dragging)) {
|
||||
System.Diagnostics.Trace.WriteLine(s);
|
||||
int index = data.IndexOf(s);
|
||||
data.Remove(_dragging);
|
||||
data.Insert(index, _dragging);
|
||||
_dragging = null;
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void OnDragStart(DragEventArgs e, string s)
|
||||
{
|
||||
e.DataTransfer.DropEffect = "move";
|
||||
e.DataTransfer.EffectAllowed = "move";
|
||||
_dragging = s;
|
||||
}
|
||||
|
||||
public List<string> data = new List<string> {
|
||||
"Racing car sprays burning fuel into crowd.",
|
||||
"Japanese princess to wed commoner.",
|
||||
"Australian walks 100km after outback crash.",
|
||||
"Man charged over missing wedding girl.",
|
||||
"Los Angeles battles huge wildfires."
|
||||
};
|
||||
}
|
12
site/AntDesign.Docs/Demos/Components/List/demo/draggable.md
Normal file
12
site/AntDesign.Docs/Demos/Components/List/demo/draggable.md
Normal file
@ -0,0 +1,12 @@
|
||||
---
|
||||
order: 8
|
||||
title:
|
||||
zh-CN: 可拖拽(Simple)
|
||||
en-US: Simple Draggable
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
为ListItem子组件包装一层div, 设置draggable='true', 并为之加上ondrop/ondragstart/ondragover事件处理函数.
|
||||
|
||||
## en-US
|
||||
Add a `div` element wrapping `ListItem` child element, set `draggable='true'`, add `ondrop`/`ondragstart`/`ondragover` event handler.
|
@ -24,6 +24,7 @@ Radio/Radio.Button
|
||||
| Checked | Specifies whether the radio is selected. | boolean |
|
||||
| DefaultChecked | Specifies the initial state: whether or not the radio is selected. | boolean |- |
|
||||
| Disabled | Disable radio | string | - |
|
||||
| RadioButton | Set to TRUE to style the radio as button group. | bool | false |
|
||||
| Value | According to value for comparison, to determine whether the selected | string | - |
|
||||
|
||||
RadioGroup
|
||||
|
@ -24,6 +24,7 @@ Radio/Radio.Button
|
||||
| Checked | 指定当前是否选中 | boolean |
|
||||
| DefaultChecked | 初始是否选中 | boolean |- |
|
||||
| Disabled | 禁用 Radio | string | - |
|
||||
| RadioButton | 设置为 TRUE 以将radio风格设置为按钮组 | bool | false |
|
||||
| Value | 根据 value 进行比较,判断是否选中 | string | - |
|
||||
|
||||
RadioGroup
|
||||
|
@ -8,6 +8,8 @@
|
||||
<Col Span="24">
|
||||
<CountDown Title="Day Level" Value="@deadline" Format="dd 天 h 小时 m 分钟 s 秒" />
|
||||
</Col>
|
||||
<br/>
|
||||
<Button OnClick="OnReset">Reset Value</Button>
|
||||
</Row>
|
||||
|
||||
@code
|
||||
@ -18,4 +20,9 @@
|
||||
{
|
||||
Console.WriteLine("finished!");
|
||||
}
|
||||
|
||||
void OnReset()
|
||||
{
|
||||
deadline = DateTime.Now.AddMinutes(10);
|
||||
}
|
||||
}
|
@ -1,25 +1,22 @@
|
||||
@using System.ComponentModel
|
||||
@using AntDesign.TableModels
|
||||
|
||||
<Table TItem="Dictionary<string, object>" DataSource="@data" Loading="data==null" ScrollX="1500" PageSize="5">
|
||||
@if (data?.Any() == true)
|
||||
{
|
||||
@foreach (var key in data.FirstOrDefault()?.Keys.Take(10))
|
||||
{
|
||||
<Column TData="object" DataIndex=@($"['{key}']") Title="@key"></Column>
|
||||
}
|
||||
}
|
||||
<Table TItem="Dictionary<string, object>" OnChange="HanleChange" DataSource="@data" Loading="data==null" ScrollX="1500" PageSize="5" Size="TableSize.Small">
|
||||
@foreach (var key in data?.FirstOrDefault()?.Keys.Take(10) ??new string[0])
|
||||
{
|
||||
<PropertyColumn Property=@(c=>c[key]) Title="@key"></PropertyColumn>
|
||||
}
|
||||
</Table>
|
||||
|
||||
@inject HttpClient httpClient;
|
||||
@code {
|
||||
|
||||
List<Dictionary<string, object>> data;
|
||||
List<Dictionary<string, object>> data;
|
||||
|
||||
string githubUrl = "https://api.github.com/repos/ant-design-blazor/ant-design-blazor/contributors?per_page=200";
|
||||
string githubUrl = "https://api.github.com/repos/ant-design-blazor/ant-design-blazor/contributors?per_page=200";
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
data = await httpClient.GetFromJsonAsync<List<Dictionary<string, object>>>(githubUrl);
|
||||
}
|
||||
protected async Task HanleChange(QueryModel<Dictionary<string, object>> query)
|
||||
{
|
||||
data = await httpClient.GetFromJsonAsync<List<Dictionary<string, object>>>(githubUrl);
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
DefaultExpandedKeys="@(new[] { "0-0-0", "0-0-1"})"
|
||||
DefaultSelectedKeys="@(new[] {"0-0-0", "0-0-1" })"
|
||||
DefaultCheckedKeys="@(new[] {"0-0-0", "0-0-1" })"
|
||||
SelectedNodeChanged="SelectedNodeChanged"
|
||||
SelectedNodeChanged="SelectedNodeChanged"
|
||||
OnSelect="OnSelect"
|
||||
OnCheck="OnCheck">
|
||||
<TreeNode Title="parent 1" Key="0-0" TItem="string">
|
||||
|
@ -0,0 +1,5 @@
|
||||
<h3>Async</h3>
|
||||
|
||||
@code {
|
||||
|
||||
}
|
@ -3,14 +3,13 @@
|
||||
@bind-Value="value"
|
||||
Placeholder="Please select"
|
||||
AllowClear
|
||||
TreeDefaultExpandAll
|
||||
OnChange="OnChange">
|
||||
TreeDefaultExpandAll>
|
||||
<TreeNode TItem="string" Key="parent 1" Title="parent 1">
|
||||
<TreeNode TItem="string" Key="parent 1-0" title="parent 1-0">
|
||||
<TreeNode TItem="string" Key="leaf1" title="leaf1" />
|
||||
<TreeNode TItem="string" Key="leaf2" title="leaf2" />
|
||||
<TreeNode TItem="string" Key="parent 1-0" Title="parent 1-0">
|
||||
<TreeNode TItem="string" Key="leaf1" Title="leaf1" />
|
||||
<TreeNode TItem="string" Key="leaf2" Title="leaf2" />
|
||||
</TreeNode>
|
||||
<TreeNode TItem="string" Key="parent 1-1" title="parent 1-1">
|
||||
<TreeNode TItem="string" Key="parent 1-1" Title="parent 1-1">
|
||||
<TreeNode TItem="string" Key="leaf3">
|
||||
<TitleTemplate>
|
||||
<b Style="color:#08c;">leaf3</b>
|
||||
@ -22,10 +21,5 @@
|
||||
|
||||
|
||||
@code {
|
||||
private string value;
|
||||
|
||||
public void OnChange()
|
||||
{
|
||||
|
||||
}
|
||||
private string value="leaf3";
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
<TreeSelect TItem="Data"
|
||||
Style="width:100%;"
|
||||
DataSource="treeData"
|
||||
@bind-Value="@value"
|
||||
Placeholder="Please select"
|
||||
AllowClear
|
||||
Multiple
|
||||
TreeCheckable
|
||||
TreeDefaultExpandAll
|
||||
ChildrenExpression="node=>node.DataItem.Children"
|
||||
TitleExpression="node=>node.DataItem.Title"
|
||||
KeyExpression="node=>node.DataItem.Key"
|
||||
IsLeafExpression="node=>node.DataItem.Children==null">
|
||||
</TreeSelect>
|
||||
|
||||
|
||||
@code {
|
||||
private string value;
|
||||
|
||||
Data[] treeData = new Data[]
|
||||
{
|
||||
new()
|
||||
{
|
||||
Title = "Node1",
|
||||
Key="0-0",
|
||||
Children = new Data[]
|
||||
{
|
||||
new()
|
||||
{
|
||||
Title = "Child Node1",
|
||||
Key="0-0-0",
|
||||
},
|
||||
}
|
||||
},
|
||||
new()
|
||||
{
|
||||
Title = "Node2",
|
||||
Key="0-1",
|
||||
Children = new Data[]
|
||||
{
|
||||
new()
|
||||
{
|
||||
Title ="Child Node3",
|
||||
Key="0-1-0"
|
||||
},
|
||||
new()
|
||||
{
|
||||
Title ="Child Node4",
|
||||
Key="0-1-1",
|
||||
},
|
||||
new()
|
||||
{
|
||||
Title ="Child Node5",
|
||||
Key="0-1-2",
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public class Data : ITreeData<Data>
|
||||
{
|
||||
public string Key { get; set; }
|
||||
public Data Value => this;
|
||||
public string Title { get; set; }
|
||||
public IEnumerable<Data> Children { get; set; }
|
||||
}
|
||||
}
|
@ -1,17 +1,17 @@
|
||||
<TreeSelect TItem="string"
|
||||
Style="width:100%;"
|
||||
@bind-Value="value"
|
||||
@bind-Values="values"
|
||||
DropdownStyle="max-height:400px;overflow:auto;"
|
||||
Placeholder="Please select"
|
||||
AllowClear
|
||||
Multiple
|
||||
TreeDefaultExpandAll
|
||||
OnChange="OnValuesChange">
|
||||
<TreeNode TItem="string" Key="parent 1" title="parent 1">
|
||||
<TreeNode TItem="string" Key="parent 1-0" title="parent 1-0">
|
||||
<TreeNode TItem="string" Key="leaf1" title="my leaf" />
|
||||
<TreeNode TItem="string" Key="leaf2" title="your leaf" />
|
||||
TreeDefaultExpandAll>
|
||||
<TreeNode TItem="string" Key="parent 1" Title="parent 1">
|
||||
<TreeNode TItem="string" Key="parent 1-0" Title="parent 1-0">
|
||||
<TreeNode TItem="string" Key="leaf1" Title="my leaf" />
|
||||
<TreeNode TItem="string" Key="leaf2" Title="your leaf" />
|
||||
</TreeNode>
|
||||
<TreeNode TItem="string" Key="parent 1-1" title="parent 1-1">
|
||||
<TreeNode TItem="string" Key="parent 1-1" Title="parent 1-1">
|
||||
<TreeNode TItem="string" Key="sss">
|
||||
<TitleTemplate>
|
||||
<b style=" color: #08c;">sss</b>
|
||||
@ -21,13 +21,10 @@
|
||||
</TreeNode>
|
||||
</TreeSelect>
|
||||
|
||||
@JsonSerializer.Serialize(values);
|
||||
|
||||
@code {
|
||||
|
||||
private string value;
|
||||
|
||||
public void OnValuesChange(IEnumerable<string> args)
|
||||
{
|
||||
Console.WriteLine(string.Join(',', args));
|
||||
}
|
||||
|
||||
private IEnumerable<string> values=new[]{"leaf1","leaf2"};
|
||||
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
<RadioGroup @bind-Value="_placement">
|
||||
<Radio RadioButton Value="Placement.TopLeft">topLeft</Radio>
|
||||
<Radio RadioButton Value="Placement.TopRight">topRight</Radio>
|
||||
<Radio RadioButton Value="Placement.BottomLeft">bottomLeft</Radio>
|
||||
<Radio RadioButton Value="Placement.BottomRight">bottomRight</Radio>
|
||||
</RadioGroup>
|
||||
<br />
|
||||
<br />
|
||||
<TreeSelect TItem="string"
|
||||
Style="width:100%;"
|
||||
DropdownStyle="max-height:400px;overflow:auto;"
|
||||
Placeholder="Please select"
|
||||
AllowClear
|
||||
Multiple
|
||||
TreeDefaultExpandAll>
|
||||
<TreeNode TItem="string" Value="parent 1" Title="parent 1">
|
||||
<TreeNode TItem="string" Value="parent 1-0" Title="parent 1-0">
|
||||
<TreeNode TItem="string" Value="leaf1" Title="leaf1" />
|
||||
<TreeNode TItem="string" Value="leaf2" Title="leaf2" />
|
||||
</TreeNode>
|
||||
<TreeNode TItem="string" Value="parent 1-1" Title="parent 1-1">
|
||||
<TreeNode TItem="string" Value="leaf3">
|
||||
<TitleTemplate>
|
||||
<b style=" color: #08c;">leaf3</b>
|
||||
</TitleTemplate>
|
||||
</TreeNode>
|
||||
</TreeNode>
|
||||
</TreeNode>
|
||||
</TreeSelect>
|
||||
|
||||
@code {
|
||||
Placement _placement;
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
---
|
||||
order: 1
|
||||
title:
|
||||
zh-CN: 多选赋值
|
||||
en-US: SetMultipleValue
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
展示设置选中多个点击节点,以及默认值功能。
|
||||
|
||||
## en-US
|
||||
|
||||
The most basic usage, tell you how to use tree-select multiple selected etc.
|
@ -1,68 +0,0 @@
|
||||
|
||||
|
||||
<SimpleTreeSelect Multiple="true" TItem="WebMenu" @bind-Values="selectMenuId"
|
||||
DataSource="@(LocalJsonData.Data)" AllowClear="true"
|
||||
TitleExpression="m => m.MenuName"
|
||||
KeyExpression="m => m.MenuId"
|
||||
DataItemExpression="(menus, menuId) => menus.FirstOrDefault(m => m.MenuId == menuId)"
|
||||
ChildrenMethodExpression="(menus, menuId) => menus.Where(m => m.ParentId == menuId).ToList()"
|
||||
IsLeafExpression="(menus,m) => menus.All(m => m.ParentId != m.MenuId)"
|
||||
Placeholder="Please select"
|
||||
TreeDefaultExpandAll>
|
||||
</SimpleTreeSelect>
|
||||
|
||||
select MenuId: @string.Join(',', selectMenuId ?? new[] { ""})
|
||||
|
||||
<Button OnClick="ChangeMenuId" OnClickStopPropagation="true">Update</Button>
|
||||
|
||||
@code{
|
||||
private IEnumerable<string> selectMenuId = new[] { "3", "1"};
|
||||
|
||||
private void ChangeMenuId()
|
||||
{
|
||||
selectMenuId = new[] { "5", "2" };
|
||||
}
|
||||
public class WebMenu
|
||||
{
|
||||
|
||||
public string MenuId { get; set; }
|
||||
|
||||
public string MenuHref { get; set; }
|
||||
|
||||
public string MenuName { get; set; }
|
||||
|
||||
public string Target { get; set; }
|
||||
|
||||
public string ParentId { get; set; }
|
||||
|
||||
public string Right { get; set; }
|
||||
|
||||
public int? OrderBy { get; set; } = 9999;
|
||||
|
||||
}
|
||||
|
||||
public static class LocalJsonData
|
||||
{
|
||||
private static readonly IList<WebMenu> _data;
|
||||
|
||||
static LocalJsonData()
|
||||
{
|
||||
_data = new List<WebMenu>() {
|
||||
new WebMenu(){ MenuId="1", MenuName="parent 1", ParentId="0", OrderBy=10},
|
||||
new WebMenu(){ MenuId="2", MenuName="parent 1-0", ParentId="1", OrderBy=10},
|
||||
new WebMenu(){ MenuId="3", MenuName="leaf1", ParentId="2", OrderBy=10},
|
||||
new WebMenu(){ MenuId="4", MenuName="leaf2", ParentId="0", OrderBy=10},
|
||||
new WebMenu(){ MenuId="5", MenuName="parent1-1", ParentId="0", OrderBy=10},
|
||||
new WebMenu(){ MenuId="6", MenuName="leaf3", ParentId="5", OrderBy=10}
|
||||
};
|
||||
}
|
||||
|
||||
public static IList<WebMenu> Data => _data;
|
||||
|
||||
|
||||
public static IList<WebMenu> GetMenusByParentId(string parentId)
|
||||
{
|
||||
return _data.Where(m => m.ParentId == parentId).ToList();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
|
||||
|
||||
|
||||
<SimpleTreeSelect TItem="WebMenu" @bind-Value="selectMenuId"
|
||||
DataSource="@(LocalJsonData.Data)"
|
||||
TitleExpression="m => m.MenuName"
|
||||
KeyExpression="m => m.MenuId"
|
||||
DataItemExpression="(menus, menuId) => menus.FirstOrDefault(m => m.MenuId == menuId)"
|
||||
ChildrenMethodExpression="(menus, menuId) => menus.Where(m => m.ParentId == menuId).ToList()"
|
||||
IsLeafExpression="(menus,m) => menus.All(m => m.ParentId != m.MenuId)"
|
||||
Placeholder="Please select"
|
||||
TreeDefaultExpandAll>
|
||||
</SimpleTreeSelect>
|
||||
|
||||
|
||||
select MenuId:<Input Placeholder="current Select MenuId" @bind-Value="@selectMenuId" /><Button OnClick="ChangeMenuId" OnClickStopPropagation="true">Update</Button>
|
||||
|
||||
@code{
|
||||
private string selectMenuId = "3";
|
||||
|
||||
private void ChangeMenuId()
|
||||
{
|
||||
selectMenuId = "5";
|
||||
}
|
||||
|
||||
public class WebMenu
|
||||
{
|
||||
|
||||
public string MenuId { get; set; }
|
||||
|
||||
public string MenuHref { get; set; }
|
||||
|
||||
public string MenuName { get; set; }
|
||||
|
||||
public string Target { get; set; }
|
||||
|
||||
public string ParentId { get; set; }
|
||||
|
||||
public string Right { get; set; }
|
||||
|
||||
public int? OrderBy { get; set; } = 9999;
|
||||
|
||||
}
|
||||
public static class LocalJsonData
|
||||
{
|
||||
private static readonly IList<WebMenu> _data;
|
||||
|
||||
static LocalJsonData()
|
||||
{
|
||||
_data = new List<WebMenu>() {
|
||||
new WebMenu(){ MenuId="1", MenuName="parent 1", ParentId="0", OrderBy=10},
|
||||
new WebMenu(){ MenuId="2", MenuName="parent 1-0", ParentId="1", OrderBy=10},
|
||||
new WebMenu(){ MenuId="3", MenuName="leaf1", ParentId="2", OrderBy=10},
|
||||
new WebMenu(){ MenuId="4", MenuName="leaf2", ParentId="0", OrderBy=10},
|
||||
new WebMenu(){ MenuId="5", MenuName="parent1-1", ParentId="0", OrderBy=10},
|
||||
new WebMenu(){ MenuId="6", MenuName="leaf3", ParentId="5", OrderBy=10}
|
||||
};
|
||||
}
|
||||
|
||||
public static IList<WebMenu> Data => _data;
|
||||
|
||||
|
||||
public static IList<WebMenu> GetMenusByParentId(string parentId)
|
||||
{
|
||||
return _data.Where(m => m.ParentId == parentId).ToList();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
---
|
||||
order: 1
|
||||
title:
|
||||
zh-CN: 赋值
|
||||
en-US: SetValue1
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
展示设置选中节点,以及默认值功能。XXXXXXXXXXX
|
||||
|
||||
## en-US
|
||||
|
||||
The most basic usage, tell you how to use tree-select multiple selected etc.
|
@ -1,66 +0,0 @@
|
||||
|
||||
|
||||
|
||||
<TreeSelect TItem="WebMenu"
|
||||
Style="width:100%;"
|
||||
@bind-Value="@ParentDeptId"
|
||||
DataSource="@(LocalJsonData.Data)"
|
||||
Placeholder="请选择"
|
||||
AllowClear="false"
|
||||
TitleExpression="m => m.MenuName"
|
||||
KeyExpression="m => m.MenuId"
|
||||
ChildrenExpression="m => LocalJsonData.GetMenusByParentId(m.MenuId)"
|
||||
IsLeafExpression="(menus,m) => menus.All(m => m.ParentId != m.MenuId)"
|
||||
TreeDefaultExpandAll>
|
||||
|
||||
</TreeSelect>
|
||||
|
||||
@ParentDeptId
|
||||
|
||||
@code{
|
||||
private string ParentDeptId = "1";
|
||||
|
||||
public class WebMenu
|
||||
{
|
||||
|
||||
public string MenuId { get; set; }
|
||||
|
||||
public string MenuHref { get; set; }
|
||||
|
||||
public string MenuName { get; set; }
|
||||
|
||||
public string Target { get; set; }
|
||||
|
||||
public string ParentId { get; set; }
|
||||
|
||||
public string Right { get; set; }
|
||||
|
||||
public int? OrderBy { get; set; } = 9999;
|
||||
|
||||
}
|
||||
|
||||
public static class LocalJsonData
|
||||
{
|
||||
private static readonly IList<WebMenu> _data;
|
||||
|
||||
static LocalJsonData()
|
||||
{
|
||||
_data = new List<WebMenu>() {
|
||||
new WebMenu(){ MenuId="1", MenuName="parent 1", ParentId="0", OrderBy=10},
|
||||
new WebMenu(){ MenuId="2", MenuName="parent 1-0", ParentId="1", OrderBy=10},
|
||||
new WebMenu(){ MenuId="3", MenuName="leaf1", ParentId="2", OrderBy=10},
|
||||
new WebMenu(){ MenuId="4", MenuName="leaf2", ParentId="0", OrderBy=10},
|
||||
new WebMenu(){ MenuId="5", MenuName="parent1-1", ParentId="0", OrderBy=10},
|
||||
new WebMenu(){ MenuId="6", MenuName="leaf3", ParentId="5", OrderBy=10}
|
||||
};
|
||||
}
|
||||
|
||||
public static IList<WebMenu> Data => _data;
|
||||
|
||||
|
||||
public static IList<WebMenu> GetMenusByParentId(string parentId)
|
||||
{
|
||||
return _data.Where(m => m.ParentId == parentId).ToList();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
<Space Direction="DirectionVHType.Vertical" Style="width: 100%">
|
||||
<SpaceItem>
|
||||
<TreeSelect TItem="string" Status="error" Style="width: 100%" Placeholder="Error" />
|
||||
</SpaceItem>
|
||||
<Space>
|
||||
<TreeSelect TItem="string" Status="warning" Style="width: 100%" Multiple Placeholder="Warning multiple" />
|
||||
</Space>
|
||||
|
||||
</Space>
|
||||
|
||||
@code {
|
||||
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
<TreeSelect TItem="string"
|
||||
EnableSearch
|
||||
Style="width:100%;"
|
||||
@bind-Value="value"
|
||||
DropdownStyle="max-height:400px;overflow:auto;"
|
||||
Placeholder="Please select"
|
||||
AllowClear
|
||||
Multiple
|
||||
SuffixIcon="icon"
|
||||
TreeDefaultExpandAll>
|
||||
<TreeNode TItem="string" Key="parent 1" Title="parent 1">
|
||||
<TreeNode TItem="string" Key="parent 1-0" Title="parent 1-0">
|
||||
<TreeNode TItem="string" Key="leaf1" Title="my leaf" />
|
||||
<TreeNode TItem="string" Key="leaf2" Title="your leaf" />
|
||||
</TreeNode>
|
||||
<TreeNode TItem="string" Key="parent 1-1" Title="parent 1-1">
|
||||
<TreeNode TItem="string" Key="sss">
|
||||
<TitleTemplate>
|
||||
<b style=" color: #08c;">sss</b>
|
||||
</TitleTemplate>
|
||||
</TreeNode>
|
||||
</TreeNode>
|
||||
</TreeNode>
|
||||
</TreeSelect>
|
||||
|
||||
@code {
|
||||
|
||||
private string value;
|
||||
private RenderFragment icon =@<Icon Type="smile"></Icon>;
|
||||
}
|
@ -1,54 +1,53 @@
|
||||
|
||||
|
||||
<TreeSelect TItem="Data"
|
||||
Style="width:100%;"
|
||||
DataSource="treeData"
|
||||
@bind-Value="@value"
|
||||
Placeholder="Please select"
|
||||
AllowClear
|
||||
Multiple
|
||||
TitleExpression="data => data.Title"
|
||||
KeyExpression="data => data.Value"
|
||||
ChildrenExpression="data => data.Children "
|
||||
IsLeafExpression="(menus, data) => data.Children == null "
|
||||
TreeDefaultExpandAll>
|
||||
<TreeSelect TItem="Data"
|
||||
Style="width:100%;"
|
||||
DataSource="treeData"
|
||||
@bind-Value="@value"
|
||||
Placeholder="Please select"
|
||||
AllowClear
|
||||
Multiple
|
||||
TreeDefaultExpandAll
|
||||
ChildrenExpression="node=>node.DataItem.Children"
|
||||
TitleExpression="node=>node.DataItem.Title"
|
||||
KeyExpression="node=>node.DataItem.Key"
|
||||
IsLeafExpression="node=>node.DataItem.Children==null">
|
||||
</TreeSelect>
|
||||
|
||||
|
||||
@code {
|
||||
private string value;
|
||||
private string value;
|
||||
|
||||
Data[] treeData = new Data[]
|
||||
{
|
||||
Data[] treeData = new Data[]
|
||||
{
|
||||
new()
|
||||
{
|
||||
Title = "Node1",
|
||||
Value = "0-0",
|
||||
Key = "0-0",
|
||||
Children = new Data[]
|
||||
{
|
||||
{
|
||||
new()
|
||||
{
|
||||
Title = "Child Node1",
|
||||
Value = "0-0-1",
|
||||
Key = "0-0-1",
|
||||
},
|
||||
new()
|
||||
{
|
||||
Title = "Child Node2",
|
||||
Value = "0-0-2",
|
||||
Key = "0-0-2",
|
||||
}
|
||||
}
|
||||
},
|
||||
new()
|
||||
{
|
||||
Title = "Node2",
|
||||
Value = "0-1",
|
||||
Key = "0-1",
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
public class Data
|
||||
{
|
||||
public string Value { get; set; }
|
||||
public string Title { get; set; }
|
||||
public Data[] Children { get; set; }
|
||||
}
|
||||
public class Data : ITreeData<Data>
|
||||
{
|
||||
public string Key { get; set; }
|
||||
public Data Value => this;
|
||||
public string Title { get; set; }
|
||||
public IEnumerable<Data> Children { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
<TreeSelect TItem="string"
|
||||
EnableSearch
|
||||
Style="width:100%;"
|
||||
@bind-Value="value"
|
||||
DropdownStyle="max-height:400px;overflow:auto;"
|
||||
Placeholder="Please select"
|
||||
AllowClear
|
||||
Multiple
|
||||
TreeLine
|
||||
TreeDefaultExpandAll>
|
||||
<TreeNode TItem="string" Key="parent 1" Title="parent 1">
|
||||
<TreeNode TItem="string" Key="parent 1-0" Title="parent 1-0">
|
||||
<TreeNode TItem="string" Key="leaf1" Title="my leaf" />
|
||||
<TreeNode TItem="string" Key="leaf2" Title="your leaf" />
|
||||
</TreeNode>
|
||||
<TreeNode TItem="string" Key="parent 1-1" Title="parent 1-1">
|
||||
<TreeNode TItem="string" Key="sss">
|
||||
<TitleTemplate>
|
||||
<b style=" color: #08c;">sss</b>
|
||||
</TitleTemplate>
|
||||
</TreeNode>
|
||||
</TreeNode>
|
||||
</TreeNode>
|
||||
</TreeSelect>
|
||||
|
||||
@code {
|
||||
|
||||
private string value;
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
---
|
||||
order: 5
|
||||
debug: true
|
||||
title:
|
||||
zh-CN: 异步加载
|
||||
en-US: Asynchronous loading
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
异步加载树节点。
|
||||
|
||||
## en-US
|
||||
|
||||
Asynchronous loading tree node.
|
||||
|
||||
```tsx
|
||||
import React, { useState } from 'react';
|
||||
import { TreeSelect } from 'antd';
|
||||
import type { DefaultOptionType } from 'antd/es/select';
|
||||
import type { TreeSelectProps } from 'antd';
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [value, setValue] = useState<string>();
|
||||
const [treeData, setTreeData] = useState<Omit<DefaultOptionType, 'label'>[]>([
|
||||
{ id: 1, pId: 0, value: '1', title: 'Expand to load' },
|
||||
{ id: 2, pId: 0, value: '2', title: 'Expand to load' },
|
||||
{ id: 3, pId: 0, value: '3', title: 'Tree Node', isLeaf: true },
|
||||
]);
|
||||
|
||||
const genTreeNode = (parentId: number, isLeaf = false) => {
|
||||
const random = Math.random().toString(36).substring(2, 6);
|
||||
return {
|
||||
id: random,
|
||||
pId: parentId,
|
||||
value: random,
|
||||
title: isLeaf ? 'Tree Node' : 'Expand to load',
|
||||
isLeaf,
|
||||
};
|
||||
};
|
||||
|
||||
const onLoadData: TreeSelectProps['loadData'] = ({ id }) =>
|
||||
new Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
setTreeData(
|
||||
treeData.concat([genTreeNode(id, false), genTreeNode(id, true), genTreeNode(id, true)]),
|
||||
);
|
||||
resolve(undefined);
|
||||
}, 300);
|
||||
});
|
||||
|
||||
const onChange = (newValue: string) => {
|
||||
console.log(newValue);
|
||||
setValue(newValue);
|
||||
};
|
||||
|
||||
return (
|
||||
<TreeSelect
|
||||
treeDataSimpleMode
|
||||
style={{ width: '100%' }}
|
||||
value={value}
|
||||
dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
|
||||
placeholder="Please select"
|
||||
onChange={onChange}
|
||||
loadData={onLoadData}
|
||||
treeData={treeData}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
||||
```
|
@ -7,8 +7,48 @@ title:
|
||||
|
||||
## zh-CN
|
||||
|
||||
最简单的用法,展示动态下拉树功能。
|
||||
最简单的用法。
|
||||
|
||||
## en-US
|
||||
|
||||
The most basic usage, tell you how to use tree-select etc.
|
||||
The most basic usage.
|
||||
|
||||
```tsx
|
||||
import React, { useState } from 'react';
|
||||
import { TreeSelect } from 'antd';
|
||||
|
||||
const { TreeNode } = TreeSelect;
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [value, setValue] = useState<string | undefined>(undefined);
|
||||
|
||||
const onChange = (newValue: string) => {
|
||||
setValue(newValue);
|
||||
};
|
||||
|
||||
return (
|
||||
<TreeSelect
|
||||
showSearch
|
||||
style={{ width: '100%' }}
|
||||
value={value}
|
||||
dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
|
||||
placeholder="Please select"
|
||||
allowClear
|
||||
treeDefaultExpandAll
|
||||
onChange={onChange}
|
||||
>
|
||||
<TreeNode value="parent 1" title="parent 1">
|
||||
<TreeNode value="parent 1-0" title="parent 1-0">
|
||||
<TreeNode value="leaf1" title="leaf1" />
|
||||
<TreeNode value="leaf2" title="leaf2" />
|
||||
</TreeNode>
|
||||
<TreeNode value="parent 1-1" title="parent 1-1">
|
||||
<TreeNode value="leaf3" title={<b style={{ color: '#08c' }}>leaf3</b>} />
|
||||
</TreeNode>
|
||||
</TreeNode>
|
||||
</TreeSelect>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
||||
```
|
||||
|
@ -0,0 +1,84 @@
|
||||
---
|
||||
order: 3
|
||||
debug: true
|
||||
title:
|
||||
zh-CN: 可勾选
|
||||
en-US: Checkable
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
使用勾选框实现多选功能。
|
||||
|
||||
## en-US
|
||||
|
||||
Multiple and checkable.
|
||||
|
||||
```tsx
|
||||
import React, { useState } from 'react';
|
||||
import { TreeSelect } from 'antd';
|
||||
|
||||
const { SHOW_PARENT } = TreeSelect;
|
||||
|
||||
const treeData = [
|
||||
{
|
||||
title: 'Node1',
|
||||
value: '0-0',
|
||||
key: '0-0',
|
||||
children: [
|
||||
{
|
||||
title: 'Child Node1',
|
||||
value: '0-0-0',
|
||||
key: '0-0-0',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Node2',
|
||||
value: '0-1',
|
||||
key: '0-1',
|
||||
children: [
|
||||
{
|
||||
title: 'Child Node3',
|
||||
value: '0-1-0',
|
||||
key: '0-1-0',
|
||||
},
|
||||
{
|
||||
title: 'Child Node4',
|
||||
value: '0-1-1',
|
||||
key: '0-1-1',
|
||||
},
|
||||
{
|
||||
title: 'Child Node5',
|
||||
value: '0-1-2',
|
||||
key: '0-1-2',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [value, setValue] = useState(['0-0-0']);
|
||||
|
||||
const onChange = (newValue: string[]) => {
|
||||
console.log('onChange ', value);
|
||||
setValue(newValue);
|
||||
};
|
||||
|
||||
const tProps = {
|
||||
treeData,
|
||||
value,
|
||||
onChange,
|
||||
treeCheckable: true,
|
||||
showCheckedStrategy: SHOW_PARENT,
|
||||
placeholder: 'Please select',
|
||||
style: {
|
||||
width: '100%',
|
||||
},
|
||||
};
|
||||
|
||||
return <TreeSelect {...tProps} />;
|
||||
};
|
||||
|
||||
export default App;
|
||||
```
|
@ -2,13 +2,55 @@
|
||||
order: 1
|
||||
title:
|
||||
zh-CN: 多选
|
||||
en-US: multiple
|
||||
en-US: Multiple Selection
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
最简单的用法,展示多选功能。其中RootValue用于筛选DataSources中第一级的节点。
|
||||
多选的树选择。
|
||||
|
||||
## en-US
|
||||
|
||||
The most basic usage, tell you how to use tree-select multiple selected etc.
|
||||
Multiple selection usage.
|
||||
|
||||
```tsx
|
||||
import React, { useState } from 'react';
|
||||
import { TreeSelect } from 'antd';
|
||||
|
||||
const { TreeNode } = TreeSelect;
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [value, setValue] = useState<string>();
|
||||
|
||||
const onChange = (newValue: string) => {
|
||||
console.log(newValue);
|
||||
setValue(newValue);
|
||||
};
|
||||
|
||||
return (
|
||||
<TreeSelect
|
||||
showSearch
|
||||
style={{ width: '100%' }}
|
||||
value={value}
|
||||
dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
|
||||
placeholder="Please select"
|
||||
allowClear
|
||||
multiple
|
||||
treeDefaultExpandAll
|
||||
onChange={onChange}
|
||||
>
|
||||
<TreeNode value="parent 1" title="parent 1">
|
||||
<TreeNode value="parent 1-0" title="parent 1-0">
|
||||
<TreeNode value="leaf1" title="my leaf" />
|
||||
<TreeNode value="leaf2" title="your leaf" />
|
||||
</TreeNode>
|
||||
<TreeNode value="parent 1-1" title="parent 1-1">
|
||||
<TreeNode value="sss" title={<b style={{ color: '#08c' }}>sss</b>} />
|
||||
</TreeNode>
|
||||
</TreeNode>
|
||||
</TreeSelect>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
||||
```
|
||||
|
@ -0,0 +1,67 @@
|
||||
---
|
||||
order: 8
|
||||
debug: true
|
||||
title:
|
||||
zh-CN: 弹出位置
|
||||
en-US: Placement
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
可以通过 `placement` 手动指定弹出的位置。
|
||||
|
||||
## en-US
|
||||
|
||||
You can manually specify the position of the popup via `placement`.
|
||||
|
||||
```tsx
|
||||
import React, { useState } from 'react';
|
||||
import { TreeSelect, Radio } from 'antd';
|
||||
import type { SelectCommonPlacement } from 'antd/es/_util/motion';
|
||||
import type { RadioChangeEvent } from 'antd';
|
||||
|
||||
const { TreeNode } = TreeSelect;
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [placement, SetPlacement] = useState<SelectCommonPlacement>('topLeft');
|
||||
|
||||
const placementChange = (e: RadioChangeEvent) => {
|
||||
SetPlacement(e.target.value);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Radio.Group value={placement} onChange={placementChange}>
|
||||
<Radio.Button value="topLeft">topLeft</Radio.Button>
|
||||
<Radio.Button value="topRight">topRight</Radio.Button>
|
||||
<Radio.Button value="bottomLeft">bottomLeft</Radio.Button>
|
||||
<Radio.Button value="bottomRight">bottomRight</Radio.Button>
|
||||
</Radio.Group>
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<TreeSelect
|
||||
showSearch
|
||||
dropdownStyle={{ maxHeight: 400, overflow: 'auto', minWidth: 300 }}
|
||||
placeholder="Please select"
|
||||
dropdownMatchSelectWidth={false}
|
||||
placement={placement}
|
||||
allowClear
|
||||
treeDefaultExpandAll
|
||||
>
|
||||
<TreeNode value="parent 1" title="parent 1">
|
||||
<TreeNode value="parent 1-0" title="parent 1-0">
|
||||
<TreeNode value="leaf1" title="leaf1" />
|
||||
<TreeNode value="leaf2" title="leaf2" />
|
||||
</TreeNode>
|
||||
<TreeNode value="parent 1-1" title="parent 1-1">
|
||||
<TreeNode value="leaf3" title={<b style={{ color: '#08c' }}>leaf3</b>} />
|
||||
</TreeNode>
|
||||
</TreeNode>
|
||||
</TreeSelect>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
||||
```
|
@ -1,14 +0,0 @@
|
||||
---
|
||||
order: 1
|
||||
title:
|
||||
zh-CN: 赋值
|
||||
en-US: setValue
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
展示设置选中节点,以及默认值功能。
|
||||
|
||||
## en-US
|
||||
|
||||
The most basic usage, tell you how to use tree-select multiple selected etc.
|
@ -0,0 +1,34 @@
|
||||
---
|
||||
order: 9
|
||||
debug: true
|
||||
title:
|
||||
zh-CN: 自定义状态
|
||||
en-US: Status
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
使用 `status` 为 TreeSelect 添加状态,可选 `error` 或者 `warning`。
|
||||
|
||||
## en-US
|
||||
|
||||
Add status to TreeSelect with `status`, which could be `error` or `warning`.
|
||||
|
||||
```tsx
|
||||
import React from 'react';
|
||||
import { TreeSelect, Space } from 'antd';
|
||||
|
||||
const App: React.FC = () => (
|
||||
<Space direction="vertical" style={{ width: '100%' }}>
|
||||
<TreeSelect status="error" style={{ width: '100%' }} placeholder="Error" />
|
||||
<TreeSelect
|
||||
status="warning"
|
||||
style={{ width: '100%' }}
|
||||
multiple
|
||||
placeholder="Warning multiple"
|
||||
/>
|
||||
</Space>
|
||||
);
|
||||
|
||||
export default App;
|
||||
```
|
@ -0,0 +1,59 @@
|
||||
---
|
||||
order: 12
|
||||
debug: true
|
||||
title:
|
||||
zh-CN: 后缀图标
|
||||
en-US: Suffix
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
最简单的用法。
|
||||
|
||||
## en-US
|
||||
|
||||
The most basic usage.
|
||||
|
||||
```tsx
|
||||
import React, { useState } from 'react';
|
||||
import { TreeSelect } from 'antd';
|
||||
import { SmileOutlined } from '@ant-design/icons';
|
||||
|
||||
const { TreeNode } = TreeSelect;
|
||||
const icon = <SmileOutlined />;
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [value, setValue] = useState<string>();
|
||||
|
||||
const onChange = (newValue: string) => {
|
||||
console.log(newValue);
|
||||
setValue(newValue);
|
||||
};
|
||||
|
||||
return (
|
||||
<TreeSelect
|
||||
showSearch
|
||||
suffixIcon={icon}
|
||||
style={{ width: '100%' }}
|
||||
value={value}
|
||||
dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
|
||||
placeholder="Please select"
|
||||
allowClear
|
||||
treeDefaultExpandAll
|
||||
onChange={onChange}
|
||||
>
|
||||
<TreeNode value="parent 1" title="parent 1">
|
||||
<TreeNode value="parent 1-0" title="parent 1-0">
|
||||
<TreeNode value="leaf1" title="my leaf" />
|
||||
<TreeNode value="leaf2" title="your leaf" />
|
||||
</TreeNode>
|
||||
<TreeNode value="parent 1-1" title="parent 1-1">
|
||||
<TreeNode value="sss" title={<b style={{ color: '#08c' }}>sss</b>} />
|
||||
</TreeNode>
|
||||
</TreeNode>
|
||||
</TreeSelect>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
||||
```
|
@ -7,8 +7,8 @@ title:
|
||||
|
||||
## zh-CN
|
||||
|
||||
使用 `treeData` 把 JSON 数据直接生成树结构。
|
||||
使用 `DataSource` 把 IEnumerable<T> 数据直接生成树结构。
|
||||
|
||||
## en-US
|
||||
|
||||
The tree structure can be populated using `treeData` property. This is a quick and easy way to provide the tree content.
|
||||
The tree structure can be populated using `DataSource` property. This is a quick and easy way to provide the tree content.
|
||||
|
@ -0,0 +1,58 @@
|
||||
---
|
||||
order: 6
|
||||
debug: true
|
||||
title:
|
||||
zh-CN: 线性样式
|
||||
en-US: Show Tree Line
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
通过 `treeLine` 配置线性样式。
|
||||
|
||||
## en-US
|
||||
|
||||
Use `treeLine` to show the line style.
|
||||
|
||||
```tsx
|
||||
import React, { useState } from 'react';
|
||||
import { TreeSelect, Switch, Space } from 'antd';
|
||||
|
||||
const { TreeNode } = TreeSelect;
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [treeLine, setTreeLine] = useState(true);
|
||||
const [showLeafIcon, setShowLeafIcon] = useState(false);
|
||||
|
||||
return (
|
||||
<Space direction="vertical">
|
||||
<Switch
|
||||
checkedChildren="treeLine"
|
||||
unCheckedChildren="treeLine"
|
||||
checked={treeLine}
|
||||
onChange={() => setTreeLine(!treeLine)}
|
||||
/>
|
||||
<Switch
|
||||
disabled={!treeLine}
|
||||
checkedChildren="showLeafIcon"
|
||||
unCheckedChildren="showLeafIcon"
|
||||
checked={showLeafIcon}
|
||||
onChange={() => setShowLeafIcon(!showLeafIcon)}
|
||||
/>
|
||||
<TreeSelect treeLine={treeLine && { showLeafIcon }} style={{ width: 300 }}>
|
||||
<TreeNode value="parent 1" title="parent 1">
|
||||
<TreeNode value="parent 1-0" title="parent 1-0">
|
||||
<TreeNode value="leaf1" title="my leaf" />
|
||||
<TreeNode value="leaf2" title="your leaf" />
|
||||
</TreeNode>
|
||||
<TreeNode value="parent 1-1" title="parent 1-1">
|
||||
<TreeNode value="sss" title="sss" />
|
||||
</TreeNode>
|
||||
</TreeNode>
|
||||
</TreeSelect>
|
||||
</Space>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
||||
```
|
@ -7,7 +7,7 @@
|
||||
@Title
|
||||
</div>
|
||||
<div class="code-box-description">
|
||||
<Markdown>@Description</Markdown>
|
||||
@Description
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
@ -1,25 +1,44 @@
|
||||
@using System.Text.RegularExpressions
|
||||
@inherits AntDesignTestBase
|
||||
@inherits AntDesignTestBase
|
||||
@code {
|
||||
|
||||
[Fact]
|
||||
public void InputNumber_formatter_parser_change_value()
|
||||
{
|
||||
//Arrange
|
||||
[Fact]
|
||||
public void InputNumber_formatter_parser_change_value()
|
||||
{
|
||||
//Arrange
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
JSInterop.SetupVoid(JSInteropConstants.Focus, _ => true).SetVoidResult();
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
AntDesign.InputNumber<double>? input = null;
|
||||
Func<double, string> formatter = v => "$ " + v.ToString("n0");
|
||||
Func<string, string> parser = v => Regex.Replace(v, @"\$\s?|(,*)", "");
|
||||
AntDesign.InputNumber<double>? input = null;
|
||||
Func<double, string> formatter = v => "$ " + v.ToString("n0");
|
||||
Func<string, string> parser = v => Regex.Replace(v, @"\$\s?|(,*)", "");
|
||||
|
||||
var cut = Render<AntDesign.InputNumber<double>>(
|
||||
@<AntDesign.InputNumber @ref="@input" Formatter="formatter" Parser="parser" DefaultValue="1000d"/>
|
||||
);
|
||||
//Act
|
||||
cut.Find("input").Change("$ 10");
|
||||
//Assert
|
||||
cut.Instance.Value.Should().Be(10);
|
||||
}
|
||||
var cut = Render<AntDesign.InputNumber<double>>(
|
||||
@<AntDesign.InputNumber @ref="@input" Formatter="formatter" Parser="parser" DefaultValue="1000d" />
|
||||
);
|
||||
//Act
|
||||
cut.Find("input").Change("$ 10");
|
||||
//Assert
|
||||
cut.Instance.Value.Should().Be(10);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InputNumber_value_display_check_when_step_notation_is_scientific()
|
||||
{
|
||||
//Arrange
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
JSInterop.SetupVoid(JSInteropConstants.Focus, _ => true).SetVoidResult();
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
AntDesign.InputNumber<double>? input = null;
|
||||
|
||||
var cut = Render<AntDesign.InputNumber<double>>(
|
||||
@<AntDesign.InputNumber @ref="@input" Step="0.00001" />
|
||||
);
|
||||
//Act
|
||||
var inputElement = cut.Find("input");
|
||||
inputElement.KeyDown(Key.Up);
|
||||
//Assert
|
||||
string decimalSeparator = System.Globalization.CultureInfo.CurrentCulture.NumberFormat.CurrencyDecimalSeparator;
|
||||
inputElement.GetAttribute("value").Should().Be($"0{decimalSeparator}00001");
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user