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.
|
- 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
|
### 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
|
### 0.10.7
|
||||||
|
|
||||||
`2022-05-22`
|
`2022-05-22`
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://yangshunjie.com/ant-design-blazor/">
|
<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>
|
</a>
|
||||||
</p>
|
</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 混合客户端环境中。
|
- 可直接运行在 [.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 标准的环境上。
|
- 可直接运行在 [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 |
|
| Edge 16 / IE 11† | 522 | 57 | 11 | 44 | Chromium 57 |
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://yangshunjie.com/ant-design-blazor/">
|
<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>
|
</a>
|
||||||
</p>
|
</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 [.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.
|
- 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 |
|
| Edge 16 / IE 11† | 522 | 57 | 11 | 44 | Chromium 57 |
|
||||||
|
|
||||||
@ -166,7 +166,7 @@ Options for the template:
|
|||||||
- Clone to local development
|
- Clone to local development
|
||||||
|
|
||||||
```bash
|
```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
|
$ cd ant-design-blazor
|
||||||
$ npm install
|
$ npm install
|
||||||
$ dotnet build ./site/AntDesign.Docs.Build/AntDesign.Docs.Build.csproj
|
$ 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>
|
<details>
|
||||||
<summary>Scan QR Code with DingTalk</summary>
|
<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>
|
</details>
|
||||||
|
|
||||||
## Code of Conduct
|
## Code of Conduct
|
||||||
|
@ -121,6 +121,7 @@ namespace AntDesign
|
|||||||
{
|
{
|
||||||
base.OnValueChange(value);
|
base.OnValueChange(value);
|
||||||
RefreshNodeValue(value);
|
RefreshNodeValue(value);
|
||||||
|
RefreshDisplayText();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -178,13 +179,16 @@ namespace AntDesign
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 清除已选择项
|
/// 清除已选择项
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void ClearSelected()
|
private async Task ClearSelected()
|
||||||
{
|
{
|
||||||
_selectedNodes.Clear();
|
_selectedNodes.Clear();
|
||||||
_hoverSelectedNodes.Clear();
|
_hoverSelectedNodes.Clear();
|
||||||
_displayText = string.Empty;
|
_displayText = string.Empty;
|
||||||
SetValue(string.Empty);
|
SetValue(string.Empty);
|
||||||
_dropdownOpened = false;
|
_dropdownOpened = false;
|
||||||
|
|
||||||
|
_searchValue = string.Empty;
|
||||||
|
await this.FocusAsync(_inputRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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]
|
[Parameter]
|
||||||
public bool Closable { get; set; } = true;
|
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]
|
[Parameter]
|
||||||
public bool MaskClosable { get; set; } = true;
|
public bool MaskClosable { get; set; } = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>
|
||||||
|
/// 是否显示蒙层
|
||||||
|
/// </para>
|
||||||
|
/// <para>
|
||||||
|
/// Whether to show mask or not.
|
||||||
|
/// </para>
|
||||||
|
/// </summary>
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public bool Mask { get; set; } = true;
|
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]
|
[Parameter]
|
||||||
public bool Keyboard { get; set; } = true;
|
public bool Keyboard { get; set; } = true;
|
||||||
|
|
||||||
@ -43,6 +86,14 @@ namespace AntDesign
|
|||||||
|
|
||||||
private OneOf<RenderFragment, string> _title;
|
private OneOf<RenderFragment, string> _title;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>
|
||||||
|
/// 标题
|
||||||
|
/// </para>
|
||||||
|
/// <para>
|
||||||
|
/// The title for Drawer.
|
||||||
|
/// </para>
|
||||||
|
/// </summary>
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public OneOf<RenderFragment, string> Title
|
public OneOf<RenderFragment, string> Title
|
||||||
{
|
{
|
||||||
@ -63,20 +114,68 @@ namespace AntDesign
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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>
|
/// </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;
|
/// <summary>
|
||||||
|
/// <para>
|
||||||
[Parameter] public int Height { get; set; } = 256;
|
/// 高度,仅当 <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]
|
[Parameter]
|
||||||
public int ZIndex
|
public int ZIndex
|
||||||
{
|
{
|
||||||
@ -93,10 +192,36 @@ namespace AntDesign
|
|||||||
|
|
||||||
private string InnerZIndexStyle => (_status.IsOpen() || _status == ComponentStatus.Closing) ? _zIndexStyle : "z-index:-9999;";
|
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]
|
[Parameter]
|
||||||
public bool Visible
|
public bool Visible
|
||||||
{
|
{
|
||||||
@ -115,10 +240,30 @@ namespace AntDesign
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Parameter] public EventCallback OnClose { get; set; }
|
/// <summary>
|
||||||
[Parameter] public RenderFragment Handler { get; set; }
|
/// <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;
|
private OneOf<RenderFragment, string> _content;
|
||||||
|
|
||||||
@ -126,6 +271,8 @@ namespace AntDesign
|
|||||||
|
|
||||||
private RenderFragment ContentTemplate { get; set; }
|
private RenderFragment ContentTemplate { get; set; }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
private ComponentStatus _status;
|
private ComponentStatus _status;
|
||||||
private bool _hasInvokeClosed;
|
private bool _hasInvokeClosed;
|
||||||
private bool _isOpen = default;
|
private bool _isOpen = default;
|
||||||
@ -257,6 +404,12 @@ namespace AntDesign
|
|||||||
case ComponentStatus.Opening:
|
case ComponentStatus.Opening:
|
||||||
{
|
{
|
||||||
_status = ComponentStatus.Opened;
|
_status = ComponentStatus.Opened;
|
||||||
|
|
||||||
|
if (OnOpen != null)
|
||||||
|
{
|
||||||
|
await OnOpen.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
_hasInvokeClosed = false;
|
_hasInvokeClosed = false;
|
||||||
if (string.IsNullOrWhiteSpace(Style))
|
if (string.IsNullOrWhiteSpace(Style))
|
||||||
{
|
{
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
OffsetX="@drawerConfig.OffsetX"
|
OffsetX="@drawerConfig.OffsetX"
|
||||||
OffsetY="@drawerConfig.OffsetY"
|
OffsetY="@drawerConfig.OffsetY"
|
||||||
Visible="@drawerConfig.Visible"
|
Visible="@drawerConfig.Visible"
|
||||||
|
OnOpen="@drawerRef.OnOpen"
|
||||||
OnClose="@drawerRef.CloseAsync">
|
OnClose="@drawerRef.CloseAsync">
|
||||||
@drawerConfig.ChildContent
|
@drawerConfig.ChildContent
|
||||||
</Drawer>
|
</Drawer>
|
||||||
|
@ -50,8 +50,6 @@ namespace AntDesign
|
|||||||
public override async Task OpenAsync()
|
public override async Task OpenAsync()
|
||||||
{
|
{
|
||||||
await _service.OpenAsync(this);
|
await _service.OpenAsync(this);
|
||||||
if (OnOpen != null)
|
|
||||||
await OnOpen.Invoke();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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;
|
_step = value;
|
||||||
NumberFormatInfo nfi = CultureInfo.NumberFormat;
|
NumberFormatInfo nfi = CultureInfo.NumberFormat;
|
||||||
var stepStr = _step.ToString();
|
var stepStr = Convert.ToDecimal(_step).ToString(nfi);
|
||||||
if (string.IsNullOrEmpty(_format))
|
if (string.IsNullOrEmpty(_format))
|
||||||
{
|
{
|
||||||
_format = string.Join('.', stepStr.Split(nfi.NumberDecimalSeparator).Select(n => new string('0', n.Length)));
|
_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())
|
if (CurrentValueAsString != args?.Value?.ToString())
|
||||||
{
|
{
|
||||||
|
CurrentValueAsString = args?.Value?.ToString();
|
||||||
if (OnChange.HasDelegate)
|
if (OnChange.HasDelegate)
|
||||||
{
|
{
|
||||||
await OnChange.InvokeAsync(Value);
|
await OnChange.InvokeAsync(Value);
|
||||||
@ -636,11 +637,12 @@ namespace AntDesign
|
|||||||
}
|
}
|
||||||
|
|
||||||
// onchange 和 onblur 事件会导致点击 OnSearch 按钮时不触发 Click 事件,暂时取消这两个事件
|
// onchange 和 onblur 事件会导致点击 OnSearch 按钮时不触发 Click 事件,暂时取消这两个事件
|
||||||
if (!IgnoreOnChangeAndBlur)
|
//2022-8-3 去掉if后,search也能正常工作
|
||||||
{
|
//if (!IgnoreOnChangeAndBlur)
|
||||||
|
//{
|
||||||
builder.AddAttribute(70, "onchange", CallbackFactory.Create(this, OnChangeAsync));
|
builder.AddAttribute(70, "onchange", CallbackFactory.Create(this, OnChangeAsync));
|
||||||
builder.AddAttribute(71, "onblur", CallbackFactory.Create(this, OnBlurAsync));
|
builder.AddAttribute(71, "onblur", CallbackFactory.Create(this, OnBlurAsync));
|
||||||
}
|
//}
|
||||||
|
|
||||||
builder.AddAttribute(72, "onkeypress", CallbackFactory.Create(this, OnKeyPressAsync));
|
builder.AddAttribute(72, "onkeypress", CallbackFactory.Create(this, OnKeyPressAsync));
|
||||||
builder.AddAttribute(73, "onkeydown", CallbackFactory.Create(this, OnkeyDownAsync));
|
builder.AddAttribute(73, "onkeydown", CallbackFactory.Create(this, OnkeyDownAsync));
|
||||||
|
@ -44,6 +44,9 @@ namespace AntDesign
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public EventCallback<bool> CollapsedChanged { get; set; }
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public EventCallback<bool> OnCollapse { get; set; }
|
public EventCallback<bool> OnCollapse { get; set; }
|
||||||
|
|
||||||
@ -132,6 +135,11 @@ namespace AntDesign
|
|||||||
{
|
{
|
||||||
OnCollapse.InvokeAsync(_isCollapsed);
|
OnCollapse.InvokeAsync(_isCollapsed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (CollapsedChanged.HasDelegate)
|
||||||
|
{
|
||||||
|
CollapsedChanged.InvokeAsync(_isCollapsed);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OptimizeSize(decimal windowWidth)
|
private void OptimizeSize(decimal windowWidth)
|
||||||
@ -165,6 +173,11 @@ namespace AntDesign
|
|||||||
{
|
{
|
||||||
OnCollapse.InvokeAsync(_isCollapsed);
|
OnCollapse.InvokeAsync(_isCollapsed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (CollapsedChanged.HasDelegate)
|
||||||
|
{
|
||||||
|
CollapsedChanged.InvokeAsync(_isCollapsed);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
|
@ -312,6 +312,21 @@ namespace AntDesign
|
|||||||
return style;
|
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>
|
/// <summary>
|
||||||
/// Hide Dialog through animation
|
/// Hide Dialog through animation
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -102,6 +102,7 @@ namespace AntDesign
|
|||||||
_hideDone = false;
|
_hideDone = false;
|
||||||
_hasDestroy = false;
|
_hasDestroy = false;
|
||||||
|
|
||||||
|
await _dialog.CleanShowAnimationAsync();
|
||||||
if (OnAfterShow.HasDelegate)
|
if (OnAfterShow.HasDelegate)
|
||||||
{
|
{
|
||||||
await OnAfterShow.InvokeAsync(null);
|
await OnAfterShow.InvokeAsync(null);
|
||||||
|
@ -6,7 +6,7 @@ namespace AntDesign
|
|||||||
{
|
{
|
||||||
public sealed class ModalAnimation
|
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 ModalLeave = " ant-zoom-leave ant-zoom-leave-active ant-zoom";
|
||||||
|
|
||||||
public const string MaskEnter = " ant-fade-enter ant-fade-enter-active ant-fade";
|
public const string MaskEnter = " ant-fade-enter ant-fade-enter-active ant-fade";
|
||||||
|
@ -209,6 +209,7 @@
|
|||||||
Page="@key"
|
Page="@key"
|
||||||
Active="@(_current == key)"
|
Active="@(_current == key)"
|
||||||
ShowTitle="ShowTitle"
|
ShowTitle="ShowTitle"
|
||||||
|
Class=""
|
||||||
ItemRender="@ItemRender"/>
|
ItemRender="@ItemRender"/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -239,7 +240,7 @@
|
|||||||
Page="@right"
|
Page="@right"
|
||||||
Active="@(_current == right)"
|
Active="@(_current == right)"
|
||||||
ShowTitle="ShowTitle"
|
ShowTitle="ShowTitle"
|
||||||
Class="@($"{PrefixCls}-item-after-jump-prev")"
|
Class="@($"{PrefixCls}-item-before-jump-next")"
|
||||||
ItemRender="@ItemRender"/>;
|
ItemRender="@ItemRender"/>;
|
||||||
pagerList.AddLast(jumpNext);
|
pagerList.AddLast(jumpNext);
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,6 @@
|
|||||||
var prefixCls = $"{RootPrefixCls}-item";
|
var prefixCls = $"{RootPrefixCls}-item";
|
||||||
ClassMapper.Add(prefixCls).Add($"{prefixCls}-{Page}")
|
ClassMapper.Add(prefixCls).Add($"{prefixCls}-{Page}")
|
||||||
.If($"{prefixCls}-active", () => Active)
|
.If($"{prefixCls}-active", () => Active)
|
||||||
.If(Class, () => !string.IsNullOrWhiteSpace(Class))
|
|
||||||
.If($"{prefixCls}-disabled", () => Page == 0);
|
.If($"{prefixCls}-disabled", () => Page == 0);
|
||||||
|
|
||||||
base.OnInitialized();
|
base.OnInitialized();
|
||||||
|
@ -737,8 +737,8 @@ namespace AntDesign
|
|||||||
{
|
{
|
||||||
if (!updateSelectOption.IsSelected)
|
if (!updateSelectOption.IsSelected)
|
||||||
{
|
{
|
||||||
updateSelectOption.IsSelected = isSelected;
|
//updateSelectOption.IsSelected = isSelected;
|
||||||
SelectedOptionItems.Add(updateSelectOption);
|
//SelectedOptionItems.Add(updateSelectOption);
|
||||||
}
|
}
|
||||||
processedSelectedCount--;
|
processedSelectedCount--;
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ using Microsoft.AspNetCore.Components;
|
|||||||
using Microsoft.AspNetCore.Components.Web;
|
using Microsoft.AspNetCore.Components.Web;
|
||||||
using OneOf;
|
using OneOf;
|
||||||
|
|
||||||
#endregion
|
#endregion using block
|
||||||
|
|
||||||
namespace AntDesign
|
namespace AntDesign
|
||||||
{
|
{
|
||||||
@ -34,7 +34,6 @@ namespace AntDesign
|
|||||||
internal ElementReference _inputRef;
|
internal ElementReference _inputRef;
|
||||||
protected bool _isInitialized;
|
protected bool _isInitialized;
|
||||||
|
|
||||||
|
|
||||||
protected bool _isPrimitive;
|
protected bool _isPrimitive;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -50,7 +49,6 @@ namespace AntDesign
|
|||||||
protected string _prevSearchValue = string.Empty;
|
protected string _prevSearchValue = string.Empty;
|
||||||
protected string _searchValue = string.Empty;
|
protected string _searchValue = string.Empty;
|
||||||
|
|
||||||
|
|
||||||
protected SelectContent<TItemValue, TItem> _selectContent;
|
protected SelectContent<TItemValue, TItem> _selectContent;
|
||||||
|
|
||||||
protected IEnumerable<TItemValue> _selectedValues;
|
protected IEnumerable<TItemValue> _selectedValues;
|
||||||
@ -58,77 +56,93 @@ namespace AntDesign
|
|||||||
protected Action<TItem, string> _setLabel;
|
protected Action<TItem, string> _setLabel;
|
||||||
|
|
||||||
protected Action<TItem, TItemValue> _setValue;
|
protected Action<TItem, TItemValue> _setValue;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Show clear button. Has no effect if <see cref="AntInputComponentBase{TValue}.Value"/> type default
|
/// 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}"/>,
|
/// is also in the list of <see cref="SelectOption{TItemValue, TItem}"/>,
|
||||||
/// unless used with <see cref="ValueOnClear"/>.
|
/// unless used with <see cref="ValueOnClear"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter] public bool AllowClear { get; set; }
|
[Parameter] public bool AllowClear { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether the current search will be cleared on selecting an item.
|
/// Whether the current search will be cleared on selecting an item.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter] public bool AutoClearSearchValue { get; set; } = true;
|
[Parameter] public bool AutoClearSearchValue { get; set; } = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether the Select component is disabled.
|
/// Whether the Select component is disabled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter] public bool Disabled { get; set; }
|
[Parameter] public bool Disabled { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Set mode of Select - default | multiple | tags
|
/// Set mode of Select - default | multiple | tags
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter] public string Mode { get; set; } = "default";
|
[Parameter] public string Mode { get; set; } = "default";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates whether the search function is active or not. Always true for mode tags.
|
/// Indicates whether the search function is active or not. Always true for mode tags.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter] public bool EnableSearch { get; set; }
|
[Parameter] public bool EnableSearch { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <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
|
/// typing for a predetermined amount of time
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public int SearchDebounceMilliseconds { get; set; }
|
public int SearchDebounceMilliseconds { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Show loading indicator. You have to write the loading logic on your own.
|
/// Show loading indicator. You have to write the loading logic on your own.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter] public bool Loading { get; set; }
|
[Parameter] public bool Loading { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Controlled open state of dropdown.
|
/// Controlled open state of dropdown.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter] public bool Open { get; set; }
|
[Parameter] public bool Open { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Placeholder of select.
|
/// Placeholder of select.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter] public string Placeholder { get; set; }
|
[Parameter] public string Placeholder { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called when focus.
|
/// Called when focus.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter] public EventCallback OnFocus { get; set; }
|
[Parameter] public EventCallback OnFocus { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The name of the property to be used as a group indicator.
|
/// The name of the property to be used as a group indicator.
|
||||||
/// If the value is set, the entries are displayed in groups.
|
/// If the value is set, the entries are displayed in groups.
|
||||||
/// Use additional SortByGroup and SortByLabel.
|
/// Use additional SortByGroup and SortByLabel.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter] public SortDirection SortByGroup { get; set; } = SortDirection.None;
|
[Parameter] public SortDirection SortByGroup { get; set; } = SortDirection.None;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sort items by label value. None | Ascending | Descending
|
/// Sort items by label value. None | Ascending | Descending
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter] public SortDirection SortByLabel { get; set; } = SortDirection.None;
|
[Parameter] public SortDirection SortByLabel { get; set; } = SortDirection.None;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Hides the selected items when they are selected.
|
/// Hides the selected items when they are selected.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter] public bool HideSelected { get; set; }
|
[Parameter] public bool HideSelected { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Used for the two-way binding.
|
/// Used for the two-way binding.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter] public override EventCallback<TItemValue> ValueChanged { get; set; }
|
[Parameter] public override EventCallback<TItemValue> ValueChanged { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Used for the two-way binding.
|
/// Used for the two-way binding.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter] public EventCallback<IEnumerable<TItemValue>> ValuesChanged { get; set; }
|
[Parameter] public EventCallback<IEnumerable<TItemValue>> ValuesChanged { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The custom suffix icon.
|
/// The custom suffix icon.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter] public RenderFragment SuffixIcon { get; set; }
|
[Parameter] public RenderFragment SuffixIcon { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The custom prefix icon.
|
/// The custom prefix icon.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -136,6 +150,7 @@ namespace AntDesign
|
|||||||
|
|
||||||
protected IEnumerable<TItemValue> _defaultValues;
|
protected IEnumerable<TItemValue> _defaultValues;
|
||||||
protected bool _defaultValuesHasItems;
|
protected bool _defaultValuesHasItems;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Used when Mode = multiple | tags - The values are used during initialization and when pressing the Reset button within Forms.
|
/// Used when Mode = multiple | tags - The values are used during initialization and when pressing the Reset button within Forms.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -177,6 +192,7 @@ namespace AntDesign
|
|||||||
|
|
||||||
internal HashSet<SelectOptionItem<TItemValue, TItem>> SelectOptionItems { get; } = new();
|
internal HashSet<SelectOptionItem<TItemValue, TItem>> SelectOptionItems { get; } = new();
|
||||||
internal List<SelectOptionItem<TItemValue, TItem>> SelectedOptionItems { get; } = new();
|
internal List<SelectOptionItem<TItemValue, TItem>> SelectedOptionItems { get; } = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called when the selected item changes.
|
/// Called when the selected item changes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -187,8 +203,9 @@ namespace AntDesign
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter] public EventCallback<IEnumerable<TItem>> OnSelectedItemsChanged { get; set; }
|
[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>
|
/// <summary>
|
||||||
/// Currently active (highlighted) option.
|
/// Currently active (highlighted) option.
|
||||||
@ -263,7 +280,6 @@ namespace AntDesign
|
|||||||
public Func<string, TItemValue> CustomTagLabelToValue { get; set; } =
|
public Func<string, TItemValue> CustomTagLabelToValue { get; set; } =
|
||||||
label => (TItemValue)TypeDescriptor.GetConverter(typeof(TItemValue)).ConvertFromInvariantString(label);
|
label => (TItemValue)TypeDescriptor.GetConverter(typeof(TItemValue)).ConvertFromInvariantString(label);
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines if SelectOptions has any selected items
|
/// Determines if SelectOptions has any selected items
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -351,7 +367,7 @@ namespace AntDesign
|
|||||||
[Parameter] public int MaxTagTextLength { get; set; }
|
[Parameter] public int MaxTagTextLength { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <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" }
|
/// e.g. { "value": TItemValue, "label": "Label value" }
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter]
|
[Parameter]
|
||||||
@ -383,6 +399,7 @@ namespace AntDesign
|
|||||||
|
|
||||||
private bool _hasValueOnClear;
|
private bool _hasValueOnClear;
|
||||||
private TItemValue _valueOnClear;
|
private TItemValue _valueOnClear;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When Clear button is pressed, Value will be set to
|
/// When Clear button is pressed, Value will be set to
|
||||||
/// whatever is set in ValueOnClear
|
/// 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>
|
/// <returns>true if SelectOptions has no values and the searchValue is empty; otherwise false </returns>
|
||||||
protected bool ShowPlaceholder => !HasValue && string.IsNullOrEmpty(_searchValue);
|
protected bool ShowPlaceholder => !HasValue && string.IsNullOrEmpty(_searchValue);
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The Method is called every time if the value of the @bind-Values was changed by the two-way binding.
|
/// The Method is called every time if the value of the @bind-Values was changed by the two-way binding.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected async Task OnValuesChangeAsync(IEnumerable<TItemValue> values)
|
protected async Task OnValuesChangeAsync(IEnumerable<TItemValue> values)
|
||||||
{
|
{
|
||||||
if (
|
if (!_isInitialized) // This is important because otherwise the initial value is overwritten by the EventCallback of ValueChanged and would be NULL.
|
||||||
!_isInitialized) // This is important because otherwise the initial value is overwritten by the EventCallback of ValueChanged and would be NULL.
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -670,7 +685,6 @@ namespace AntDesign
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The method is called every time if the user select/de-select a item by mouse or keyboard.
|
/// 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.
|
/// Don't change the IsSelected property outside of this function.
|
||||||
@ -827,7 +841,6 @@ namespace AntDesign
|
|||||||
_prevSearchValue = string.Empty;
|
_prevSearchValue = string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Method is called via EventCallBack after the user clicked on the Clear icon inside the Input element.
|
/// 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
|
/// 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;
|
Focused = true;
|
||||||
|
|
||||||
SetClassMap();
|
|
||||||
|
|
||||||
await FocusAsync(_inputRef);
|
await FocusAsync(_inputRef);
|
||||||
|
|
||||||
await OnFocus.InvokeAsync(Focused);
|
await OnFocus.InvokeAsync(Focused);
|
||||||
@ -962,7 +973,6 @@ namespace AntDesign
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
internal async Task OnArrowClick(MouseEventArgs args)
|
internal async Task OnArrowClick(MouseEventArgs args)
|
||||||
{
|
{
|
||||||
await _dropDown.OnClickDiv(args);
|
await _dropDown.OnClickDiv(args);
|
||||||
@ -985,7 +995,6 @@ namespace AntDesign
|
|||||||
_ = ClearSelectedAsync();
|
_ = ClearSelectedAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Clears the selectValue(s) property and send the null(default) value back through the two-way binding.
|
/// Clears the selectValue(s) property and send the null(default) value back through the two-way binding.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -1005,4 +1014,4 @@ namespace AntDesign
|
|||||||
|
|
||||||
protected abstract void SetClassMap();
|
protected abstract void SetClassMap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,297 +2,306 @@
|
|||||||
@namespace AntDesign.Select.Internal
|
@namespace AntDesign.Select.Internal
|
||||||
@typeparam TItemValue
|
@typeparam TItemValue
|
||||||
@typeparam TItem
|
@typeparam TItem
|
||||||
|
@inherits AntDomComponentBase
|
||||||
|
|
||||||
@if (ParentSelect.SelectMode == SelectMode.Default)
|
@if (ParentSelect.SelectMode == SelectMode.Default)
|
||||||
{
|
{
|
||||||
<div class="@Prefix-selector" @ref="@Ref" style="@(ParentSelect.PrefixIcon is null?"":"padding-left: 4px;")">
|
<div class="@Prefix-selector" @ref="@Ref" style="@(ParentSelect.PrefixIcon is null?"":"padding-left: 4px;")">
|
||||||
@if (ParentSelect.PrefixIcon != null)
|
@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)
|
|
||||||
{
|
{
|
||||||
<span class="ant-select-arrow" unselectable="on" aria-hidden="true" style="user-select: none;" @onclick="@ParentSelect.OnArrowClick" @onclick:stopPropagation="true">
|
<span class="@Prefix-prefix" unselectable="on" aria-hidden="true" style="user-select: none;display:flex;align-items: center;padding-right: 4px;">
|
||||||
@ParentSelect.SuffixIcon
|
@ParentSelect.PrefixIcon
|
||||||
</span>
|
</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;">
|
<span class="@Prefix-selection-placeholder">@Placeholder</span>
|
||||||
<Icon Type="loading"></Icon>
|
|
||||||
</span>
|
|
||||||
}
|
}
|
||||||
else
|
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">
|
<CascadingValue Value="this" Name="SelectContent">
|
||||||
@if (ParentSelect.IsSearchEnabled && IsOverlayShow)
|
<CascadingValue Value="@selectedItem" Name="SelectOption">
|
||||||
{
|
@ParentLabelTemplate(selectedItem.Item)
|
||||||
if (ShowSearchIcon)
|
</CascadingValue>
|
||||||
{
|
</CascadingValue>
|
||||||
<Icon Type="search"></Icon>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<Icon Type="down"></Icon>
|
|
||||||
}
|
|
||||||
</span>
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<span class="ant-select-arrow" unselectable="on" aria-hidden="true" style="user-select: none;" @onclick="@ParentSelect.OnArrowClick" @onclick:stopPropagation="true">
|
<span class="@Prefix-selection-item">
|
||||||
@if (ParentSelect.IsSearchEnabled && IsOverlayShow)
|
@getLabel(selectedItem)
|
||||||
{
|
</span>
|
||||||
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>
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
</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
|
else //ParentSelect.SelectMode != SelectMode.Default
|
||||||
{
|
{
|
||||||
<div class="@Prefix-selector" @ref="@Ref" style="@(ParentSelect.PrefixIcon is null?"":"padding-left: 4px;")" >
|
<div class="@Prefix-selector" @ref="@Ref" style="@(ParentSelect.PrefixIcon is null?"":"padding-left: 4px;")">
|
||||||
<div class="@Prefix-selection-overflow" @ref="@_overflow">
|
<div class="@Prefix-selection-overflow" @ref="@_overflow">
|
||||||
@if (ParentSelect.PrefixIcon != null)
|
@if (ParentSelect.PrefixIcon != null)
|
||||||
{
|
{
|
||||||
<div class="@Prefix-selection-overflow-item" style="opacity: 1;order:-100;">
|
<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;">
|
<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
|
@ParentSelect.PrefixIcon
|
||||||
</span>
|
</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>
|
</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 class="@Prefix-selection-item">
|
||||||
{
|
<span class="@Prefix-selection-item-content">+ @(selectedItems.Count - ParentSelect.MaxTagCount.AsT0)@Ellipse</span>
|
||||||
<span @ref="@_suffixRef" class="ant-select-arrow" unselectable="on" aria-hidden="true" style="user-select: none;" @onclick="@ParentSelect.OnArrowClick" @onclick:stopPropagation="true">
|
</span>
|
||||||
@ParentSelect.SuffixIcon
|
|
||||||
</span>
|
}
|
||||||
}
|
</div>
|
||||||
else if (ParentSelect.Loading)
|
}
|
||||||
{
|
}
|
||||||
<span @ref="@_suffixRef" class="ant-select-arrow ant-select-arrow-loading" unselectable="on" aria-hidden="true" style="user-select: none;">
|
else if (ParentSelect.IsResponsive)
|
||||||
<Icon Type="loading"></Icon>
|
{
|
||||||
</span>
|
@for (int i = 0; i < selectedItems.Count; i++)
|
||||||
}
|
{
|
||||||
@if (!ParentSelect.Disabled && ParentSelect.AllowClear && ParentSelect.HasValue)
|
var selectedOption = selectedItems[i];
|
||||||
{
|
<div class="@Prefix-selection-overflow-item" @key="@selectedOption.InternalId" @ref="@selectedOption.SelectedTagRef" style="@OverflowStyle(i)">
|
||||||
<span @ref="@_suffixRef" class="ant-select-clear" unselectable="on" aria-hidden="true" style="user-select: none;" @onclick="OnClearClickAsync" @onclick:stopPropagation="true">
|
@if (ParentLabelTemplate != null)
|
||||||
<Icon Type="close-circle" Theme="fill"></Icon>
|
{
|
||||||
</span>
|
<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
|
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 = "ParentSelect")] internal SelectBase<TItemValue, TItem> ParentSelect { get; set; }
|
||||||
[CascadingParameter(Name = "ParentLabelTemplate")] internal RenderFragment<TItem> ParentLabelTemplate { 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<MouseEventArgs> OnClearClick { get; set; }
|
||||||
[Parameter] public EventCallback<SelectOptionItem<TItemValue, TItem>> OnRemoveSelected { get; set; }
|
[Parameter] public EventCallback<SelectOptionItem<TItemValue, TItem>> OnRemoveSelected { get; set; }
|
||||||
[Parameter] public string SearchValue { get; set; }
|
[Parameter] public string SearchValue { get; set; }
|
||||||
[Parameter] public ForwardRef RefBack { get; set; } = new ForwardRef();
|
|
||||||
[Parameter] public int SearchDebounceMilliseconds { get; set; }
|
[Parameter] public int SearchDebounceMilliseconds { get; set; }
|
||||||
[Inject] protected IJSRuntime Js { get; set; }
|
|
||||||
[Inject] private IDomEventListener DomEventListener { 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 char Ellipse = (char)0x2026;
|
||||||
private const int ItemMargin = 4; //taken from each tag item
|
private const int ItemMargin = 4; //taken from each tag item
|
||||||
private string _inputStyle = string.Empty;
|
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
|
//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());
|
private async void OnBlurInternal(JsonElement e) => await OnBlur.InvokeAsync(new());
|
||||||
|
|
||||||
public bool IsDisposed { get; private set; }
|
protected override void Dispose(bool disposing)
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
|
||||||
{
|
{
|
||||||
if (!_isReloading)
|
if (!_isReloading)
|
||||||
{
|
{
|
||||||
@ -466,22 +452,6 @@ namespace AntDesign.Select.Internal
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
DomEventListener?.Dispose();
|
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();
|
public Guid InternalId { get; set; } = Guid.NewGuid();
|
||||||
|
|
||||||
private TItemValue _value;
|
private TItemValue _value;
|
||||||
|
|
||||||
public TItemValue Value
|
public TItemValue Value
|
||||||
{
|
{
|
||||||
get => _value;
|
get => _value;
|
||||||
@ -38,6 +39,7 @@ namespace AntDesign.Select.Internal
|
|||||||
}
|
}
|
||||||
|
|
||||||
private TItem _item;
|
private TItem _item;
|
||||||
|
|
||||||
public TItem Item
|
public TItem Item
|
||||||
{
|
{
|
||||||
get => _item;
|
get => _item;
|
||||||
@ -74,6 +76,8 @@ namespace AntDesign.Select.Internal
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public RenderFragment LabelTemplate { get; set; }
|
||||||
|
|
||||||
private string _groupName = string.Empty;
|
private string _groupName = string.Empty;
|
||||||
|
|
||||||
public string GroupName
|
public string GroupName
|
||||||
@ -102,6 +106,7 @@ namespace AntDesign.Select.Internal
|
|||||||
}
|
}
|
||||||
|
|
||||||
private bool _isSelected;
|
private bool _isSelected;
|
||||||
|
|
||||||
public bool IsSelected
|
public bool IsSelected
|
||||||
{
|
{
|
||||||
get => _isSelected;
|
get => _isSelected;
|
||||||
@ -118,6 +123,7 @@ namespace AntDesign.Select.Internal
|
|||||||
}
|
}
|
||||||
|
|
||||||
private bool _isActive;
|
private bool _isActive;
|
||||||
|
|
||||||
public bool IsActive
|
public bool IsActive
|
||||||
{
|
{
|
||||||
get => _isActive;
|
get => _isActive;
|
||||||
@ -134,6 +140,7 @@ namespace AntDesign.Select.Internal
|
|||||||
}
|
}
|
||||||
|
|
||||||
private bool _isDisabled;
|
private bool _isDisabled;
|
||||||
|
|
||||||
public bool IsDisabled
|
public bool IsDisabled
|
||||||
{
|
{
|
||||||
get => _isDisabled;
|
get => _isDisabled;
|
||||||
@ -150,6 +157,7 @@ namespace AntDesign.Select.Internal
|
|||||||
}
|
}
|
||||||
|
|
||||||
private bool _isHidden;
|
private bool _isHidden;
|
||||||
|
|
||||||
public bool IsHidden
|
public bool IsHidden
|
||||||
{
|
{
|
||||||
get => _isHidden;
|
get => _isHidden;
|
||||||
@ -165,7 +173,6 @@ namespace AntDesign.Select.Internal
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public bool IsAddedTag { get; set; }
|
public bool IsAddedTag { get; set; }
|
||||||
|
|
||||||
private SelectOption<TItemValue, TItem> _childComponent;
|
private SelectOption<TItemValue, TItem> _childComponent;
|
||||||
|
@ -10,26 +10,50 @@ namespace AntDesign
|
|||||||
[Parameter]
|
[Parameter]
|
||||||
public string Format { get; set; } = "hh:mm:ss";
|
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]
|
[Parameter]
|
||||||
public EventCallback OnFinish { get; set; }
|
public EventCallback OnFinish { get; set; }
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public int RefreshInterval { get; set; } = REFRESH_INTERVAL;
|
||||||
|
|
||||||
private Timer _timer;
|
private Timer _timer;
|
||||||
|
|
||||||
private const int REFRESH_INTERVAL = 1000 / 30;
|
private const int REFRESH_INTERVAL = 1000 / 10;
|
||||||
|
|
||||||
private TimeSpan _countDown = TimeSpan.Zero;
|
private TimeSpan _countDown = TimeSpan.Zero;
|
||||||
|
|
||||||
protected override void OnInitialized()
|
protected override void OnInitialized()
|
||||||
{
|
{
|
||||||
base.OnInitialized();
|
base.OnInitialized();
|
||||||
|
SetTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetTimer()
|
||||||
|
{
|
||||||
|
_countDown = Value - DateTime.Now;
|
||||||
_timer = new Timer(StartCountDownForTimeSpan);
|
_timer = new Timer(StartCountDownForTimeSpan);
|
||||||
_timer.Change(0, REFRESH_INTERVAL);
|
_timer.Change(0, RefreshInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void StartCountDownForTimeSpan(object o)
|
private void StartCountDownForTimeSpan(object o)
|
||||||
{
|
{
|
||||||
_countDown = Value - DateTime.Now;
|
_countDown = _countDown.Add(TimeSpan.FromMilliseconds(-RefreshInterval));
|
||||||
if (_countDown.Ticks <= 0)
|
if (_countDown.Ticks <= 0)
|
||||||
{
|
{
|
||||||
_countDown = TimeSpan.Zero;
|
_countDown = TimeSpan.Zero;
|
||||||
@ -39,8 +63,23 @@ namespace AntDesign
|
|||||||
InvokeAsync(() => OnFinish.InvokeAsync(o));
|
InvokeAsync(() => OnFinish.InvokeAsync(o));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
InvokeStateHasChanged();
|
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>
|
||||||
/// 数值内容
|
/// 数值内容
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter] public T Value { get; set; }
|
[Parameter] public virtual T Value { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 设置数值的样式
|
/// 设置数值的样式
|
||||||
|
@ -48,7 +48,12 @@ namespace AntDesign
|
|||||||
if (_pending.Value != value.Value)
|
if (_pending.Value != value.Value)
|
||||||
{
|
{
|
||||||
_pending = value;
|
_pending = value;
|
||||||
|
if (value.Value == null)
|
||||||
|
{
|
||||||
|
_pendingItem = null;
|
||||||
|
SetItems();
|
||||||
|
return;
|
||||||
|
}
|
||||||
_pendingItem = _pending.Value == null ? null : new TimelineItem()
|
_pendingItem = _pending.Value == null ? null : new TimelineItem()
|
||||||
{
|
{
|
||||||
Class = "ant-timeline-item-pending"
|
Class = "ant-timeline-item-pending"
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
@onfocusin="OnTriggerFocusIn"
|
@onfocusin="OnTriggerFocusIn"
|
||||||
@onfocusout="OnTriggerFocusOut"
|
@onfocusout="OnTriggerFocusOut"
|
||||||
@oncontextmenu:preventDefault
|
@oncontextmenu:preventDefault
|
||||||
tabindex="0">
|
tabindex="@TabIndex">
|
||||||
@ChildContent
|
@ChildContent
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,9 @@ namespace AntDesign
|
|||||||
[Parameter]
|
[Parameter]
|
||||||
public double MouseLeaveDelay { get; set; } = 0.1;
|
public double MouseLeaveDelay { get; set; } = 0.1;
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public int TabIndex { get; set; } = 0;
|
||||||
|
|
||||||
public Tooltip()
|
public Tooltip()
|
||||||
{
|
{
|
||||||
PrefixCls = "ant-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
|
@using AntDesign.Select.Internal
|
||||||
|
|
||||||
<CascadingValue Value="this" IsFixed>
|
<CascadingValue Value="this" IsFixed>
|
||||||
<CascadingValue Value=@("ant-select-dropdown") Name="PrefixCls" IsFixed>
|
<CascadingValue Value=@("ant-select-dropdown") Name="PrefixCls" IsFixed>
|
||||||
<div class="@ClassMapper.Class" style="@Style" id="@Id" tabindex="-1" @ref="Ref">
|
<div class="@ClassMapper.Class" style="@Style" id="@Id" tabindex="-1" @ref="Ref">
|
||||||
<OverlayTrigger @ref="@_dropDown"
|
<OverlayTrigger @ref="@_dropDown"
|
||||||
Visible="Open"
|
Visible="Open"
|
||||||
Disabled="Disabled"
|
Disabled="Disabled"
|
||||||
Trigger="new[] { Trigger.Click }"
|
Trigger="new[] { Trigger.Click }"
|
||||||
HiddenMode
|
HiddenMode
|
||||||
OnMouseEnter="@(() => { OnMouseEnter?.Invoke(); })"
|
OnMouseEnter="@(() => { OnMouseEnter?.Invoke(); })"
|
||||||
OnMouseLeave="@(() => { OnMouseLeave?.Invoke(); })"
|
OnMouseLeave="@(() => { OnMouseLeave?.Invoke(); })"
|
||||||
OnVisibleChange="@OnOverlayVisibleChangeAsync"
|
OnVisibleChange="@OnOverlayVisibleChangeAsync"
|
||||||
PopupContainerSelector="@PopupContainerSelector"
|
PopupContainerSelector="@PopupContainerSelector"
|
||||||
OverlayEnterCls="ant-slide-up-enter ant-slide-up-enter-active ant-slide-up"
|
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">
|
OverlayLeaveCls="ant-slide-up-leave ant-slide-up-leave-active ant-slide-up">
|
||||||
<Overlay >
|
<Overlay>
|
||||||
<div style="@_dropdownStyle">
|
<div style="@_dropdownStyle">
|
||||||
<div class="" style="max-height: @PopupContainerMaxHeight; overflow-y: auto;">
|
<div class="" style="max-height: @PopupContainerMaxHeight; overflow-y: auto;">
|
||||||
<div>
|
<div>
|
||||||
<div class="" role="listbox" style="display: flex; flex-direction: column;">
|
<div class="" role="listbox" style="display: flex; flex-direction: column;">
|
||||||
|
|
||||||
<Tree TItem="TItem"
|
<Tree @ref="_tree"
|
||||||
BlockNode @ref="_tree" Multiple="Multiple"
|
TItem="TItem"
|
||||||
@attributes="TreeAttributes"
|
BlockNode
|
||||||
SelectedKeys="SelectedKeys"
|
DataSource="DataSource"
|
||||||
OnClick="OnTreeNodeClick"
|
Multiple="Multiple"
|
||||||
OnUnSelect="OnTreeNodeUnSelect">
|
Selectable="!TreeCheckable"
|
||||||
<Nodes>
|
SelectedKeys="SelectedKeys"
|
||||||
@if (IsInnerModel)
|
Checkable="TreeCheckable"
|
||||||
{
|
OnClick="OnTreeNodeClick"
|
||||||
<CascadingValue Name="Tree" Value="_tree" IsFixed="true">
|
OnUnselect="OnTreeNodeUnSelect"
|
||||||
@ChildContent
|
OnCheck="OnTreeCheck"
|
||||||
</CascadingValue>
|
ShowLeafIcon="ShowLeafIcon"
|
||||||
}
|
ShowLine="ShowTreeLine"
|
||||||
</Nodes>
|
TitleExpression="TitleExpression"
|
||||||
|
KeyExpression="KeyExpression"
|
||||||
</Tree>
|
IconExpression="IconExpression"
|
||||||
</div>
|
IsLeafExpression="IsLeafExpression"
|
||||||
</div>
|
ChildrenExpression="ChildrenExpression"
|
||||||
</div>
|
DisabledExpression="DisabledExpression"
|
||||||
</div>
|
DefaultExpandAll="TreeDefaultExpandAll"
|
||||||
</Overlay>
|
>
|
||||||
<Unbound>
|
<Nodes>
|
||||||
<CascadingValue Value="this" Name=@("ParentSelect") IsFixed>
|
@if (IsTemplatedNodes)
|
||||||
<CascadingValue Value="@LabelTemplate" Name="ParentLabelTemplate">
|
{
|
||||||
<CascadingValue Value="@ShowSearchIcon" Name="ShowSearchIcon">
|
<CascadingValue Name="Tree" Value="_tree" IsFixed="true">
|
||||||
<CascadingValue Value="@ShowArrowIcon" Name="ShowArrowIcon">
|
@ChildContent
|
||||||
<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>
|
||||||
</CascadingValue>
|
}
|
||||||
</Unbound>
|
</Nodes>
|
||||||
</OverlayTrigger>
|
|
||||||
</div>
|
</Tree>
|
||||||
</CascadingValue>
|
</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>
|
</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.Collections.Generic;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using AntDesign.Internal;
|
|
||||||
using AntDesign.Select.Internal;
|
using AntDesign.Select.Internal;
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
using Microsoft.AspNetCore.Components.Web;
|
using Microsoft.AspNetCore.Components.Web;
|
||||||
using AntDesign.Core.Helpers.MemberPath;
|
|
||||||
using AntDesign.JsInterop;
|
using AntDesign.JsInterop;
|
||||||
using OneOf;
|
using OneOf;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@ -17,8 +18,6 @@ namespace AntDesign
|
|||||||
{
|
{
|
||||||
[Parameter] public bool ShowExpand { get; set; } = true;
|
[Parameter] public bool ShowExpand { get; set; } = true;
|
||||||
|
|
||||||
protected Tree<TItem> _tree;
|
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public bool Multiple
|
public bool Multiple
|
||||||
{
|
{
|
||||||
@ -56,162 +55,87 @@ namespace AntDesign
|
|||||||
[Parameter] public bool TreeDefaultExpandAll { get; set; }
|
[Parameter] public bool TreeDefaultExpandAll { get; set; }
|
||||||
|
|
||||||
[Parameter]
|
[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";
|
public string RootValue { get; set; } = "0";
|
||||||
|
|
||||||
protected Func<TreeNode<TItem>, string> TreeNodeTitleExpression
|
[Parameter] public OneOf<bool, string> DropdownMatchSelectWidth { get; set; } = true;
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return node => TitleExpression(node.DataItem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
[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]
|
[Parameter]
|
||||||
public Func<TItem, string> TitleExpression { get; set; }
|
public Func<TreeNode<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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Specifies a method that returns the key of the node.
|
||||||
|
/// </summary>
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public Func<TItem, string> KeyExpression { get; set; }
|
public Func<TreeNode<TItem>, string> KeyExpression { get; set; }
|
||||||
|
|
||||||
|
|
||||||
protected Func<TreeNode<TItem>, string> TreeNodeIconExpression
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return node => IconExpression(node.DataItem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies a method to return the node icon.
|
/// Specifies a method to return the node icon.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public Func<TItem, string> IconExpression { get; set; }
|
public Func<TreeNode<TItem>, string> IconExpression { get; set; }
|
||||||
|
|
||||||
protected Func<TreeNode<TItem>, bool> TreeNodeIsLeafExpression
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return node => IsLeafExpression(DataSource, node.DataItem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private bool IsInnerModel => ChildContent != null;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies a method that returns whether the expression is a leaf node.
|
/// Specifies a method that returns whether the expression is a leaf node.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public Func<IEnumerable<TItem>, TItem, bool> IsLeafExpression { get; set; }
|
public Func<TreeNode<TItem>, bool> IsLeafExpression { get; set; }
|
||||||
|
|
||||||
|
|
||||||
protected virtual Func<TreeNode<TItem>, IList<TItem>> TreeNodeChildrenExpression
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return node => ChildrenExpression == null ? null : ChildrenExpression(node.DataItem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Specifies a method to return a child node
|
||||||
|
/// </summary>
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public virtual Func<TItem, IList<TItem>> ChildrenExpression { get; set; }
|
public Func<TreeNode<TItem>, IEnumerable<TItem>> ChildrenExpression { get; set; }
|
||||||
|
|
||||||
protected Func<TreeNode<TItem>, bool> TreeNodeDisabledExpression
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return node => DisabledExpression != null && DisabledExpression(node.DataItem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies a method to return a disabled node
|
/// Specifies a method to return a disabled node
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public Func<TItem, bool> DisabledExpression { get; set; }
|
public Func<TreeNode<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";
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private bool IsMultiple => Multiple || TreeCheckable;
|
private bool IsMultiple => Multiple || TreeCheckable;
|
||||||
|
|
||||||
|
private bool IsTemplatedNodes => ChildContent != null;
|
||||||
|
|
||||||
internal override SelectMode SelectMode => IsMultiple ? SelectMode.Multiple : base.SelectMode;
|
internal override SelectMode SelectMode => IsMultiple ? SelectMode.Multiple : base.SelectMode;
|
||||||
|
|
||||||
private string[] SelectedKeys => Values?.ToArray();
|
private string[] SelectedKeys => Values?.ToArray();
|
||||||
//private readonly IList<TreeNode<TItem>> _selectedNodes = new List<TreeNode<TItem>>();
|
|
||||||
|
|
||||||
private string _dropdownStyle = string.Empty;
|
private string _dropdownStyle = string.Empty;
|
||||||
private bool _multiple;
|
private bool _multiple;
|
||||||
private readonly string _dir = "ltr";
|
private readonly string _dir = "ltr";
|
||||||
|
private Tree<TItem> _tree;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public override string Value
|
public override string Value
|
||||||
{
|
{
|
||||||
get => base.Value;
|
get => base.Value;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(value))
|
|
||||||
return;
|
|
||||||
if (base.Value == value)
|
if (base.Value == value)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
base.Value = value;
|
base.Value = value;
|
||||||
|
|
||||||
if (SelectOptionItems.Any(o => o.Value == value))
|
if (value == null)
|
||||||
{
|
{
|
||||||
_ = SetValueAsync(SelectOptionItems.First(o => o.Value == value));
|
ClearOptions();
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var data = DataItemExpression?.Invoke(DataSource, value);
|
|
||||||
if (data != null)
|
|
||||||
{
|
|
||||||
var o = CreateOption(data, true);
|
|
||||||
_ = SetValueAsync(o);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UpdateValueAndSelection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,12 +144,6 @@ namespace AntDesign
|
|||||||
get => base.Values;
|
get => base.Values;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (!_isInitialized)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!Multiple)
|
|
||||||
throw new NotImplementedException("not Multiple select, no die");
|
|
||||||
|
|
||||||
if (value != null && _selectedValues != null)
|
if (value != null && _selectedValues != null)
|
||||||
{
|
{
|
||||||
var hasChanged = !value.SequenceEqual(_selectedValues);
|
var hasChanged = !value.SequenceEqual(_selectedValues);
|
||||||
@ -233,31 +151,24 @@ namespace AntDesign
|
|||||||
if (!hasChanged)
|
if (!hasChanged)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ClearOptions();
|
|
||||||
|
|
||||||
_selectedValues = value;
|
_selectedValues = value;
|
||||||
CreateOptions(value);
|
|
||||||
_ = OnValuesChangeAsync(value);
|
|
||||||
}
|
}
|
||||||
else if (value != null && _selectedValues == null)
|
else if (value != null && _selectedValues == null)
|
||||||
{
|
{
|
||||||
_selectedValues = value;
|
_selectedValues = value;
|
||||||
CreateOptions(value);
|
|
||||||
_ = OnValuesChangeAsync(value);
|
|
||||||
}
|
}
|
||||||
else if (value == null && _selectedValues != null)
|
else if (value == null && _selectedValues != null)
|
||||||
{
|
{
|
||||||
_selectedValues = default;
|
_selectedValues = default;
|
||||||
|
|
||||||
ClearOptions();
|
ClearOptions();
|
||||||
|
|
||||||
_ = OnValuesChangeAsync(default);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UpdateValuesSelection();
|
||||||
|
|
||||||
if (_isNotifyFieldChanged && (Form?.ValidateOnChange == true))
|
if (_isNotifyFieldChanged && (Form?.ValidateOnChange == true))
|
||||||
{
|
{
|
||||||
EditContext?.NotifyFieldChanged(FieldIdentifier);
|
EditContext?.NotifyFieldChanged(FieldIdentifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,41 +176,26 @@ namespace AntDesign
|
|||||||
{
|
{
|
||||||
SelectOptionItems.Clear();
|
SelectOptionItems.Clear();
|
||||||
SelectedOptionItems.Clear();
|
SelectedOptionItems.Clear();
|
||||||
|
_tree?._allNodes.ForEach(x => x.SetSelected(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateOptions(IEnumerable<string> data)
|
private void CreateOptions(IEnumerable<string> data)
|
||||||
{
|
{
|
||||||
if (IsInnerModel)
|
if (IsTemplatedNodes)
|
||||||
{
|
{
|
||||||
var d1 = data.Where(d => !SelectOptionItems.Any(o => o.Value == d));
|
var d1 = data.Where(d => !SelectOptionItems.Any(o => o.Value == d));
|
||||||
CreateOptionsByTreeNode(d1);
|
CreateOptionsByTreeNode(d1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 通过DataItemExpression来生成选中项
|
data.ForEach(menuId =>
|
||||||
if (DataItemExpression != null)
|
|
||||||
{
|
{
|
||||||
data.ForEach(menuId =>
|
var d = _tree._allNodes.FirstOrDefault(m => m.Key == menuId);
|
||||||
|
if (d != null)
|
||||||
{
|
{
|
||||||
var d = DataItemExpression?.Invoke(DataSource, menuId);
|
var o = CreateOption(d, true);
|
||||||
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);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateOptionsByTreeNode(IEnumerable<string> data)
|
private void CreateOptionsByTreeNode(IEnumerable<string> data)
|
||||||
@ -319,36 +215,30 @@ namespace AntDesign
|
|||||||
var o = new SelectOptionItem<string, TItem>()
|
var o = new SelectOptionItem<string, TItem>()
|
||||||
{
|
{
|
||||||
Label = data.Title,
|
Label = data.Title,
|
||||||
|
LabelTemplate = data.TitleTemplate,
|
||||||
Value = data.Key,
|
Value = data.Key,
|
||||||
Item = data.DataItem,
|
Item = data.DataItem,
|
||||||
IsAddedTag = SelectMode != SelectMode.Default
|
IsAddedTag = SelectMode != SelectMode.Default,
|
||||||
};
|
};
|
||||||
if (append && !SelectOptionItems.Any(m => m.Value == o.Value))
|
if (append && !SelectOptionItems.Any(m => m.Value == o.Value))
|
||||||
SelectOptionItems.Add(o);
|
SelectOptionItems.Add(o);
|
||||||
return 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),
|
UpdateValueAndSelection();
|
||||||
Value = KeyExpression(data),
|
}
|
||||||
Item = data,
|
|
||||||
IsAddedTag = SelectMode != SelectMode.Default
|
|
||||||
};
|
|
||||||
if (append && !SelectOptionItems.Any(m => m.Value == o.Value))
|
|
||||||
SelectOptionItems.Add(o);
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
if (Values != null)
|
||||||
{
|
{
|
||||||
SelectOptions = "".ToRenderFragment();
|
UpdateValuesSelection();
|
||||||
//_inputValue = Value;
|
}
|
||||||
base.OnInitialized();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return base.OnFirstAfterRenderAsync();
|
||||||
|
}
|
||||||
|
|
||||||
private void OnKeyDownAsync(KeyboardEventArgs args)
|
private void OnKeyDownAsync(KeyboardEventArgs args)
|
||||||
{
|
{
|
||||||
@ -377,6 +267,7 @@ namespace AntDesign
|
|||||||
await SetDropdownStyleAsync();
|
await SetDropdownStyleAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async Task OnRemoveSelectedAsync(SelectOptionItem<string, TItem> selectOption)
|
protected async Task OnRemoveSelectedAsync(SelectOptionItem<string, TItem> selectOption)
|
||||||
{
|
{
|
||||||
if (selectOption == null) throw new ArgumentNullException(nameof(selectOption));
|
if (selectOption == null) throw new ArgumentNullException(nameof(selectOption));
|
||||||
@ -389,43 +280,56 @@ namespace AntDesign
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private async Task OnTreeNodeClick(TreeEventArgs<TItem> args)
|
private async Task OnTreeNodeClick(TreeEventArgs<TItem> args)
|
||||||
{
|
{
|
||||||
if (!args.Node.Selected)
|
var node = args.Node;
|
||||||
|
|
||||||
|
if (!TreeCheckable && !node.Selected)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var key = args.Node.Key;
|
var key = node.Key;
|
||||||
if (Value != null && Value.Equals(key))
|
if (Value != null && Value.Equals(key))
|
||||||
return;
|
return;
|
||||||
if (Values != null && Values.Contains(key))
|
if (Values != null && Values.Contains(key))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var data = args.Node;
|
var option = CreateOption(node, true);
|
||||||
SelectOptionItem<string, TItem> item;
|
|
||||||
if (IsInnerModel)
|
|
||||||
item = CreateOption(data, true);
|
|
||||||
else
|
|
||||||
item = CreateOption(data.DataItem, 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)
|
if (SelectMode == SelectMode.Default)
|
||||||
|
{
|
||||||
await CloseAsync();
|
await CloseAsync();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected async Task OnTreeNodeUnSelect(TreeEventArgs<TItem> args)
|
||||||
protected void OnTreeNodeUnSelect(TreeEventArgs<TItem> args)
|
|
||||||
{
|
{
|
||||||
if (args == null) throw new ArgumentNullException(nameof(args));
|
// Prevent deselect in sigle selection mode
|
||||||
var key = args.Node.Key;
|
if (!Multiple && args.Node.Key == Value)
|
||||||
var nodes = SelectOptionItems.Where(o => o.Value == key).ToArray();
|
|
||||||
foreach (var item in nodes)
|
|
||||||
{
|
{
|
||||||
_ = 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()
|
protected async Task SetDropdownStyleAsync()
|
||||||
@ -444,7 +348,7 @@ namespace AntDesign
|
|||||||
}
|
}
|
||||||
if (!DropdownMaxWidth.Equals("auto", StringComparison.CurrentCultureIgnoreCase))
|
if (!DropdownMaxWidth.Equals("auto", StringComparison.CurrentCultureIgnoreCase))
|
||||||
maxWidth = $"max-width: {DropdownMaxWidth};";
|
maxWidth = $"max-width: {DropdownMaxWidth};";
|
||||||
_dropdownStyle = minWidth + definedWidth + maxWidth;
|
_dropdownStyle = minWidth + definedWidth + maxWidth + DropdownStyle ?? "";
|
||||||
|
|
||||||
if (Multiple)
|
if (Multiple)
|
||||||
{
|
{
|
||||||
@ -458,7 +362,6 @@ namespace AntDesign
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected override void SetClassMap()
|
protected override void SetClassMap()
|
||||||
{
|
{
|
||||||
var classPrefix = "ant-select";
|
var classPrefix = "ant-select";
|
||||||
@ -466,17 +369,51 @@ namespace AntDesign
|
|||||||
.Add(classPrefix)
|
.Add(classPrefix)
|
||||||
.Add("ant-tree-select")
|
.Add("ant-tree-select")
|
||||||
.If("ant-select-lg", () => Size == "large")
|
.If("ant-select-lg", () => Size == "large")
|
||||||
.If("ant-select-rtl", () => _dir == "rtl")
|
.If("ant-select-sm", () => Size == "small")
|
||||||
.If("ant-select-sm", () => Size == "rtl")
|
.If("ant-select-rtl", () => RTL)
|
||||||
.If("ant-select-disabled", () => Disabled)
|
.If("ant-select-disabled", () => Disabled)
|
||||||
.If("ant-select-single", () => SelectMode == SelectMode.Default)
|
.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-arrow", () => !IsMultiple)
|
||||||
.If("ant-select-show-search", () => !IsMultiple)
|
.If("ant-select-show-search", () => !IsMultiple)
|
||||||
.If("ant-select-allow-clear", () => AllowClear)
|
.If("ant-select-allow-clear", () => AllowClear)
|
||||||
.If("ant-select-open", () => Open)
|
.If("ant-select-open", () => Open)
|
||||||
.If("ant-select-focused", () => Open || Focused)
|
.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.
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
@ -94,7 +94,7 @@ namespace AntDesign
|
|||||||
private bool _hasSetShowLeafIcon;
|
private bool _hasSetShowLeafIcon;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specific the Icon type of switcher
|
/// Specific the Icon type of switcher
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string SwitcherIcon { get; set; }
|
public string SwitcherIcon { get; set; }
|
||||||
@ -190,9 +190,9 @@ namespace AntDesign
|
|||||||
if (SelectedNodesDictionary.ContainsKey(treeNode.NodeId) == true)
|
if (SelectedNodesDictionary.ContainsKey(treeNode.NodeId) == true)
|
||||||
SelectedNodesDictionary.Remove(treeNode.NodeId);
|
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>
|
/// <summary>
|
||||||
/// Specifies the keys of the default checked treeNodes
|
/// Specifies the keys of the default checked treeNodes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -377,6 +385,7 @@ namespace AntDesign
|
|||||||
_checkedNodes.TryAdd(treeNode.NodeId, treeNode);
|
_checkedNodes.TryAdd(treeNode.NodeId, treeNode);
|
||||||
else
|
else
|
||||||
_checkedNodes.TryRemove(treeNode.NodeId, out TreeNode<TItem> _);
|
_checkedNodes.TryRemove(treeNode.NodeId, out TreeNode<TItem> _);
|
||||||
|
|
||||||
_checkedKeys = _checkedNodes.Select(x => x.Value.Key).ToArray();
|
_checkedKeys = _checkedNodes.Select(x => x.Value.Key).ToArray();
|
||||||
|
|
||||||
if (!old.SequenceEqual(_checkedKeys) && CheckedKeysChanged.HasDelegate)
|
if (!old.SequenceEqual(_checkedKeys) && CheckedKeysChanged.HasDelegate)
|
||||||
@ -419,12 +428,6 @@ namespace AntDesign
|
|||||||
|
|
||||||
private void SearchNodes()
|
private void SearchNodes()
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(_searchValue))
|
|
||||||
{
|
|
||||||
_allNodes.ForEach(m => { m.Expand(true); m.Matched = false; });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var allList = _allNodes.ToList();
|
var allList = _allNodes.ToList();
|
||||||
List<TreeNode<TItem>> searchDatas = null, exceptList = null;
|
List<TreeNode<TItem>> searchDatas = null, exceptList = null;
|
||||||
|
|
||||||
@ -489,7 +492,7 @@ namespace AntDesign
|
|||||||
/// Specifies a method to return a child node
|
/// Specifies a method to return a child node
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public Func<TreeNode<TItem>, IList<TItem>> ChildrenExpression { get; set; }
|
public Func<TreeNode<TItem>, IEnumerable<TItem>> ChildrenExpression { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies a method to return a disabled node
|
/// Specifies a method to return a disabled node
|
||||||
@ -536,7 +539,7 @@ namespace AntDesign
|
|||||||
public EventCallback<TreeEventArgs<TItem>> OnSelect { get; set; }
|
public EventCallback<TreeEventArgs<TItem>> OnSelect { get; set; }
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public EventCallback<TreeEventArgs<TItem>> OnUnSelect { get; set; }
|
public EventCallback<TreeEventArgs<TItem>> OnUnselect { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Click the expansion tree node icon to call back
|
/// Click the expansion tree node icon to call back
|
||||||
@ -620,6 +623,33 @@ namespace AntDesign
|
|||||||
base.OnInitialized();
|
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>
|
/// <summary>
|
||||||
/// Find Node
|
/// Find Node
|
||||||
/// </summary>
|
/// </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.
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ namespace AntDesign
|
|||||||
public int TreeLevel => (ParentNode?.TreeLevel ?? -1) + 1;
|
public int TreeLevel => (ParentNode?.TreeLevel ?? -1) + 1;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// record the index in children nodes list of parent node.
|
/// record the index in children nodes list of parent node.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal int NodeIndex { get; set; }
|
internal int NodeIndex { get; set; }
|
||||||
|
|
||||||
@ -157,7 +157,7 @@ namespace AntDesign
|
|||||||
_key = value;
|
_key = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool _disabled;
|
private bool _disabled;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -193,11 +193,7 @@ namespace AntDesign
|
|||||||
public void SetSelected(bool value)
|
public void SetSelected(bool value)
|
||||||
{
|
{
|
||||||
if (Disabled) return;
|
if (Disabled) return;
|
||||||
if (!TreeComponent.Selectable && TreeComponent.Checkable)
|
|
||||||
{
|
|
||||||
SetChecked(!Checked);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (_selected == value) return;
|
if (_selected == value) return;
|
||||||
_selected = value;
|
_selected = value;
|
||||||
if (value == true)
|
if (value == true)
|
||||||
@ -397,12 +393,11 @@ namespace AntDesign
|
|||||||
|
|
||||||
#region Checkbox
|
#region Checkbox
|
||||||
|
|
||||||
private bool _checked;
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// According to check the
|
/// According to check the
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public bool Checked { get; set; }
|
public bool Checked { get; set; }
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public bool Indeterminate { get; set; }
|
public bool Indeterminate { get; set; }
|
||||||
@ -460,6 +455,24 @@ namespace AntDesign
|
|||||||
TreeComponent.AddOrRemoveCheckNode(this);
|
TreeComponent.AddOrRemoveCheckNode(this);
|
||||||
StateHasChanged();
|
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>
|
/// <summary>
|
||||||
/// Sets the checkbox status of child nodes
|
/// Sets the checkbox status of child nodes
|
||||||
@ -476,6 +489,20 @@ namespace AntDesign
|
|||||||
foreach (var child in subnode.ChildNodes)
|
foreach (var child in subnode.ChildNodes)
|
||||||
child?.SetChildChecked(child, check);
|
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>
|
/// <summary>
|
||||||
/// Update check status
|
/// Update check status
|
||||||
@ -540,6 +567,66 @@ namespace AntDesign
|
|||||||
if (ParentNode == null)
|
if (ParentNode == null)
|
||||||
StateHasChanged();
|
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
|
#endregion Checkbox
|
||||||
|
|
||||||
@ -621,7 +708,7 @@ namespace AntDesign
|
|||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (TreeComponent.ChildrenExpression != null)
|
if (TreeComponent.ChildrenExpression != null)
|
||||||
return TreeComponent.ChildrenExpression(this) ?? new List<TItem>();
|
return TreeComponent.ChildrenExpression(this)?.ToList() ?? new List<TItem>();
|
||||||
else
|
else
|
||||||
return new List<TItem>();
|
return new List<TItem>();
|
||||||
}
|
}
|
||||||
@ -789,8 +876,6 @@ namespace AntDesign
|
|||||||
|
|
||||||
#endregion Node data operation
|
#endregion Node data operation
|
||||||
|
|
||||||
bool _defaultBinding;
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
protected override void OnInitialized()
|
||||||
{
|
{
|
||||||
SetTreeNodeClassMapper();
|
SetTreeNodeClassMapper();
|
||||||
@ -817,73 +902,22 @@ namespace AntDesign
|
|||||||
if (TreeComponent.Selectable && TreeComponent.SelectedKeys != null)
|
if (TreeComponent.Selectable && TreeComponent.SelectedKeys != null)
|
||||||
{
|
{
|
||||||
this.Selected = TreeComponent.SelectedKeys.Any(k => k == this.Key);
|
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();
|
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);
|
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()
|
public bool IsPicture()
|
||||||
{
|
{
|
||||||
string[] imageTypes = new[] { ".jpg", ".png", ".gif", ".ico",".jfif",".jpeg",".bmp",".tga",".svg",".tif" };
|
if (string.IsNullOrEmpty(Ext))
|
||||||
Ext = FileName.Substring(FileName.LastIndexOf('.'));
|
{
|
||||||
return imageTypes.Any(imageType => imageType.Equals(Ext, StringComparison.InvariantCultureIgnoreCase));
|
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
|
$ 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">
|
<div class="pic-plus">
|
||||||
<img width="150" src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg">
|
<img width="150" src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg">
|
||||||
<span>+</span>
|
<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>
|
</div>
|
||||||
|
|
||||||
<style>
|
<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 [.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.
|
- 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 |
|
| 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
|
- Install the template
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ dotnet new --install AntDesign.Templates::0.1.0-*
|
$ dotnet new --install AntDesign.Templates
|
||||||
```
|
```
|
||||||
|
|
||||||
- Create the Boilerplate project with the template
|
- 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
|
- Go to the project folder of the application and install the Nuget package reference
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ dotnet add package AntDesign --version 0.1.0-*
|
$ dotnet add package AntDesign
|
||||||
```
|
```
|
||||||
|
|
||||||
- Register the services
|
- Register the services
|
||||||
@ -148,7 +148,7 @@ Options for the template:
|
|||||||
|
|
||||||
## 🔨 Local Development
|
## 🔨 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)
|
- Install Node.js (only for building style files and interoperable TypeScript files)
|
||||||
- Clone to local development
|
- 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.
|
- 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
|
## 🔗 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)
|
- [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)
|
- [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
|
## 🤝 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)
|
[![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">
|
<div class="pic-plus">
|
||||||
<img width="150" src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg">
|
<img width="150" src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg">
|
||||||
<span>+</span>
|
<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>
|
</div>
|
||||||
|
|
||||||
<style>
|
<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 混合客户端环境中。
|
- 可直接运行在 [.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 标准的环境上
|
- 可直接运行在 [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 |
|
| Edge 16 / IE 11† | 522 | 57 | 11 | 44 | Chromium 57 |
|
||||||
|
|
||||||
@ -76,7 +76,7 @@ title: Ant Design of Blazor
|
|||||||
- 安装模板
|
- 安装模板
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ dotnet new --install AntDesign.Templates::0.1.0-*
|
$ dotnet new --install AntDesign.Templates
|
||||||
```
|
```
|
||||||
|
|
||||||
- 从模板创建 Ant Design Blazor Pro 项目
|
- 从模板创建 Ant Design Blazor Pro 项目
|
||||||
@ -98,7 +98,7 @@ title: Ant Design of Blazor
|
|||||||
- 进入应用的项目文件夹,安装 Nuget 包引用
|
- 进入应用的项目文件夹,安装 Nuget 包引用
|
||||||
|
|
||||||
```bash
|
```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) (中文)
|
- [![钉钉群](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。广告勿扰。
|
- 另外,我还创立了面向中文开发者的 Blazor 中文社区,高手如云,只讨论技术,无卖课广告。可以加我微信(JamesYeungMVP)拉进微信群,另外也有一个 QQ 群 1012762441。广告勿扰。
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@
|
|||||||
"husky": "^4.2.3",
|
"husky": "^4.2.3",
|
||||||
"inquirer": "^7.1.0",
|
"inquirer": "^7.1.0",
|
||||||
"jquery": "^3.4.1",
|
"jquery": "^3.4.1",
|
||||||
"jsdom": "^16.0.0",
|
"jsdom": "^16.5.0",
|
||||||
"less": "^4.1.0",
|
"less": "^4.1.0",
|
||||||
"less-plugin-clean-css": "^1.5.1",
|
"less-plugin-clean-css": "^1.5.1",
|
||||||
"less-plugin-npm-import": "^2.1.0",
|
"less-plugin-npm-import": "^2.1.0",
|
||||||
@ -76,4 +76,4 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"antblazor.js-ts.tests": "file:tests/AntDesign.Tests.Js"
|
"antblazor.js-ts.tests": "file:tests/AntDesign.Tests.Js"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -22,7 +22,7 @@
|
|||||||
#if NET5_0_OR_GREATER
|
#if NET5_0_OR_GREATER
|
||||||
var polyfillPath = "_framework/blazor.polyfill.min.js";
|
var polyfillPath = "_framework/blazor.polyfill.min.js";
|
||||||
#else
|
#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
|
#endif
|
||||||
#if NET6_0
|
#if NET6_0
|
||||||
var isNET6 = true;
|
var isNET6 = true;
|
||||||
|
@ -1,17 +1,41 @@
|
|||||||
@inject DrawerService DrawerService
|
@inject DrawerService DrawerService
|
||||||
@inject ConfirmService confirmService
|
@inject ConfirmService confirmService
|
||||||
|
|
||||||
<Input @bind-Value="@value" />
|
<Space Direction="DirectionVHType.Vertical">
|
||||||
<br />
|
<SpaceItem>
|
||||||
<br />
|
<Space>
|
||||||
<Button OnClick="OpenComponent" Type="primary">Use Component</Button>
|
<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{
|
@code{
|
||||||
|
|
||||||
|
// #region use component
|
||||||
private string value = "blazor";
|
private string value = "blazor";
|
||||||
|
|
||||||
|
|
||||||
// use component
|
|
||||||
private async Task OpenComponent()
|
private async Task OpenComponent()
|
||||||
{
|
{
|
||||||
var options = new DrawerOptions()
|
var options = new DrawerOptions()
|
||||||
@ -24,13 +48,13 @@
|
|||||||
|
|
||||||
drawerRef.OnOpen = () =>
|
drawerRef.OnOpen = () =>
|
||||||
{
|
{
|
||||||
Console.WriteLine("OnAfterOpen");
|
Console.WriteLine("drawerRef OnOpen");
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
};
|
};
|
||||||
|
|
||||||
drawerRef.OnClosing = async handle =>
|
drawerRef.OnClosing = async handle =>
|
||||||
{
|
{
|
||||||
Console.WriteLine("OnAfterClosing:");
|
Console.WriteLine("drawerRef OnClosing");
|
||||||
|
|
||||||
if (await confirmService.Show("Drawer to close?", "Confirm?", ConfirmButtons.YesNo) == ConfirmResult.No)
|
if (await confirmService.Show("Drawer to close?", "Confirm?", ConfirmButtons.YesNo) == ConfirmResult.No)
|
||||||
{
|
{
|
||||||
@ -40,11 +64,38 @@
|
|||||||
|
|
||||||
drawerRef.OnClosed = async result =>
|
drawerRef.OnClosed = async result =>
|
||||||
{
|
{
|
||||||
Console.WriteLine("OnAfterClosed:" + result);
|
Console.WriteLine("drawerRef OnClosed, value:" + result);
|
||||||
if (result != null)
|
if (result != null)
|
||||||
value = result;
|
value = result;
|
||||||
await InvokeAsync(StateHasChanged);
|
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 的事件处理
|
||||||
|
|
||||||
|
对于 Drawer 组件:
|
||||||
|
1. OnOpen: 在打开前执行,并可以通过参数的 `Cancel` 属性取消打开操作。
|
||||||
|
2. OnClose: 在关闭前执行,你需要通过它来控制 Drawer 组件的 `Visible` 属性。
|
||||||
|
|
||||||
|
对于 DrawerService:
|
||||||
|
1. DrawerRef.OnOpen: 在打开前执行,内部是在 `Drawe.OnOpen` 事件中调用该方法
|
||||||
|
2. DrawerRef.OnClosing: 在关闭前执行
|
||||||
|
3. DrawerRef.OnClosed: 在关闭后执行。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## en-US
|
## 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 | - |
|
| ChildContent | Subcomponent | object | - |
|
||||||
| MaskClosable | Clicking on the mask (area outside the Drawer) to close the Drawer or not. | boolean | true |
|
| 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 | - |
|
| 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` |
|
| 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 | - |
|
| 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 |
|
| Height | placement is top or bottom, height of the Drawer dialog. | int | 256 |
|
||||||
| ZIndex | The z-index of the Drawer. | int | - |
|
| ZIndex | The z-index of the Drawer. | int | - |
|
||||||
| OffsetX | The the X coordinate offset(px), only when placement is `'left'` or `'right'`. | int | 0 |
|
| 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 |
|
| 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 | - |
|
| Visible | Whether the Drawer dialog is visible or not. | boolean | - |
|
||||||
| Keyboard | Whether support press esc to close | boolean | true |
|
| 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) | - |
|
| OnClose | Specify a callback that will be called when a user clicks mask, close button or Cancel button. | EventCallback | - |
|
||||||
| OnViewInit | Specify a callback that will be called before drawer displayed | function(e) | - |
|
| OnOpen | Specify a callback that will be called after drawer rendered | Func<Task> | - |
|
||||||
|
|
||||||
### DrawerService
|
### 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` |
|
| CloseOnNavigation | Whether to close the drawer when the navigation history changes | `boolean` | `true` |
|
||||||
| Keyboard | Whether to support keyboard esc off | `boolean` | `true` |
|
| Keyboard | Whether to support keyboard esc off | `boolean` | `true` |
|
||||||
| MaskStyle | Style for Drawer's mask element. | `string` | `{}` |
|
| 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>` | - |
|
| Title | The title for Drawer. | `OneOf<RenderFragment, string>` | - |
|
||||||
| Width | Width of the Drawer dialog. | `int` | `256` |
|
| Width | Width of the Drawer dialog. | `int` | `256` |
|
||||||
| Height | Height of the Drawer dialog, only when placement is `'top'` or `'bottom'`. | `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 | - |
|
| Title | 标题 | string or slot | - |
|
||||||
| BodyStyle | 可用于设置 Drawer 内容部分的样式 | object | - |
|
| BodyStyle | 可用于设置 Drawer 内容部分的样式 | object | - |
|
||||||
| Closable | 是否显示右上角的关闭按钮 | boolean | true |
|
| Closable | 是否显示右上角的关闭按钮 | boolean | true |
|
||||||
| ChildContent | 抽屉元素之间的子组件 | object | - |
|
| ChildContent | 抽屉元素之间的子组件 | object | - |
|
||||||
| MaskClosable | 点击蒙层是否允许关闭 | boolean | true |
|
| MaskClosable | 点击蒙层是否允许关闭 | boolean | true |
|
||||||
| MaskStyle | 遮罩样式 | object | - |
|
| MaskStyle | 遮罩样式 | object | - |
|
||||||
| Placement | 抽屉的方向,可选值为 `left` , `top`,`right`,`bottom` | string | `right` |
|
| Mask | 是否展示遮罩 | boolean | true |
|
||||||
|
| Placement | 抽屉的方向,可选值为 `left` , `top`,`right`,`bottom` | string | right |
|
||||||
| WrapClassName | 对话框外层容器的类名 | string | - |
|
| WrapClassName | 对话框外层容器的类名 | string | - |
|
||||||
| Width | 宽度 | string\|int | 256 |
|
| Width | 宽度 | string\|int | 256 |
|
||||||
| Height | 高度, 在 placement 为 top 或 bottom 时使用 | | int |
|
| Height | 高度, 在 placement 为 top 或 bottom 时使用 | | int |
|
||||||
| ZIndex | 设置 Drawer 的 z-index | int | - |
|
| ZIndex | 设置 Drawer 的 z-index | int | - |
|
||||||
| OffsetX | X 轴方向的偏移量,只在方向为 `'left'`或`'right'` 时生效 | int | 0 |
|
| OffsetX | X 轴方向的偏移量,只在方向为 `'left'`或`'right'` 时生效 | int | 0 |
|
||||||
| OffsetY | Y 轴方向的偏移量,只在方向为 `'top'`或`'bottom'` 时生效 | int | 0 |
|
| OffsetY | Y 轴方向的偏移量,只在方向为 `'top'`或`'bottom'` 时生效 | int | 0 |
|
||||||
| Visible | Drawer 是否可见 | boolean | - |
|
| Visible | Drawer 是否可见 | boolean | - |
|
||||||
| Keyboard | 是否支持键盘 esc 关闭 | boolean | true |
|
| Keyboard | 是否支持键盘 esc 关闭 | boolean | true |
|
||||||
| OnClose | 点击遮罩层或右上角叉或取消按钮的回调 | function(e) | - |
|
| OnClose | 点击遮罩层或右上角叉或取消按钮的回调 | EventCallback | - |
|
||||||
| OnViewInit | 抽屉显示之前回调事件 | function(e) | - |
|
| OnOpen | 抽屉渲染之后回调事件 | Func<Task> | - |
|
||||||
|
|
||||||
### DrawerService
|
### DrawerService
|
||||||
|
|
||||||
@ -58,7 +59,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/7z8NJQhFb/Drawer.svg
|
|||||||
| CloseOnNavigation | 导航历史变化时是否关闭抽屉组件 | `boolean` | `true` |
|
| CloseOnNavigation | 导航历史变化时是否关闭抽屉组件 | `boolean` | `true` |
|
||||||
| Keyboard | 是否支持键盘 esc 关闭 | `boolean` | `true` |
|
| Keyboard | 是否支持键盘 esc 关闭 | `boolean` | `true` |
|
||||||
| MaskStyle | 遮罩样式 | `string` | `{}` |
|
| MaskStyle | 遮罩样式 | `string` | `{}` |
|
||||||
| BodyStyle | Modal body 样式 | `string` | `{}` |
|
| BodyStyle | Drawer body 样式 | `string` | `{}` |
|
||||||
| Title | 标题 | `OneOf<RenderFragment, string>` | - |
|
| Title | 标题 | `OneOf<RenderFragment, string>` | - |
|
||||||
| Width | 宽度 | `int` | `256` |
|
| Width | 宽度 | `int` | `256` |
|
||||||
| Height | 高度, 只在方向为 `'top'`或`'bottom'` 时生效 | `int` | `256` |
|
| Height | 高度, 只在方向为 `'top'`或`'bottom'` 时生效 | `int` | `256` |
|
||||||
|
@ -15,7 +15,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/ORmcdeaoO/Form.svg
|
|||||||
- 需要对输入的数据类型进行校验时。
|
- 需要对输入的数据类型进行校验时。
|
||||||
|
|
||||||
## API
|
## API
|
||||||
### From
|
### Form
|
||||||
| 名称 | 说明 | 类型 | 默认值 |
|
| 名称 | 说明 | 类型 | 默认值 |
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| Layout | 表单布局 | [FormLayout](https://github.com/ant-design-blazor/ant-design-blazor/blob/master/components/form/types/FormLayout.cs) | FormLayout.Horizontal |
|
| 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\> | - |
|
| OnFinish | 提交事件 | EventCallback\<EditContext\> | - |
|
||||||
| OnFinishFailed | 提交失败(校验失败)回调事件 | EventCallback\<EditContext\> | - |
|
| OnFinishFailed | 提交失败(校验失败)回调事件 | EventCallback\<EditContext\> | - |
|
||||||
| ValidateOnChange | 是否在更改时校验 | bool | false |
|
| ValidateOnChange | 是否在更改时校验 | bool | false |
|
||||||
### FromItem
|
### FormItem
|
||||||
| 名称 | 说明 | 类型 | 默认值 |
|
| 名称 | 说明 | 类型 | 默认值 |
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| Label | **label** 标签的文本 | string | input组件的Display或者DisplayName特性 |
|
| Label | **label** 标签的文本 | string | input组件的Display或者DisplayName特性 |
|
||||||
|
@ -1,15 +1,18 @@
|
|||||||
@inject IconService iconService;
|
@inject IconService iconService;
|
||||||
|
|
||||||
<div class="icons-list">
|
<div class="icons-list">
|
||||||
<IconFont Type="icon-tuichu" />
|
<IconFont Type="icon-tuichu" />
|
||||||
<IconFont Type="icon-facebook" />
|
<IconFont Type="icon-facebook" />
|
||||||
<IconFont Type="icon-twitter" />
|
<IconFont Type="icon-twitter" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@code
|
@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;
|
@inject IconService iconService;
|
||||||
|
|
||||||
<div class="icons-list">
|
<div class="icons-list">
|
||||||
<IconFont Type="icon-javascript" />
|
<IconFont Type="icon-javascript" />
|
||||||
<IconFont Type="icon-java" />
|
<IconFont Type="icon-java" />
|
||||||
<IconFont Type="icon-shoppingcart" />
|
<IconFont Type="icon-shoppingcart" />
|
||||||
<IconFont Type="icon-python" />
|
<IconFont Type="icon-python" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@code
|
@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_1788044_0dwu4guekcwr.js");
|
||||||
await iconService.CreateFromIconfontCN("//at.alicdn.com/t/font_1788592_a5xf2bdic3u.js");
|
await iconService.CreateFromIconfontCN("//at.alicdn.com/t/font_1788592_a5xf2bdic3u.js");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -9,6 +9,10 @@ title:
|
|||||||
|
|
||||||
对于使用 [iconfont.cn](http://iconfont.cn/) 的用户,通过设置 `createFromIconfontCN` 方法参数对象中的 `scriptUrl` 字段, 即可轻松地使用已有项目中的图标。
|
对于使用 [iconfont.cn](http://iconfont.cn/) 的用户,通过设置 `createFromIconfontCN` 方法参数对象中的 `scriptUrl` 字段, 即可轻松地使用已有项目中的图标。
|
||||||
|
|
||||||
|
> 注意:这个方法会涉及JS互操作,因此需要确保在 `firstRender=true` 时调用。
|
||||||
|
|
||||||
## en-US
|
## 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
|
## 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
|
## 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
|
<Layout>
|
||||||
{
|
<Sider @bind-Collapsed=@collapsed NoTrigger OnCollapse="OnCollapse">
|
||||||
bool collapsed;
|
|
||||||
|
|
||||||
void toggle()
|
|
||||||
{
|
|
||||||
collapsed = !collapsed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
<Layout>
|
|
||||||
<Sider Collapsible Collapsed=@collapsed NoTrigger OnCollapse="OnCollapse">
|
|
||||||
<div class="logo" />
|
<div class="logo" />
|
||||||
<Menu Theme="MenuTheme.Dark" Mode="MenuMode.Inline" DefaultSelectedKeys=@(new[]{"1"})>
|
<Menu Theme="MenuTheme.Dark" Mode="MenuMode.Inline" DefaultSelectedKeys=@(new[]{"1"})>
|
||||||
<MenuItem Key="1">
|
<MenuItem Key="1">
|
||||||
@ -69,6 +59,12 @@
|
|||||||
|
|
||||||
|
|
||||||
@code{
|
@code{
|
||||||
|
bool collapsed;
|
||||||
|
|
||||||
|
void toggle()
|
||||||
|
{
|
||||||
|
collapsed = !collapsed;
|
||||||
|
}
|
||||||
|
|
||||||
void OnCollapse(bool isCollapsed)
|
void OnCollapse(bool isCollapsed)
|
||||||
{
|
{
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
<h3>CustomTriggerDebug</h3>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
}
|
|
@ -1,12 +1,8 @@
|
|||||||
<Layout>
|
<Layout>
|
||||||
<Sider Breakpoint="@BreakpointType.Lg"
|
<Sider Breakpoint="@BreakpointType.Lg"
|
||||||
CollapsedWidth="64"
|
CollapsedWidth="64"
|
||||||
OnBreakpoint="@(broken => {
|
@bind-Collapsed=@collapsed
|
||||||
Console.WriteLine($"OnBreakpoint:{broken}");
|
>
|
||||||
})"
|
|
||||||
OnCollapse="@(collapsed => {
|
|
||||||
Console.WriteLine($"collapsed:{collapsed}");
|
|
||||||
})">
|
|
||||||
<div class="logo" />
|
<div class="logo" />
|
||||||
<Menu Theme="MenuTheme.Dark" Mode="MenuMode.Inline" DefaultSelectedKeys=@(new[]{"4"})>
|
<Menu Theme="MenuTheme.Dark" Mode="MenuMode.Inline" DefaultSelectedKeys=@(new[]{"4"})>
|
||||||
<MenuItem Key="1">
|
<MenuItem Key="1">
|
||||||
@ -38,6 +34,10 @@
|
|||||||
</Layout>
|
</Layout>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
||||||
|
@code{
|
||||||
|
bool collapsed;
|
||||||
|
}
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
#components-layout-demo-responsive .logo {
|
#components-layout-demo-responsive .logo {
|
||||||
height: 32px;
|
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 |
|
| Checked | Specifies whether the radio is selected. | boolean |
|
||||||
| DefaultChecked | Specifies the initial state: whether or not the radio is selected. | boolean |- |
|
| DefaultChecked | Specifies the initial state: whether or not the radio is selected. | boolean |- |
|
||||||
| Disabled | Disable radio | string | - |
|
| 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 | - |
|
| Value | According to value for comparison, to determine whether the selected | string | - |
|
||||||
|
|
||||||
RadioGroup
|
RadioGroup
|
||||||
|
@ -24,6 +24,7 @@ Radio/Radio.Button
|
|||||||
| Checked | 指定当前是否选中 | boolean |
|
| Checked | 指定当前是否选中 | boolean |
|
||||||
| DefaultChecked | 初始是否选中 | boolean |- |
|
| DefaultChecked | 初始是否选中 | boolean |- |
|
||||||
| Disabled | 禁用 Radio | string | - |
|
| Disabled | 禁用 Radio | string | - |
|
||||||
|
| RadioButton | 设置为 TRUE 以将radio风格设置为按钮组 | bool | false |
|
||||||
| Value | 根据 value 进行比较,判断是否选中 | string | - |
|
| Value | 根据 value 进行比较,判断是否选中 | string | - |
|
||||||
|
|
||||||
RadioGroup
|
RadioGroup
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
<Col Span="24">
|
<Col Span="24">
|
||||||
<CountDown Title="Day Level" Value="@deadline" Format="dd 天 h 小时 m 分钟 s 秒" />
|
<CountDown Title="Day Level" Value="@deadline" Format="dd 天 h 小时 m 分钟 s 秒" />
|
||||||
</Col>
|
</Col>
|
||||||
|
<br/>
|
||||||
|
<Button OnClick="OnReset">Reset Value</Button>
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
@code
|
@code
|
||||||
@ -18,4 +20,9 @@
|
|||||||
{
|
{
|
||||||
Console.WriteLine("finished!");
|
Console.WriteLine("finished!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OnReset()
|
||||||
|
{
|
||||||
|
deadline = DateTime.Now.AddMinutes(10);
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,25 +1,22 @@
|
|||||||
@using System.ComponentModel
|
@using System.ComponentModel
|
||||||
@using AntDesign.TableModels
|
@using AntDesign.TableModels
|
||||||
|
|
||||||
<Table TItem="Dictionary<string, object>" DataSource="@data" Loading="data==null" ScrollX="1500" PageSize="5">
|
<Table TItem="Dictionary<string, object>" OnChange="HanleChange" DataSource="@data" Loading="data==null" ScrollX="1500" PageSize="5" Size="TableSize.Small">
|
||||||
@if (data?.Any() == true)
|
@foreach (var key in data?.FirstOrDefault()?.Keys.Take(10) ??new string[0])
|
||||||
{
|
{
|
||||||
@foreach (var key in data.FirstOrDefault()?.Keys.Take(10))
|
<PropertyColumn Property=@(c=>c[key]) Title="@key"></PropertyColumn>
|
||||||
{
|
}
|
||||||
<Column TData="object" DataIndex=@($"['{key}']") Title="@key"></Column>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</Table>
|
</Table>
|
||||||
|
|
||||||
@inject HttpClient httpClient;
|
@inject HttpClient httpClient;
|
||||||
@code {
|
@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()
|
protected async Task HanleChange(QueryModel<Dictionary<string, object>> query)
|
||||||
{
|
{
|
||||||
data = await httpClient.GetFromJsonAsync<List<Dictionary<string, object>>>(githubUrl);
|
data = await httpClient.GetFromJsonAsync<List<Dictionary<string, object>>>(githubUrl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
DefaultExpandedKeys="@(new[] { "0-0-0", "0-0-1"})"
|
DefaultExpandedKeys="@(new[] { "0-0-0", "0-0-1"})"
|
||||||
DefaultSelectedKeys="@(new[] {"0-0-0", "0-0-1" })"
|
DefaultSelectedKeys="@(new[] {"0-0-0", "0-0-1" })"
|
||||||
DefaultCheckedKeys="@(new[] {"0-0-0", "0-0-1" })"
|
DefaultCheckedKeys="@(new[] {"0-0-0", "0-0-1" })"
|
||||||
SelectedNodeChanged="SelectedNodeChanged"
|
SelectedNodeChanged="SelectedNodeChanged"
|
||||||
OnSelect="OnSelect"
|
OnSelect="OnSelect"
|
||||||
OnCheck="OnCheck">
|
OnCheck="OnCheck">
|
||||||
<TreeNode Title="parent 1" Key="0-0" TItem="string">
|
<TreeNode Title="parent 1" Key="0-0" TItem="string">
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
<h3>Async</h3>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
|
||||||
|
}
|
@ -3,14 +3,13 @@
|
|||||||
@bind-Value="value"
|
@bind-Value="value"
|
||||||
Placeholder="Please select"
|
Placeholder="Please select"
|
||||||
AllowClear
|
AllowClear
|
||||||
TreeDefaultExpandAll
|
TreeDefaultExpandAll>
|
||||||
OnChange="OnChange">
|
|
||||||
<TreeNode TItem="string" Key="parent 1" Title="parent 1">
|
<TreeNode TItem="string" Key="parent 1" Title="parent 1">
|
||||||
<TreeNode TItem="string" Key="parent 1-0" title="parent 1-0">
|
<TreeNode TItem="string" Key="parent 1-0" Title="parent 1-0">
|
||||||
<TreeNode TItem="string" Key="leaf1" title="leaf1" />
|
<TreeNode TItem="string" Key="leaf1" Title="leaf1" />
|
||||||
<TreeNode TItem="string" Key="leaf2" title="leaf2" />
|
<TreeNode TItem="string" Key="leaf2" Title="leaf2" />
|
||||||
</TreeNode>
|
</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">
|
<TreeNode TItem="string" Key="leaf3">
|
||||||
<TitleTemplate>
|
<TitleTemplate>
|
||||||
<b Style="color:#08c;">leaf3</b>
|
<b Style="color:#08c;">leaf3</b>
|
||||||
@ -22,10 +21,5 @@
|
|||||||
|
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private string value;
|
private string value="leaf3";
|
||||||
|
|
||||||
public void OnChange()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -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"
|
<TreeSelect TItem="string"
|
||||||
Style="width:100%;"
|
Style="width:100%;"
|
||||||
@bind-Value="value"
|
@bind-Values="values"
|
||||||
|
DropdownStyle="max-height:400px;overflow:auto;"
|
||||||
Placeholder="Please select"
|
Placeholder="Please select"
|
||||||
AllowClear
|
AllowClear
|
||||||
Multiple
|
Multiple
|
||||||
TreeDefaultExpandAll
|
TreeDefaultExpandAll>
|
||||||
OnChange="OnValuesChange">
|
<TreeNode TItem="string" Key="parent 1" Title="parent 1">
|
||||||
<TreeNode TItem="string" Key="parent 1" title="parent 1">
|
<TreeNode TItem="string" Key="parent 1-0" Title="parent 1-0">
|
||||||
<TreeNode TItem="string" Key="parent 1-0" title="parent 1-0">
|
<TreeNode TItem="string" Key="leaf1" Title="my leaf" />
|
||||||
<TreeNode TItem="string" Key="leaf1" title="my leaf" />
|
<TreeNode TItem="string" Key="leaf2" Title="your leaf" />
|
||||||
<TreeNode TItem="string" Key="leaf2" title="your leaf" />
|
|
||||||
</TreeNode>
|
</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">
|
<TreeNode TItem="string" Key="sss">
|
||||||
<TitleTemplate>
|
<TitleTemplate>
|
||||||
<b style=" color: #08c;">sss</b>
|
<b style=" color: #08c;">sss</b>
|
||||||
@ -21,13 +21,10 @@
|
|||||||
</TreeNode>
|
</TreeNode>
|
||||||
</TreeSelect>
|
</TreeSelect>
|
||||||
|
|
||||||
|
@JsonSerializer.Serialize(values);
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
|
|
||||||
private string value;
|
private IEnumerable<string> values=new[]{"leaf1","leaf2"};
|
||||||
|
|
||||||
public void OnValuesChange(IEnumerable<string> args)
|
|
||||||
{
|
|
||||||
Console.WriteLine(string.Join(',', args));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -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%;"
|
||||||
<TreeSelect TItem="Data"
|
DataSource="treeData"
|
||||||
Style="width:100%;"
|
@bind-Value="@value"
|
||||||
DataSource="treeData"
|
Placeholder="Please select"
|
||||||
@bind-Value="@value"
|
AllowClear
|
||||||
Placeholder="Please select"
|
Multiple
|
||||||
AllowClear
|
TreeDefaultExpandAll
|
||||||
Multiple
|
ChildrenExpression="node=>node.DataItem.Children"
|
||||||
TitleExpression="data => data.Title"
|
TitleExpression="node=>node.DataItem.Title"
|
||||||
KeyExpression="data => data.Value"
|
KeyExpression="node=>node.DataItem.Key"
|
||||||
ChildrenExpression="data => data.Children "
|
IsLeafExpression="node=>node.DataItem.Children==null">
|
||||||
IsLeafExpression="(menus, data) => data.Children == null "
|
|
||||||
TreeDefaultExpandAll>
|
|
||||||
</TreeSelect>
|
</TreeSelect>
|
||||||
|
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private string value;
|
private string value;
|
||||||
|
|
||||||
Data[] treeData = new Data[]
|
Data[] treeData = new Data[]
|
||||||
{
|
{
|
||||||
new()
|
new()
|
||||||
{
|
{
|
||||||
Title = "Node1",
|
Title = "Node1",
|
||||||
Value = "0-0",
|
Key = "0-0",
|
||||||
Children = new Data[]
|
Children = new Data[]
|
||||||
{
|
{
|
||||||
new()
|
new()
|
||||||
{
|
{
|
||||||
Title = "Child Node1",
|
Title = "Child Node1",
|
||||||
Value = "0-0-1",
|
Key = "0-0-1",
|
||||||
},
|
},
|
||||||
new()
|
new()
|
||||||
{
|
{
|
||||||
Title = "Child Node2",
|
Title = "Child Node2",
|
||||||
Value = "0-0-2",
|
Key = "0-0-2",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new()
|
new()
|
||||||
{
|
{
|
||||||
Title = "Node2",
|
Title = "Node2",
|
||||||
Value = "0-1",
|
Key = "0-1",
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public class Data
|
public class Data : ITreeData<Data>
|
||||||
{
|
{
|
||||||
public string Value { get; set; }
|
public string Key { get; set; }
|
||||||
public string Title { get; set; }
|
public Data Value => this;
|
||||||
public Data[] Children { get; set; }
|
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
|
## zh-CN
|
||||||
|
|
||||||
最简单的用法,展示动态下拉树功能。
|
最简单的用法。
|
||||||
|
|
||||||
## en-US
|
## 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
|
order: 1
|
||||||
title:
|
title:
|
||||||
zh-CN: 多选
|
zh-CN: 多选
|
||||||
en-US: multiple
|
en-US: Multiple Selection
|
||||||
---
|
---
|
||||||
|
|
||||||
## zh-CN
|
## zh-CN
|
||||||
|
|
||||||
最简单的用法,展示多选功能。其中RootValue用于筛选DataSources中第一级的节点。
|
多选的树选择。
|
||||||
|
|
||||||
## en-US
|
## 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
|
## zh-CN
|
||||||
|
|
||||||
使用 `treeData` 把 JSON 数据直接生成树结构。
|
使用 `DataSource` 把 IEnumerable<T> 数据直接生成树结构。
|
||||||
|
|
||||||
## en-US
|
## 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
|
@Title
|
||||||
</div>
|
</div>
|
||||||
<div class="code-box-description">
|
<div class="code-box-description">
|
||||||
<Markdown>@Description</Markdown>
|
@Description
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,25 +1,44 @@
|
|||||||
@using System.Text.RegularExpressions
|
@using System.Text.RegularExpressions
|
||||||
@inherits AntDesignTestBase
|
@inherits AntDesignTestBase
|
||||||
@code {
|
@code {
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void InputNumber_formatter_parser_change_value()
|
public void InputNumber_formatter_parser_change_value()
|
||||||
{
|
{
|
||||||
//Arrange
|
//Arrange
|
||||||
#pragma warning disable CS0618 // Type or member is obsolete
|
#pragma warning disable CS0618 // Type or member is obsolete
|
||||||
JSInterop.SetupVoid(JSInteropConstants.Focus, _ => true).SetVoidResult();
|
JSInterop.SetupVoid(JSInteropConstants.Focus, _ => true).SetVoidResult();
|
||||||
#pragma warning restore CS0618 // Type or member is obsolete
|
#pragma warning restore CS0618 // Type or member is obsolete
|
||||||
AntDesign.InputNumber<double>? input = null;
|
AntDesign.InputNumber<double>? input = null;
|
||||||
Func<double, string> formatter = v => "$ " + v.ToString("n0");
|
Func<double, string> formatter = v => "$ " + v.ToString("n0");
|
||||||
Func<string, string> parser = v => Regex.Replace(v, @"\$\s?|(,*)", "");
|
Func<string, string> parser = v => Regex.Replace(v, @"\$\s?|(,*)", "");
|
||||||
|
|
||||||
var cut = Render<AntDesign.InputNumber<double>>(
|
var cut = Render<AntDesign.InputNumber<double>>(
|
||||||
@<AntDesign.InputNumber @ref="@input" Formatter="formatter" Parser="parser" DefaultValue="1000d"/>
|
@<AntDesign.InputNumber @ref="@input" Formatter="formatter" Parser="parser" DefaultValue="1000d" />
|
||||||
);
|
);
|
||||||
//Act
|
//Act
|
||||||
cut.Find("input").Change("$ 10");
|
cut.Find("input").Change("$ 10");
|
||||||
//Assert
|
//Assert
|
||||||
cut.Instance.Value.Should().Be(10);
|
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