mirror of
https://github.com/radzenhq/radzen-blazor.git
synced 2026-02-04 05:35:44 +00:00
Compare commits
483 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dc67a0b0fc | ||
|
|
1258bbc770 | ||
|
|
5960318a60 | ||
|
|
d4faf758f4 | ||
|
|
f88216b9a0 | ||
|
|
e21d648588 | ||
|
|
dbcbdc9bbc | ||
|
|
c5d16e8381 | ||
|
|
ac1aa6f3b1 | ||
|
|
866c222c74 | ||
|
|
06843477cb | ||
|
|
9a7a6fc6ab | ||
|
|
4986da415f | ||
|
|
cdbd20b794 | ||
|
|
49567ade65 | ||
|
|
4d857449d2 | ||
|
|
dc03621a14 | ||
|
|
b83cca17e2 | ||
|
|
343afffd40 | ||
|
|
163eac9511 | ||
|
|
167bfcb0b3 | ||
|
|
f0f94eb84c | ||
|
|
7123c9ca12 | ||
|
|
41e12d8e54 | ||
|
|
473ab14ae6 | ||
|
|
127ffd451c | ||
|
|
32bb43b66f | ||
|
|
765f5acbcc | ||
|
|
8ac137f22d | ||
|
|
10bbf6b157 | ||
|
|
390dc0605b | ||
|
|
6fda9f0691 | ||
|
|
0a1c5830d2 | ||
|
|
33efa2316d | ||
|
|
b3de9374a7 | ||
|
|
1d869e8d2b | ||
|
|
56156dd5ff | ||
|
|
35c9f55c41 | ||
|
|
e70e3559eb | ||
|
|
5957439475 | ||
|
|
322ed552ed | ||
|
|
bf848d5ef8 | ||
|
|
285057a9df | ||
|
|
4de62ffa55 | ||
|
|
f97fde1387 | ||
|
|
8a5bba625c | ||
|
|
108a209ac8 | ||
|
|
8390a4aba9 | ||
|
|
9740416e56 | ||
|
|
8cc82642f9 | ||
|
|
5f4804f4cf | ||
|
|
24dbee5d3d | ||
|
|
298f84d25e | ||
|
|
182c66f0a9 | ||
|
|
fd11c34646 | ||
|
|
6bcc7388bb | ||
|
|
60da0c0082 | ||
|
|
2b2b48bec4 | ||
|
|
d579f79399 | ||
|
|
bf85df68b3 | ||
|
|
e6e7ec49df | ||
|
|
e7801e1222 | ||
|
|
3327254022 | ||
|
|
d53d09e358 | ||
|
|
34c02ac391 | ||
|
|
cf4eb0c9cd | ||
|
|
ee6220b1fe | ||
|
|
a264638726 | ||
|
|
3e6a10a57d | ||
|
|
5258816770 | ||
|
|
fb4457f9a1 | ||
|
|
627a74038c | ||
|
|
54c297e898 | ||
|
|
a4d7201f7d | ||
|
|
b04cf69b90 | ||
|
|
ea654f0b8d | ||
|
|
9b16aaf9e4 | ||
|
|
87672de761 | ||
|
|
171a8def6d | ||
|
|
f09179f4cd | ||
|
|
03f62068b3 | ||
|
|
828b4230e3 | ||
|
|
2b23e5d472 | ||
|
|
17dbe70460 | ||
|
|
587c3a0647 | ||
|
|
83f0879b11 | ||
|
|
212b741828 | ||
|
|
ee81b608f9 | ||
|
|
ad17080ee8 | ||
|
|
6a8611c348 | ||
|
|
3ba3610b21 | ||
|
|
8deed23e01 | ||
|
|
356106263b | ||
|
|
0566244b61 | ||
|
|
17d76b4e6f | ||
|
|
9c3490f275 | ||
|
|
b1b6499d7c | ||
|
|
a36a74091f | ||
|
|
4dfbd676af | ||
|
|
f72f8b3e39 | ||
|
|
45cc6880f9 | ||
|
|
17281cd3b1 | ||
|
|
332b452b56 | ||
|
|
c647515186 | ||
|
|
6faf0ed9b9 | ||
|
|
fad024d9bb | ||
|
|
67718df278 | ||
|
|
273c3283c2 | ||
|
|
aa7306ebd1 | ||
|
|
56cb173ad5 | ||
|
|
174f0a9393 | ||
|
|
a1dbc1a6fb | ||
|
|
d9de2ee0bc | ||
|
|
cf1e0eda27 | ||
|
|
ccc82e5a61 | ||
|
|
0859f939dd | ||
|
|
519c133c0c | ||
|
|
9f62860821 | ||
|
|
238ed1ac2c | ||
|
|
cd5903b358 | ||
|
|
f78125c4fb | ||
|
|
6394241b9f | ||
|
|
d4dfc9bbab | ||
|
|
cf668be964 | ||
|
|
6ef443d724 | ||
|
|
75af217864 | ||
|
|
7a7343c3c8 | ||
|
|
18bfa8f562 | ||
|
|
a76a0815a0 | ||
|
|
332f384a65 | ||
|
|
3c5e1216c8 | ||
|
|
c7c11a1c1e | ||
|
|
0dd993c1d0 | ||
|
|
c977e9b59c | ||
|
|
81055b5500 | ||
|
|
c8df446846 | ||
|
|
97ac4621b9 | ||
|
|
9346c474cf | ||
|
|
d9a55965d3 | ||
|
|
50306343a8 | ||
|
|
08d7457620 | ||
|
|
b80a382d2f | ||
|
|
ab066bb441 | ||
|
|
4a64260d6e | ||
|
|
9390077007 | ||
|
|
baf5386e34 | ||
|
|
86e72b2f7f | ||
|
|
70bc02b12e | ||
|
|
6bce8b0195 | ||
|
|
dd4afb1d0a | ||
|
|
95493fe157 | ||
|
|
42b9ef3956 | ||
|
|
97ee7b7a7a | ||
|
|
230860f773 | ||
|
|
5f7f6d975e | ||
|
|
e7c95fdcc1 | ||
|
|
933367a685 | ||
|
|
4857307533 | ||
|
|
1ee50e42ca | ||
|
|
5bbc108331 | ||
|
|
11d62516d9 | ||
|
|
ef714a8bfc | ||
|
|
c6b8441a79 | ||
|
|
200ad86575 | ||
|
|
54fe2f260f | ||
|
|
e056cf743d | ||
|
|
8dbc747928 | ||
|
|
969b37e4e9 | ||
|
|
79a111668e | ||
|
|
9c90e3110b | ||
|
|
59237fb9c6 | ||
|
|
fc3705f019 | ||
|
|
15adbc0823 | ||
|
|
ca6472f5f2 | ||
|
|
de38322f34 | ||
|
|
ed45d30639 | ||
|
|
f99fc6f15f | ||
|
|
56aaa082da | ||
|
|
0aaa2f20bd | ||
|
|
bac589e3ec | ||
|
|
1dc7b02a3c | ||
|
|
83965afe68 | ||
|
|
0e9b110023 | ||
|
|
44f01a77fd | ||
|
|
58552b7a50 | ||
|
|
ddf3feac51 | ||
|
|
c2d59fcee1 | ||
|
|
ee3b2592aa | ||
|
|
ed79dfb220 | ||
|
|
6fbb942ad9 | ||
|
|
94a9340ee3 | ||
|
|
ef6d2b7d2b | ||
|
|
7f0b603f60 | ||
|
|
04ec31ea5c | ||
|
|
d1ff36c44a | ||
|
|
d703443469 | ||
|
|
5455a02c4d | ||
|
|
4bbb186f63 | ||
|
|
b62e8bf976 | ||
|
|
7ccc4fe33a | ||
|
|
b52d1cf1e2 | ||
|
|
6ee9db0eb8 | ||
|
|
36ac2a5bfb | ||
|
|
e1841c652a | ||
|
|
6fc2c88482 | ||
|
|
b8a13a5ba4 | ||
|
|
d36623c1fb | ||
|
|
06ab88556c | ||
|
|
b552790035 | ||
|
|
6610dd22df | ||
|
|
04dddf92d8 | ||
|
|
bedd9c97c2 | ||
|
|
81c859ba31 | ||
|
|
041e662e07 | ||
|
|
65c7c66b50 | ||
|
|
287f2762f9 | ||
|
|
3750e94ff5 | ||
|
|
e127d60345 | ||
|
|
5189298884 | ||
|
|
5a9c370b29 | ||
|
|
ec4f370f29 | ||
|
|
da194dd88d | ||
|
|
91e6b86eb3 | ||
|
|
550e2d59b4 | ||
|
|
80b7ef08c8 | ||
|
|
7c9ddf0c3f | ||
|
|
9abdb1d47b | ||
|
|
a5171dd9b4 | ||
|
|
4e7c04efbe | ||
|
|
d3c66dc750 | ||
|
|
7e14357902 | ||
|
|
92f6c2448f | ||
|
|
b05ebe8bdf | ||
|
|
0b62390a54 | ||
|
|
8c9b5f2a18 | ||
|
|
960894c329 | ||
|
|
a5786ecccf | ||
|
|
33a83928e7 | ||
|
|
149c6271b3 | ||
|
|
031d23df0c | ||
|
|
30134bf3b5 | ||
|
|
7907150f17 | ||
|
|
e5f9639d1e | ||
|
|
47bad16b54 | ||
|
|
efa944ef8c | ||
|
|
68d4cfff16 | ||
|
|
c9c6c4c5ea | ||
|
|
792b3a1267 | ||
|
|
5b64cf6925 | ||
|
|
097878b4b2 | ||
|
|
32eca9aabf | ||
|
|
7a27432885 | ||
|
|
92e4249eec | ||
|
|
6fac0aa0f5 | ||
|
|
cd2ede5ce8 | ||
|
|
ac407375ab | ||
|
|
1730effc55 | ||
|
|
21c063ac53 | ||
|
|
2ba2ef9617 | ||
|
|
cfe2424cff | ||
|
|
397fe2a0c8 | ||
|
|
e846cc532c | ||
|
|
d273f99940 | ||
|
|
f0763c2b67 | ||
|
|
48d6293ab6 | ||
|
|
0e270595df | ||
|
|
db6770159e | ||
|
|
e6bf1ed6f7 | ||
|
|
996dd11e24 | ||
|
|
4ea1f20022 | ||
|
|
a56cfc5688 | ||
|
|
d71d05374f | ||
|
|
99b82b24d0 | ||
|
|
5cfe624e25 | ||
|
|
62066e04e3 | ||
|
|
5478c014f1 | ||
|
|
aea3147454 | ||
|
|
e466de4d0e | ||
|
|
0de3cf72b8 | ||
|
|
41fa97994e | ||
|
|
d03a563e0d | ||
|
|
0f89c0b112 | ||
|
|
07ae096af2 | ||
|
|
11e4d482f4 | ||
|
|
f959e3b869 | ||
|
|
ec19bfb556 | ||
|
|
fa4edf9845 | ||
|
|
ab52430846 | ||
|
|
6045869260 | ||
|
|
c08a598658 | ||
|
|
340483bf7f | ||
|
|
87395e0ec4 | ||
|
|
694194dd01 | ||
|
|
aa6935820d | ||
|
|
57c038dca6 | ||
|
|
fe69b1419f | ||
|
|
0cf7365755 | ||
|
|
7e96f776ff | ||
|
|
e5ce3d46de | ||
|
|
f097cb3c3a | ||
|
|
23aea7b794 | ||
|
|
c2839fdc29 | ||
|
|
3fbd64338c | ||
|
|
36a2917b17 | ||
|
|
9f3fc43791 | ||
|
|
4774d2d1fd | ||
|
|
91de8a5a8f | ||
|
|
652005264b | ||
|
|
98967410cb | ||
|
|
55b2e3f1ff | ||
|
|
cf8ddc98af | ||
|
|
f259fa85a5 | ||
|
|
5ea6c7739f | ||
|
|
eac071af9d | ||
|
|
2b0f424af6 | ||
|
|
fcbfd28025 | ||
|
|
37982fe416 | ||
|
|
6824c85820 | ||
|
|
bd9f76222a | ||
|
|
349e771f74 | ||
|
|
83c2993cef | ||
|
|
dbb91fa140 | ||
|
|
849ca6803d | ||
|
|
f41288f441 | ||
|
|
9e974d5c30 | ||
|
|
62d25ee917 | ||
|
|
652a5dd27d | ||
|
|
1051bfa661 | ||
|
|
3a3c481e3b | ||
|
|
9642c58d94 | ||
|
|
72d37ab218 | ||
|
|
a2047f9498 | ||
|
|
22a94130f2 | ||
|
|
6a907ff0c2 | ||
|
|
11e0ca29d4 | ||
|
|
47cd4ef790 | ||
|
|
25572a9d57 | ||
|
|
02b94e5672 | ||
|
|
23790fefd6 | ||
|
|
3c8e4a24c6 | ||
|
|
0f754055ab | ||
|
|
ac7c2612b2 | ||
|
|
7b54ff2046 | ||
|
|
c7743ffdbe | ||
|
|
7a604d39bd | ||
|
|
7c67f8bba1 | ||
|
|
6f2ca41eb6 | ||
|
|
b26ac16201 | ||
|
|
71b7ba70d1 | ||
|
|
96bd62e0cc | ||
|
|
c2ce598d0f | ||
|
|
cf56069804 | ||
|
|
7834b535d6 | ||
|
|
4b440199a2 | ||
|
|
4facfa5c7a | ||
|
|
99ab247c06 | ||
|
|
5cf12fced5 | ||
|
|
5abc92308a | ||
|
|
ed50ca5b53 | ||
|
|
3e8eb1a6eb | ||
|
|
d360c584c1 | ||
|
|
55482bf28a | ||
|
|
bcf5b4c1b2 | ||
|
|
7098e28532 | ||
|
|
ab8aa2e1ae | ||
|
|
97fc9a8b37 | ||
|
|
5f91a4561b | ||
|
|
b5dd56f187 | ||
|
|
819f0b7d7e | ||
|
|
16399d4512 | ||
|
|
86df184463 | ||
|
|
a4a2d66b85 | ||
|
|
1fb972cf2a | ||
|
|
f1ab0e3449 | ||
|
|
5032646090 | ||
|
|
2facce9633 | ||
|
|
bce50b991e | ||
|
|
bd1a5ef046 | ||
|
|
47e9b4b587 | ||
|
|
676e6127cd | ||
|
|
7b192a4e14 | ||
|
|
e3239ed0b3 | ||
|
|
1423454191 | ||
|
|
285b6367ed | ||
|
|
2907403f82 | ||
|
|
9a735639d4 | ||
|
|
375e3c4636 | ||
|
|
ab3d7078bf | ||
|
|
3b191b917b | ||
|
|
4be129917a | ||
|
|
507f508497 | ||
|
|
4b063b3493 | ||
|
|
8e457a20bc | ||
|
|
b9716cf2a3 | ||
|
|
b05a4ab83a | ||
|
|
ca75eb651d | ||
|
|
a6329fd3c0 | ||
|
|
89e33e984b | ||
|
|
40c0b85a10 | ||
|
|
7cdb199855 | ||
|
|
8c165dc17f | ||
|
|
43fe21a87d | ||
|
|
4b7559f2ec | ||
|
|
9e026034d7 | ||
|
|
9466ccb12a | ||
|
|
f53f314f0b | ||
|
|
9b53a3a052 | ||
|
|
7f8a95646a | ||
|
|
88d452a9fa | ||
|
|
ee2e1412d6 | ||
|
|
f2ea6af1c3 | ||
|
|
76bd5d7518 | ||
|
|
70626ccb79 | ||
|
|
124fca6d1f | ||
|
|
37154cc1ef | ||
|
|
9f42ad5746 | ||
|
|
94c19c8724 | ||
|
|
c3dd9a5f14 | ||
|
|
8f2a6acb7b | ||
|
|
821817fc89 | ||
|
|
0f3097590f | ||
|
|
20826fff54 | ||
|
|
9067e1d8d1 | ||
|
|
dbf983e287 | ||
|
|
f81043133a | ||
|
|
cab9b0bd1e | ||
|
|
d9b42016dc | ||
|
|
5ee5a23b29 | ||
|
|
a1f33d93c1 | ||
|
|
1f9a19c37a | ||
|
|
9e9d371a3f | ||
|
|
b97136a606 | ||
|
|
f1df463a07 | ||
|
|
e59c335cac | ||
|
|
a9280edf97 | ||
|
|
68eca70a31 | ||
|
|
dd68c35295 | ||
|
|
57530af792 | ||
|
|
4947fa91ef | ||
|
|
c605cc77d5 | ||
|
|
6fe6b681ac | ||
|
|
08884af624 | ||
|
|
2adfbb5169 | ||
|
|
831c3c4fa4 | ||
|
|
df87b51e63 | ||
|
|
a17fceac39 | ||
|
|
f6e05a27d8 | ||
|
|
19cb4ee7a4 | ||
|
|
8d4f853432 | ||
|
|
76eaac5d31 | ||
|
|
5c02943ab3 | ||
|
|
09a38e2dcd | ||
|
|
4a772953dd | ||
|
|
be544e09cf | ||
|
|
8a817980db | ||
|
|
1dbfbe5d5f | ||
|
|
53ed0dc12d | ||
|
|
1bbff65f5d | ||
|
|
8e5e9ab517 | ||
|
|
c2d37932e1 | ||
|
|
7e7bbd4591 | ||
|
|
6d2d3c4c3b | ||
|
|
a1ba7f9e5f | ||
|
|
b89949e361 | ||
|
|
72ad111198 | ||
|
|
00b4e9a9b4 | ||
|
|
a460fe12a1 | ||
|
|
7e4fdcd9a3 | ||
|
|
0f4d06b4d4 | ||
|
|
bfbf6edc87 | ||
|
|
5027e2f03a | ||
|
|
70ea05c0ca | ||
|
|
5e9d9abe10 | ||
|
|
128495dd91 | ||
|
|
314a8c0741 | ||
|
|
8c6ca6f8f7 | ||
|
|
421bb3b701 | ||
|
|
a8e9ef49f4 | ||
|
|
2474ad8d1d | ||
|
|
dd58ac01ed | ||
|
|
fd4fc377a1 | ||
|
|
3b31cec3e7 | ||
|
|
28fc95dd1f |
99
README.md
99
README.md
@@ -1,39 +1,13 @@
|
||||

|
||||

|
||||
|
||||
<h1 align="center">
|
||||
Radzen Blazor Components
|
||||
</h1>
|
||||
Radzen Blazor Components
|
||||
========================
|
||||
|
||||
<p align="center">
|
||||
A set of <strong>70+ free and open source</strong> native Blazor UI controls.
|
||||
</p>
|
||||
A set of **90+ free and open source** native Blazor UI controls.
|
||||
|
||||
<div align="center">
|
||||
See Online Demos or Read the Docs
|
||||
|
||||
[See Online Demos](https://blazor.radzen.com) or [Read the Docs](https://blazor.radzen.com/docs/)
|
||||
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/radzenhq/radzen-blazor/blob/master/LICENSE">
|
||||
<img alt="License - MIT" src="https://img.shields.io/github/license/radzenhq/radzen-blazor?logo=github&style=for-the-badge" />
|
||||
</a>
|
||||
<a href="https://www.nuget.org/packages/Radzen.Blazor">
|
||||
<img alt="NuGet Downloads" src="https://img.shields.io/nuget/dt/Radzen.Blazor?color=%232694F9&label=nuget%20downloads&logo=nuget&style=for-the-badge" />
|
||||
</a>
|
||||
<img alt="Last Commit" src="https://img.shields.io/github/last-commit/radzenhq/radzen-blazor?logo=github&style=for-the-badge" />
|
||||
<a href="https://github.com/radzenhq/radzen-blazor/graphs/contributors">
|
||||
<img alt="Github Contributors" src="https://img.shields.io/github/contributors/radzenhq/radzen-blazor?logo=github&style=for-the-badge" />
|
||||
</a>
|
||||
<a href="https://blazor.radzen.com">
|
||||
<img alt="Radzen Blazor Components - Online Demos" src="https://img.shields.io/badge/demos-online-brightgreen?color=%232694F9&logo=blazor&style=for-the-badge" />
|
||||
</a>
|
||||
<a href="https://blazor.radzen.com/docs">
|
||||
<img alt="Radzen Blazor Components - Documentation" src="https://img.shields.io/badge/docs-online-brightgreen?color=%232694F9&logo=blazor&style=for-the-badge" />
|
||||
</a>
|
||||
</p>
|
||||
[](https://github.com/radzenhq/radzen-blazor/blob/master/LICENSE)[ ](https://www.nuget.org/packages/Radzen.Blazor) [ ](https://github.com/radzenhq/radzen-blazor/graphs/contributors)[ ](https://blazor.radzen.com)[](https://blazor.radzen.com/docs)
|
||||
|
||||
## Why choose Radzen Blazor Components?
|
||||
|
||||
@@ -76,67 +50,8 @@ Our flagship product [Radzen Blazor Studio](https://www.radzen.com/blazor-studio
|
||||
|
||||
## Get started with Radzen Blazor Components
|
||||
|
||||
### 1. Install
|
||||
Check the [getting started](https://blazor.radzen.com/getting-started) instructions to start making awesome Blazor applications.
|
||||
|
||||
Radzen Blazor Components are distributed as a [Radzen.Blazor NuGet package](https://www.nuget.org/packages/Radzen.Blazor). You can add them to your project in one of the following ways
|
||||
- Install the package from command line by running `dotnet add package Radzen.Blazor`
|
||||
- Add the project from the Visual NuGet Package Manager
|
||||
- Manually edit the .csproj file and add a project reference
|
||||
|
||||
### 2. Import the namespace
|
||||
|
||||
Open the `_Imports.razor` file of your Blazor application and add this line `@using Radzen.Blazor`.
|
||||
|
||||
### 3. Include a theme
|
||||
|
||||
Radzen Blazor components come with five free themes: Material, Standard, Default, Dark, Software and Humanistic.
|
||||
|
||||
To use a theme
|
||||
1. Pick a theme. The [online demos](https://blazor.radzen.com/colors) allow you to preview the available options via the theme dropdown located in the header. The Material theme is currently selected by default.
|
||||
1. Include the theme CSS file in your Blazor application. Open `Pages\_Layout.cshtml` (Blazor Server .NET 6), `Pages\_Host.cshtml` (Blazor Server .NET 7) or `wwwroot/index.html` (Blazor WebAssembly) and include a theme CSS file by adding this snippet
|
||||
```html
|
||||
<link rel="stylesheet" href="_content/Radzen.Blazor/css/material-base.css">
|
||||
```
|
||||
|
||||
To include a different theme (i.e. Standard) just change the name of the CSS file:
|
||||
```
|
||||
<link rel="stylesheet" href="_content/Radzen.Blazor/css/standard-base.css">
|
||||
```
|
||||
|
||||
### 4. Include Radzen.Blazor.js
|
||||
|
||||
Open `Pages\_Layout.cshtml` (Blazor Server .NET 6), `Pages\_Host.cshtml` (Blazor Server .NET 7) or `wwwroot/index.html` (Blazor WebAssembly) and include this snippet:
|
||||
|
||||
```html
|
||||
<script src="_content/Radzen.Blazor/Radzen.Blazor.js"></script>
|
||||
```
|
||||
|
||||
### 5. Use a component
|
||||
Use any Radzen Blazor component by typing its tag name in a Blazor page e.g.
|
||||
```html
|
||||
<RadzenButton Text="Hi"></RadzenButton>
|
||||
```
|
||||
|
||||
#### Data-binding a property
|
||||
```razor
|
||||
<RadzenButton Text=@text />
|
||||
<RadzenTextBox @bind-Value=@text />
|
||||
@code {
|
||||
string text = "Hi";
|
||||
}
|
||||
```
|
||||
|
||||
#### Handing events
|
||||
|
||||
```razor
|
||||
<RadzenButton Click="@ButtonClicked" Text="Hi"></RadzenButton>
|
||||
@code {
|
||||
void ButtonClicked()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
```
|
||||
## Run demos locally
|
||||
|
||||
Use Radzen.Server.sln to open and run demos as Blazor server application or Radzen.WebAssembly.sln to open and run demos as Blazor WebAssembly application. Radzen.sln has reference to all projects including tests.
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Icon, icon));
|
||||
|
||||
Assert.Contains(@$"<i class=""rz-button-icon-left rzi"">{icon}</i>", component.Markup);
|
||||
Assert.Contains(@$"<i class=""notranslate rz-button-icon-left rzi"">{icon}</i>", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -48,7 +48,7 @@ namespace Radzen.Blazor.Tests
|
||||
);
|
||||
|
||||
// does not render the actual icon when busy
|
||||
Assert.DoesNotContain(@$"<i class=""rz-button-icon-left rzi"">{icon}</i>", component.Markup);
|
||||
Assert.DoesNotContain(@$"<i class=""notranslate rz-button-icon-left rzi"">{icon}</i>", component.Markup);
|
||||
|
||||
// renders the icon with busy spin animation
|
||||
Assert.Contains(@"<i style=""animation: rotation", component.Markup);
|
||||
@@ -71,7 +71,7 @@ namespace Radzen.Blazor.Tests
|
||||
parameters.Add(p => p.Icon, icon);
|
||||
});
|
||||
|
||||
Assert.Contains(@$"<i class=""rz-button-icon-left rzi"">{icon}</i>", component.Markup);
|
||||
Assert.Contains(@$"<i class=""notranslate rz-button-icon-left rzi"">{icon}</i>", component.Markup);
|
||||
Assert.Contains(@$"<span class=""rz-button-text"">{text}</span>", component.Markup);
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Image, image));
|
||||
|
||||
Assert.Contains(@$"<img class=""rz-button-icon-left rzi"" src=""{image}"" alt=""button"" />", component.Markup);
|
||||
Assert.Contains(@$"<img class=""notranslate rz-button-icon-left rzi"" src=""{image}"" alt=""button"" />", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -106,7 +106,7 @@ namespace Radzen.Blazor.Tests
|
||||
parameters.Add(p => p.ImageAlternateText, text);
|
||||
});
|
||||
|
||||
Assert.Contains(@$"<img class=""rz-button-icon-left rzi"" src=""{image}"" alt=""{text}"" />", component.Markup);
|
||||
Assert.Contains(@$"<img class=""notranslate rz-button-icon-left rzi"" src=""{image}"" alt=""{text}"" />", component.Markup);
|
||||
Assert.Contains(@$"<span class=""rz-button-text"">{text}</span>", component.Markup);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,39 +20,29 @@ namespace Radzen.Blazor.Tests
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder =>
|
||||
var component = ctx.RenderComponent<RadzenDataGrid<dynamic>>(parameterBuilder =>
|
||||
{
|
||||
parameterBuilder.Add<IEnumerable<dynamic>>(p => p.Data, new[] { new { Id = 1 }, new { Id = 2 }, new { Id = 3 } });
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
|
||||
{
|
||||
builder.OpenComponent(0, typeof(RadzenGridColumn<dynamic>));
|
||||
builder.OpenComponent(0, typeof(RadzenDataGridColumn<dynamic>));
|
||||
builder.AddAttribute(1, "Property", "Id");
|
||||
builder.CloseComponent();
|
||||
});
|
||||
});
|
||||
|
||||
// Main
|
||||
Assert.Contains(@$"rz-datatable-scrollable-wrapper", component.Markup);
|
||||
Assert.Contains(@$"rz-datatable-scrollable-view", component.Markup);
|
||||
Assert.Contains(@$"rz-data-grid", component.Markup);
|
||||
Assert.Contains(@$"rz-datatable", component.Markup);
|
||||
Assert.Contains(@$"rz-datatable-scrollable", component.Markup);
|
||||
|
||||
// Header
|
||||
Assert.Contains(@$"rz-datatable-scrollable-header", component.Markup);
|
||||
Assert.Contains(@$"rz-datatable-scrollable-header-box", component.Markup);
|
||||
Assert.Contains(@$"rz-datatable-thead", component.Markup);
|
||||
Assert.Contains(@$"rz-datatable-scrollable-colgroup", component.Markup);
|
||||
// Data
|
||||
Assert.Contains(@$"rz-data-grid-data", component.Markup);
|
||||
|
||||
//Body
|
||||
Assert.Contains(@$"rz-datatable-scrollable-body", component.Markup);
|
||||
Assert.Contains(@$"rz-datatable-scrollable-table-wrapper", component.Markup);
|
||||
Assert.Contains(@$"rz-datatable-data", component.Markup);
|
||||
Assert.Contains(@$"rz-datatable-hoverable-rows", component.Markup);
|
||||
|
||||
// Footer
|
||||
Assert.DoesNotContain(@$"rz-datatable-scrollable-footer", component.Markup);
|
||||
Assert.DoesNotContain(@$"rz-datatable-scrollable-footer-box", component.Markup);
|
||||
|
||||
//Columns
|
||||
Assert.DoesNotContain(@$"rz-sortable-column", component.Markup);
|
||||
// Table
|
||||
Assert.Contains(@$"rz-grid-table", component.Markup);
|
||||
Assert.Contains(@$"rz-grid-table-fixed", component.Markup);
|
||||
Assert.Contains(@$"rz-grid-table-striped", component.Markup);
|
||||
}
|
||||
|
||||
// Columns tests
|
||||
@@ -63,12 +53,12 @@ namespace Radzen.Blazor.Tests
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder =>
|
||||
var component = ctx.RenderComponent<RadzenDataGrid<dynamic>>(parameterBuilder =>
|
||||
{
|
||||
parameterBuilder.Add<IEnumerable<dynamic>>(p => p.Data, new[] { new { Id = 1 }, new { Id = 2 }, new { Id = 3 } });
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
|
||||
{
|
||||
builder.OpenComponent(0, typeof(RadzenGridColumn<dynamic>));
|
||||
builder.OpenComponent(0, typeof(RadzenDataGridColumn<dynamic>));
|
||||
builder.AddAttribute(1, "Property", "Id");
|
||||
builder.CloseComponent();
|
||||
});
|
||||
@@ -88,12 +78,12 @@ namespace Radzen.Blazor.Tests
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder =>
|
||||
var component = ctx.RenderComponent<RadzenDataGrid<dynamic>>(parameterBuilder =>
|
||||
{
|
||||
parameterBuilder.Add<IEnumerable<dynamic>>(p => p.Data, new[] { new { Id = 1 }, new { Id = 2 }, new { Id = 3 } });
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
|
||||
{
|
||||
builder.OpenComponent(0, typeof(RadzenGridColumn<dynamic>));
|
||||
builder.OpenComponent(0, typeof(RadzenDataGridColumn<dynamic>));
|
||||
builder.AddAttribute(1, "Title", "MyId");
|
||||
builder.CloseComponent();
|
||||
});
|
||||
@@ -158,12 +148,12 @@ namespace Radzen.Blazor.Tests
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder =>
|
||||
var component = ctx.RenderComponent<RadzenDataGrid<dynamic>>(parameterBuilder =>
|
||||
{
|
||||
parameterBuilder.Add<IEnumerable<dynamic>>(p => p.Data, new[] { new { Id = 1 }, new { Id = 2 }, new { Id = 3 } });
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
|
||||
{
|
||||
builder.OpenComponent(0, typeof(RadzenGridColumn<dynamic>));
|
||||
builder.OpenComponent(0, typeof(RadzenDataGridColumn<dynamic>));
|
||||
builder.AddAttribute(1, "Property", "Id");
|
||||
builder.AddAttribute(2, "Title", "Id");
|
||||
builder.CloseComponent();
|
||||
@@ -188,12 +178,12 @@ namespace Radzen.Blazor.Tests
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder =>
|
||||
var component = ctx.RenderComponent<RadzenDataGrid<dynamic>>(parameterBuilder =>
|
||||
{
|
||||
parameterBuilder.Add<IEnumerable<dynamic>>(p => p.Data, new[] { new { Id = 1 }, new { Id = 2 }, new { Id = 3 } });
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
|
||||
{
|
||||
builder.OpenComponent(0, typeof(RadzenGridColumn<dynamic>));
|
||||
builder.OpenComponent(0, typeof(RadzenDataGridColumn<dynamic>));
|
||||
builder.AddAttribute(1, "Property", "Id");
|
||||
builder.AddAttribute(2, "Title", "Id");
|
||||
builder.AddAttribute(3, "Sortable", false);
|
||||
@@ -212,12 +202,12 @@ namespace Radzen.Blazor.Tests
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder =>
|
||||
var component = ctx.RenderComponent<RadzenDataGrid<dynamic>>(parameterBuilder =>
|
||||
{
|
||||
parameterBuilder.Add<IEnumerable<dynamic>>(p => p.Data, new[] { new { Id = 1 }, new { Id = 2 }, new { Id = 3 } });
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
|
||||
{
|
||||
builder.OpenComponent(0, typeof(RadzenGridColumn<dynamic>));
|
||||
builder.OpenComponent(0, typeof(RadzenDataGridColumn<dynamic>));
|
||||
builder.AddAttribute(1, "Property", "Id");
|
||||
builder.AddAttribute(2, "Title", "Id");
|
||||
builder.CloseComponent();
|
||||
@@ -225,14 +215,14 @@ namespace Radzen.Blazor.Tests
|
||||
parameterBuilder.Add<bool>(p => p.AllowFiltering, true);
|
||||
});
|
||||
|
||||
Assert.Contains(@$"rz-cell-filter", component.Markup);
|
||||
Assert.Contains(@$"rz-grid-filter-icon", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.AllowFiltering, false);
|
||||
});
|
||||
|
||||
Assert.DoesNotContain(@$"rz-cell-filter", component.Markup);
|
||||
Assert.DoesNotContain(@$"rz-grid-filter-icon", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -242,12 +232,12 @@ namespace Radzen.Blazor.Tests
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder =>
|
||||
var component = ctx.RenderComponent<RadzenDataGrid<dynamic>>(parameterBuilder =>
|
||||
{
|
||||
parameterBuilder.Add<IEnumerable<dynamic>>(p => p.Data, new[] { new { Id = 1 }, new { Id = 2 }, new { Id = 3 } });
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
|
||||
{
|
||||
builder.OpenComponent(0, typeof(RadzenGridColumn<dynamic>));
|
||||
builder.OpenComponent(0, typeof(RadzenDataGridColumn<dynamic>));
|
||||
builder.AddAttribute(1, "Property", "Id");
|
||||
builder.AddAttribute(2, "Title", "Id");
|
||||
builder.AddAttribute(3, "Filterable", false);
|
||||
@@ -266,12 +256,12 @@ namespace Radzen.Blazor.Tests
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder =>
|
||||
var component = ctx.RenderComponent<RadzenDataGrid<dynamic>>(parameterBuilder =>
|
||||
{
|
||||
parameterBuilder.Add<IEnumerable<dynamic>>(p => p.Data, new[] { new { Id = 1 }, new { Id = 2 }, new { Id = 3 } });
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
|
||||
{
|
||||
builder.OpenComponent(0, typeof(RadzenGridColumn<dynamic>));
|
||||
builder.OpenComponent(0, typeof(RadzenDataGridColumn<dynamic>));
|
||||
builder.AddAttribute(1, "Property", "Id");
|
||||
builder.AddAttribute(2, "Title", "Id");
|
||||
builder.CloseComponent();
|
||||
@@ -297,12 +287,12 @@ namespace Radzen.Blazor.Tests
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<int>>(parameterBuilder =>
|
||||
var component = ctx.RenderComponent<RadzenDataGrid<int>>(parameterBuilder =>
|
||||
{
|
||||
parameterBuilder.Add<IEnumerable<int>>(p => p.Data, new[] { 1, 2, 3 });
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
|
||||
{
|
||||
builder.OpenComponent(0, typeof(RadzenGridColumn<int>));
|
||||
builder.OpenComponent(0, typeof(RadzenDataGridColumn<int>));
|
||||
|
||||
builder.AddAttribute(1, "HeaderTemplate", (RenderFragment)delegate (RenderTreeBuilder b)
|
||||
{
|
||||
@@ -323,12 +313,12 @@ namespace Radzen.Blazor.Tests
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<int>>(parameterBuilder =>
|
||||
var component = ctx.RenderComponent<RadzenDataGrid<int>>(parameterBuilder =>
|
||||
{
|
||||
parameterBuilder.Add<IEnumerable<int>>(p => p.Data, new[] { 1, 2, 3 });
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
|
||||
{
|
||||
builder.OpenComponent(0, typeof(RadzenGridColumn<int>));
|
||||
builder.OpenComponent(0, typeof(RadzenDataGridColumn<int>));
|
||||
|
||||
builder.AddAttribute(1, "FooterTemplate", (RenderFragment)delegate (RenderTreeBuilder b)
|
||||
{
|
||||
@@ -339,8 +329,8 @@ namespace Radzen.Blazor.Tests
|
||||
});
|
||||
});
|
||||
|
||||
Assert.Contains(@$"rz-datatable-scrollable-footer", component.Markup);
|
||||
Assert.Contains(@$"rz-datatable-scrollable-footer-box", component.Markup);
|
||||
Assert.Contains(@$"rz-datatable-tfoot", component.Markup);
|
||||
Assert.Contains(@$"rz-column-footer", component.Markup);
|
||||
Assert.Contains(@$"Footer", component.Markup);
|
||||
}
|
||||
|
||||
@@ -352,12 +342,12 @@ namespace Radzen.Blazor.Tests
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder =>
|
||||
var component = ctx.RenderComponent<RadzenDataGrid<dynamic>>(parameterBuilder =>
|
||||
{
|
||||
parameterBuilder.Add<IEnumerable<dynamic>>(p => p.Data, Enumerable.Range(0, 100).Select(i => new { Id = i }));
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
|
||||
{
|
||||
builder.OpenComponent(0, typeof(RadzenGridColumn<dynamic>));
|
||||
builder.OpenComponent(0, typeof(RadzenDataGridColumn<dynamic>));
|
||||
builder.AddAttribute(1, "Property", "Id");
|
||||
builder.AddAttribute(2, "Title", "Id");
|
||||
builder.CloseComponent();
|
||||
@@ -382,11 +372,20 @@ namespace Radzen.Blazor.Tests
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Enumerable.Range(0, 100)));
|
||||
var component = ctx.RenderComponent<RadzenDataGrid<dynamic>>(parameterBuilder =>
|
||||
{
|
||||
parameterBuilder.Add<IEnumerable<dynamic>>(p => p.Data, Enumerable.Range(0, 100).Select(i => new { Id = i }));
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
|
||||
{
|
||||
builder.OpenComponent(0, typeof(RadzenDataGridColumn<dynamic>));
|
||||
builder.AddAttribute(1, "Property", "Id");
|
||||
builder.AddAttribute(2, "Title", "Id");
|
||||
builder.CloseComponent();
|
||||
});
|
||||
parameterBuilder.Add<bool>(p => p.AllowPaging, true);
|
||||
});
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AllowPaging, true));
|
||||
|
||||
Assert.Contains(@$"rz-paginator-bottom", component.Markup);
|
||||
Assert.Contains(@$"rz-pager", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -396,16 +395,21 @@ namespace Radzen.Blazor.Tests
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Enumerable.Range(0, 100)));
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
var component = ctx.RenderComponent<RadzenDataGrid<dynamic>>(parameterBuilder =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.AllowPaging, true);
|
||||
parameters.Add<PagerPosition>(p => p.PagerPosition, PagerPosition.Top);
|
||||
parameterBuilder.Add<IEnumerable<dynamic>>(p => p.Data, Enumerable.Range(0, 100).Select(i => new { Id = i }));
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
|
||||
{
|
||||
builder.OpenComponent(0, typeof(RadzenDataGridColumn<dynamic>));
|
||||
builder.AddAttribute(1, "Property", "Id");
|
||||
builder.AddAttribute(2, "Title", "Id");
|
||||
builder.CloseComponent();
|
||||
});
|
||||
parameterBuilder.Add<bool>(p => p.AllowPaging, true);
|
||||
parameterBuilder.Add<PagerPosition>(p => p.PagerPosition, PagerPosition.Top);
|
||||
});
|
||||
|
||||
Assert.Contains(@$"rz-paginator", component.Markup);
|
||||
Assert.DoesNotContain(@$"rz-paginator-bottom", component.Markup);
|
||||
Assert.Contains(@$"rz-pager", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -415,16 +419,21 @@ namespace Radzen.Blazor.Tests
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Enumerable.Range(0, 100)));
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
var component = ctx.RenderComponent<RadzenDataGrid<dynamic>>(parameterBuilder =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.AllowPaging, true);
|
||||
parameters.Add<PagerPosition>(p => p.PagerPosition, PagerPosition.TopAndBottom);
|
||||
parameterBuilder.Add<IEnumerable<dynamic>>(p => p.Data, Enumerable.Range(0, 100).Select(i => new { Id = i }));
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
|
||||
{
|
||||
builder.OpenComponent(0, typeof(RadzenDataGridColumn<dynamic>));
|
||||
builder.AddAttribute(1, "Property", "Id");
|
||||
builder.AddAttribute(2, "Title", "Id");
|
||||
builder.CloseComponent();
|
||||
});
|
||||
parameterBuilder.Add<bool>(p => p.AllowPaging, true);
|
||||
parameterBuilder.Add<PagerPosition>(p => p.PagerPosition, PagerPosition.TopAndBottom);
|
||||
});
|
||||
|
||||
Assert.Contains(@$"rz-paginator", component.Markup);
|
||||
Assert.Contains(@$"rz-paginator-bottom", component.Markup);
|
||||
Assert.Contains(@$"rz-pager", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -434,7 +443,7 @@ namespace Radzen.Blazor.Tests
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Enumerable.Range(0, 100)));
|
||||
var component = ctx.RenderComponent<RadzenDataGrid<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Enumerable.Range(0, 100)));
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
@@ -453,7 +462,7 @@ namespace Radzen.Blazor.Tests
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Enumerable.Range(0, 100)));
|
||||
var component = ctx.RenderComponent<RadzenDataGrid<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Enumerable.Range(0, 100)));
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
@@ -472,7 +481,7 @@ namespace Radzen.Blazor.Tests
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Array.Empty<int>()));
|
||||
var component = ctx.RenderComponent<RadzenDataGrid<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Array.Empty<int>()));
|
||||
component.Render();
|
||||
|
||||
Assert.Contains("No records to display.", component.Markup);
|
||||
@@ -486,7 +495,7 @@ namespace Radzen.Blazor.Tests
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Array.Empty<int>()));
|
||||
var component = ctx.RenderComponent<RadzenDataGrid<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Array.Empty<int>()));
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.EmptyText, emptyText);
|
||||
@@ -502,7 +511,7 @@ namespace Radzen.Blazor.Tests
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Array.Empty<int>()));
|
||||
var component = ctx.RenderComponent<RadzenDataGrid<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Array.Empty<int>()));
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<RenderFragment>(p => p.EmptyTemplate, builder =>
|
||||
@@ -523,18 +532,28 @@ namespace Radzen.Blazor.Tests
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Enumerable.Range(0, 100)));
|
||||
var component = ctx.RenderComponent<RadzenDataGrid<dynamic>>(parameterBuilder =>
|
||||
{
|
||||
parameterBuilder.Add<IEnumerable<dynamic>>(p => p.Data, Enumerable.Range(0, 100).Select(i => new { Id = i }));
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
|
||||
{
|
||||
builder.OpenComponent(0, typeof(RadzenDataGridColumn<dynamic>));
|
||||
builder.AddAttribute(1, "Property", "Id");
|
||||
builder.AddAttribute(2, "Title", "Id");
|
||||
builder.CloseComponent();
|
||||
});
|
||||
parameterBuilder.Add<bool>(p => p.AllowPaging, true);
|
||||
});
|
||||
|
||||
var raised = false;
|
||||
LoadDataArgs newArgs = null;
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.AllowPaging, true);
|
||||
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; newArgs = args; });
|
||||
});
|
||||
|
||||
component.Find(".rz-paginator-next").Click();
|
||||
component.Find(".rz-pager-next").Click();
|
||||
|
||||
Assert.True(raised);
|
||||
Assert.True(newArgs.Skip == 10);
|
||||
@@ -548,18 +567,28 @@ namespace Radzen.Blazor.Tests
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Enumerable.Range(0, 100)));
|
||||
var component = ctx.RenderComponent<RadzenDataGrid<dynamic>>(parameterBuilder =>
|
||||
{
|
||||
parameterBuilder.Add<IEnumerable<dynamic>>(p => p.Data, Enumerable.Range(0, 100).Select(i => new { Id = i }));
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
|
||||
{
|
||||
builder.OpenComponent(0, typeof(RadzenDataGridColumn<dynamic>));
|
||||
builder.AddAttribute(1, "Property", "Id");
|
||||
builder.AddAttribute(2, "Title", "Id");
|
||||
builder.CloseComponent();
|
||||
});
|
||||
parameterBuilder.Add<bool>(p => p.AllowPaging, true);
|
||||
});
|
||||
|
||||
var raised = false;
|
||||
LoadDataArgs newArgs = null;
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.AllowPaging, true);
|
||||
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; newArgs = args; });
|
||||
});
|
||||
|
||||
component.Find(".rz-paginator-last").Click();
|
||||
component.Find(".rz-pager-last").Click();
|
||||
|
||||
Assert.True(raised);
|
||||
Assert.True(newArgs.Skip == 90);
|
||||
@@ -573,19 +602,29 @@ namespace Radzen.Blazor.Tests
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Enumerable.Range(0, 100)));
|
||||
var component = ctx.RenderComponent<RadzenDataGrid<dynamic>>(parameterBuilder =>
|
||||
{
|
||||
parameterBuilder.Add<IEnumerable<dynamic>>(p => p.Data, Enumerable.Range(0, 100).Select(i => new { Id = i }));
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
|
||||
{
|
||||
builder.OpenComponent(0, typeof(RadzenDataGridColumn<dynamic>));
|
||||
builder.AddAttribute(1, "Property", "Id");
|
||||
builder.AddAttribute(2, "Title", "Id");
|
||||
builder.CloseComponent();
|
||||
});
|
||||
parameterBuilder.Add<bool>(p => p.AllowPaging, true);
|
||||
});
|
||||
|
||||
var raised = false;
|
||||
LoadDataArgs newArgs = null;
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.AllowPaging, true);
|
||||
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; newArgs = args; });
|
||||
});
|
||||
|
||||
component.Find(".rz-paginator-next").Click();
|
||||
component.Find(".rz-paginator-prev").Click();
|
||||
component.Find(".rz-pager-next").Click();
|
||||
component.Find(".rz-pager-prev").Click();
|
||||
|
||||
Assert.True(raised);
|
||||
Assert.True(newArgs.Skip == 0);
|
||||
@@ -599,19 +638,29 @@ namespace Radzen.Blazor.Tests
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Enumerable.Range(0, 100)));
|
||||
var component = ctx.RenderComponent<RadzenDataGrid<dynamic>>(parameterBuilder =>
|
||||
{
|
||||
parameterBuilder.Add<IEnumerable<dynamic>>(p => p.Data, Enumerable.Range(0, 100).Select(i => new { Id = i }));
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
|
||||
{
|
||||
builder.OpenComponent(0, typeof(RadzenDataGridColumn<dynamic>));
|
||||
builder.AddAttribute(1, "Property", "Id");
|
||||
builder.AddAttribute(2, "Title", "Id");
|
||||
builder.CloseComponent();
|
||||
});
|
||||
parameterBuilder.Add<bool>(p => p.AllowPaging, true);
|
||||
});
|
||||
|
||||
var raised = false;
|
||||
LoadDataArgs newArgs = null;
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.AllowPaging, true);
|
||||
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; newArgs = args; });
|
||||
});
|
||||
|
||||
component.Find(".rz-paginator-next").Click();
|
||||
component.Find(".rz-paginator-first").Click();
|
||||
component.Find(".rz-pager-next").Click();
|
||||
component.Find(".rz-pager-first").Click();
|
||||
|
||||
Assert.True(raised);
|
||||
Assert.True(newArgs.Skip == 0);
|
||||
@@ -625,17 +674,27 @@ namespace Radzen.Blazor.Tests
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Enumerable.Range(0, 100)));
|
||||
var component = ctx.RenderComponent<RadzenDataGrid<dynamic>>(parameterBuilder =>
|
||||
{
|
||||
parameterBuilder.Add<IEnumerable<dynamic>>(p => p.Data, Enumerable.Range(0, 100).Select(i => new { Id = i }));
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
|
||||
{
|
||||
builder.OpenComponent(0, typeof(RadzenDataGridColumn<dynamic>));
|
||||
builder.AddAttribute(1, "Property", "Id");
|
||||
builder.AddAttribute(2, "Title", "Id");
|
||||
builder.CloseComponent();
|
||||
});
|
||||
parameterBuilder.Add<bool>(p => p.AllowPaging, true);
|
||||
});
|
||||
|
||||
var raised = false;
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.AllowPaging, true);
|
||||
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; });
|
||||
});
|
||||
|
||||
component.Find(".rz-paginator-first").Click();
|
||||
component.Find(".rz-pager-first").Click();
|
||||
|
||||
Assert.False(raised);
|
||||
}
|
||||
@@ -647,17 +706,27 @@ namespace Radzen.Blazor.Tests
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Enumerable.Range(0, 100)));
|
||||
var component = ctx.RenderComponent<RadzenDataGrid<dynamic>>(parameterBuilder =>
|
||||
{
|
||||
parameterBuilder.Add<IEnumerable<dynamic>>(p => p.Data, Enumerable.Range(0, 100).Select(i => new { Id = i }));
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
|
||||
{
|
||||
builder.OpenComponent(0, typeof(RadzenDataGridColumn<dynamic>));
|
||||
builder.AddAttribute(1, "Property", "Id");
|
||||
builder.AddAttribute(2, "Title", "Id");
|
||||
builder.CloseComponent();
|
||||
});
|
||||
parameterBuilder.Add<bool>(p => p.AllowPaging, true);
|
||||
});
|
||||
|
||||
var raised = false;
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.AllowPaging, true);
|
||||
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; });
|
||||
});
|
||||
|
||||
component.Find(".rz-paginator-prev").Click();
|
||||
component.Find(".rz-pager-prev").Click();
|
||||
|
||||
Assert.False(raised);
|
||||
}
|
||||
@@ -669,23 +738,29 @@ namespace Radzen.Blazor.Tests
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Enumerable.Range(0, 100)));
|
||||
var component = ctx.RenderComponent<RadzenDataGrid<dynamic>>(parameterBuilder =>
|
||||
{
|
||||
parameterBuilder.Add<IEnumerable<dynamic>>(p => p.Data, Enumerable.Range(0, 100).Select(i => new { Id = i }));
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
|
||||
{
|
||||
builder.OpenComponent(0, typeof(RadzenDataGridColumn<dynamic>));
|
||||
builder.AddAttribute(1, "Property", "Id");
|
||||
builder.AddAttribute(2, "Title", "Id");
|
||||
builder.CloseComponent();
|
||||
});
|
||||
parameterBuilder.Add<bool>(p => p.AllowPaging, true);
|
||||
});
|
||||
|
||||
var raised = false;
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.AllowPaging, true);
|
||||
});
|
||||
|
||||
component.Find(".rz-paginator-last").Click();
|
||||
component.Find(".rz-pager-last").Click();
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; });
|
||||
});
|
||||
|
||||
component.Find(".rz-paginator-last").Click();
|
||||
component.Find(".rz-pager-last").Click();
|
||||
|
||||
Assert.False(raised);
|
||||
}
|
||||
@@ -697,23 +772,29 @@ namespace Radzen.Blazor.Tests
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Enumerable.Range(0, 100)));
|
||||
var component = ctx.RenderComponent<RadzenDataGrid<dynamic>>(parameterBuilder =>
|
||||
{
|
||||
parameterBuilder.Add<IEnumerable<dynamic>>(p => p.Data, Enumerable.Range(0, 100).Select(i => new { Id = i }));
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
|
||||
{
|
||||
builder.OpenComponent(0, typeof(RadzenDataGridColumn<dynamic>));
|
||||
builder.AddAttribute(1, "Property", "Id");
|
||||
builder.AddAttribute(2, "Title", "Id");
|
||||
builder.CloseComponent();
|
||||
});
|
||||
parameterBuilder.Add<bool>(p => p.AllowPaging, true);
|
||||
});
|
||||
|
||||
var raised = false;
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.AllowPaging, true);
|
||||
});
|
||||
|
||||
component.Find(".rz-paginator-last").Click();
|
||||
component.Find(".rz-pager-last").Click();
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; });
|
||||
});
|
||||
|
||||
component.Find(".rz-paginator-next").Click();
|
||||
component.Find(".rz-pager-next").Click();
|
||||
|
||||
Assert.False(raised);
|
||||
}
|
||||
@@ -725,19 +806,29 @@ namespace Radzen.Blazor.Tests
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Enumerable.Range(0, 100)));
|
||||
var component = ctx.RenderComponent<RadzenDataGrid<dynamic>>(parameterBuilder =>
|
||||
{
|
||||
parameterBuilder.Add<IEnumerable<dynamic>>(p => p.Data, Enumerable.Range(0, 100).Select(i => new { Id = i }));
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
|
||||
{
|
||||
builder.OpenComponent(0, typeof(RadzenDataGridColumn<dynamic>));
|
||||
builder.AddAttribute(1, "Property", "Id");
|
||||
builder.AddAttribute(2, "Title", "Id");
|
||||
builder.CloseComponent();
|
||||
});
|
||||
parameterBuilder.Add<bool>(p => p.AllowPaging, true);
|
||||
});
|
||||
|
||||
var raised = false;
|
||||
LoadDataArgs newArgs = null;
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.AllowPaging, true);
|
||||
parameters.Add<int>(p => p.PageSize, 20);
|
||||
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; newArgs = args; });
|
||||
});
|
||||
|
||||
component.Find(".rz-paginator-next").Click();
|
||||
component.Find(".rz-pager-next").Click();
|
||||
|
||||
Assert.True(raised);
|
||||
Assert.True(newArgs.Skip == 20);
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AllowPaging, true));
|
||||
|
||||
Assert.Contains(@$"rz-paginator-bottom", component.Markup);
|
||||
Assert.Contains(@$"rz-pager-bottom", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -44,8 +44,8 @@ namespace Radzen.Blazor.Tests
|
||||
parameters.Add<PagerPosition>(p => p.PagerPosition, PagerPosition.Top);
|
||||
});
|
||||
|
||||
Assert.Contains(@$"rz-paginator", component.Markup);
|
||||
Assert.DoesNotContain(@$"rz-paginator-bottom", component.Markup);
|
||||
Assert.Contains(@$"rz-pager", component.Markup);
|
||||
Assert.DoesNotContain(@$"rz-pager-bottom", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -60,8 +60,8 @@ namespace Radzen.Blazor.Tests
|
||||
parameters.Add<PagerPosition>(p => p.PagerPosition, PagerPosition.TopAndBottom);
|
||||
});
|
||||
|
||||
Assert.Contains(@$"rz-paginator", component.Markup);
|
||||
Assert.Contains(@$"rz-paginator-bottom", component.Markup);
|
||||
Assert.Contains(@$"rz-pager", component.Markup);
|
||||
Assert.Contains(@$"rz-pager-bottom", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -127,7 +127,7 @@ namespace Radzen.Blazor.Tests
|
||||
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; newArgs = args; });
|
||||
});
|
||||
|
||||
component.Find(".rz-paginator-next").Click();
|
||||
component.Find(".rz-pager-next").Click();
|
||||
|
||||
Assert.True(raised);
|
||||
Assert.True(newArgs.Skip == 10);
|
||||
@@ -149,7 +149,7 @@ namespace Radzen.Blazor.Tests
|
||||
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; newArgs = args; });
|
||||
});
|
||||
|
||||
component.Find(".rz-paginator-last").Click();
|
||||
component.Find(".rz-pager-last").Click();
|
||||
|
||||
Assert.True(raised);
|
||||
Assert.True(newArgs.Skip == 90);
|
||||
@@ -171,8 +171,8 @@ namespace Radzen.Blazor.Tests
|
||||
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; newArgs = args; });
|
||||
});
|
||||
|
||||
component.Find(".rz-paginator-next").Click();
|
||||
component.Find(".rz-paginator-prev").Click();
|
||||
component.Find(".rz-pager-next").Click();
|
||||
component.Find(".rz-pager-prev").Click();
|
||||
|
||||
Assert.True(raised);
|
||||
Assert.True(newArgs.Skip == 0);
|
||||
@@ -194,8 +194,8 @@ namespace Radzen.Blazor.Tests
|
||||
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; newArgs = args; });
|
||||
});
|
||||
|
||||
component.Find(".rz-paginator-next").Click();
|
||||
component.Find(".rz-paginator-first").Click();
|
||||
component.Find(".rz-pager-next").Click();
|
||||
component.Find(".rz-pager-first").Click();
|
||||
|
||||
Assert.True(raised);
|
||||
Assert.True(newArgs.Skip == 0);
|
||||
@@ -216,7 +216,7 @@ namespace Radzen.Blazor.Tests
|
||||
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; });
|
||||
});
|
||||
|
||||
component.Find(".rz-paginator-first").Click();
|
||||
component.Find(".rz-pager-first").Click();
|
||||
|
||||
Assert.False(raised);
|
||||
}
|
||||
@@ -235,7 +235,7 @@ namespace Radzen.Blazor.Tests
|
||||
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; });
|
||||
});
|
||||
|
||||
component.Find(".rz-paginator-prev").Click();
|
||||
component.Find(".rz-pager-prev").Click();
|
||||
|
||||
Assert.False(raised);
|
||||
}
|
||||
@@ -253,13 +253,13 @@ namespace Radzen.Blazor.Tests
|
||||
parameters.Add<bool>(p => p.AllowPaging, true);
|
||||
});
|
||||
|
||||
component.Find(".rz-paginator-last").Click();
|
||||
component.Find(".rz-pager-last").Click();
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; });
|
||||
});
|
||||
|
||||
component.Find(".rz-paginator-last").Click();
|
||||
component.Find(".rz-pager-last").Click();
|
||||
|
||||
Assert.False(raised);
|
||||
}
|
||||
@@ -277,13 +277,13 @@ namespace Radzen.Blazor.Tests
|
||||
parameters.Add<bool>(p => p.AllowPaging, true);
|
||||
});
|
||||
|
||||
component.Find(".rz-paginator-last").Click();
|
||||
component.Find(".rz-pager-last").Click();
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; });
|
||||
});
|
||||
|
||||
component.Find(".rz-paginator-next").Click();
|
||||
component.Find(".rz-pager-next").Click();
|
||||
|
||||
Assert.False(raised);
|
||||
}
|
||||
@@ -304,7 +304,7 @@ namespace Radzen.Blazor.Tests
|
||||
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; newArgs = args; });
|
||||
});
|
||||
|
||||
component.Find(".rz-paginator-next").Click();
|
||||
component.Find(".rz-pager-next").Click();
|
||||
|
||||
Assert.True(raised);
|
||||
Assert.True(newArgs.Skip == 20);
|
||||
|
||||
@@ -18,10 +18,10 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
||||
|
||||
Assert.Contains(@$"rz-datepicker", component.Markup);
|
||||
Assert.Contains(@$"rz-calendar", component.Markup);
|
||||
Assert.Contains(@$"rz-datepicker-group", component.Markup);
|
||||
Assert.Contains(@$"rz-datepicker-header", component.Markup);
|
||||
Assert.Contains(@$"rz-datepicker-calendar", component.Markup);
|
||||
Assert.Contains(@$"rz-calendar-header", component.Markup);
|
||||
Assert.Contains(@$"rz-calendar-view", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -137,7 +137,7 @@ namespace Radzen.Blazor.Tests
|
||||
parameters.Add<bool>(p => p.TimeOnly, true);
|
||||
});
|
||||
|
||||
Assert.DoesNotContain(@$"rz-datepicker-header", component.Markup);
|
||||
Assert.DoesNotContain(@$"rz-calendar-header", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -155,7 +155,7 @@ namespace Radzen.Blazor.Tests
|
||||
parameters.Add<bool>(p => p.AllowClear, true);
|
||||
});
|
||||
|
||||
Assert.Contains(@$"<i class=""rz-dropdown-clear-icon rzi rzi-times""", component.Markup);
|
||||
Assert.Contains(@$"<i class=""notranslate rz-dropdown-clear-icon rzi rzi-times""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -218,7 +218,7 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Style, value));
|
||||
|
||||
Assert.Contains(@$"style=""display: inline-block;{value}""", component.Markup);
|
||||
Assert.Contains(@$"style=""{value}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -252,7 +252,7 @@ namespace Radzen.Blazor.Tests
|
||||
parameters.Add(p => p.Change, args => { raised = true; newValue = args; });
|
||||
});
|
||||
|
||||
component.Find(".rz-datepicker-next-icon").Click();
|
||||
component.Find(".rz-calendar-next-icon").Click();
|
||||
|
||||
Assert.False(raised);
|
||||
}
|
||||
@@ -274,7 +274,7 @@ namespace Radzen.Blazor.Tests
|
||||
parameters.Add(p => p.ValueChanged, args => { raised = true; newValue = args; });
|
||||
});
|
||||
|
||||
component.Find(".rz-datepicker-next-icon").Click();
|
||||
component.Find(".rz-calendar-next-icon").Click();
|
||||
|
||||
Assert.False(raised);
|
||||
}
|
||||
@@ -296,7 +296,7 @@ namespace Radzen.Blazor.Tests
|
||||
parameters.Add(p => p.Change, args => { raised = true; newValue = args; });
|
||||
});
|
||||
|
||||
component.Find(".rz-datepicker-prev-icon").Click();
|
||||
component.Find(".rz-calendar-prev-icon").Click();
|
||||
|
||||
Assert.False(raised);
|
||||
}
|
||||
@@ -318,7 +318,7 @@ namespace Radzen.Blazor.Tests
|
||||
parameters.Add(p => p.ValueChanged, args => { raised = true; newValue = args; });
|
||||
});
|
||||
|
||||
component.Find(".rz-datepicker-prev-icon").Click();
|
||||
component.Find(".rz-calendar-prev-icon").Click();
|
||||
|
||||
Assert.False(raised);
|
||||
}
|
||||
@@ -471,7 +471,7 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
Assert.Contains(DateTime.MaxValue.ToString(component.Instance.DateFormat), component.Markup);
|
||||
|
||||
var exception = Record.Exception(() => component.Find(".rz-datepicker-next-icon")
|
||||
var exception = Record.Exception(() => component.Find(".rz-calendar-next-icon")
|
||||
.Click());
|
||||
Assert.Null(exception);
|
||||
}
|
||||
@@ -500,7 +500,7 @@ namespace Radzen.Blazor.Tests
|
||||
parameters.Add(p => p.Change, args => { raised = true; newValue = args; });
|
||||
});
|
||||
|
||||
component.Find(".rz-datepicker-next-icon").Click();
|
||||
component.Find(".rz-calendar-next-icon").Click();
|
||||
component.FindAll(".rz-button-text").First(x => x.TextContent == "Ok").Click();
|
||||
|
||||
Assert.True(raised);
|
||||
@@ -665,11 +665,11 @@ namespace Radzen.Blazor.Tests
|
||||
parameter.Add(p => p.ShowCalendarWeek, true);
|
||||
});
|
||||
|
||||
Assert.Contains(@$"rz-datepicker-week-number", component.Markup);
|
||||
Assert.Equal(8, component.FindAll(".rz-datepicker-calendar th").Count());
|
||||
Assert.Contains(@$"rz-calendar-week-number", component.Markup);
|
||||
Assert.Equal(8, component.FindAll(".rz-calendar-view th").Count());
|
||||
// check header and week number column
|
||||
Assert.Single(component.FindAll("th.rz-datepicker-week-number"));
|
||||
Assert.Equal(6, component.FindAll("td.rz-datepicker-week-number").Count());
|
||||
Assert.Equal(6, component.FindAll("td.rz-calendar-week-number").Count());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -684,8 +684,8 @@ namespace Radzen.Blazor.Tests
|
||||
parameter.Add(p => p.ShowCalendarWeek, false);
|
||||
});
|
||||
|
||||
Assert.DoesNotContain(@$"rz-datepicker-week-number", component.Markup);
|
||||
Assert.Equal(7, component.FindAll(".rz-datepicker-calendar th").Count());
|
||||
Assert.DoesNotContain(@$"rz-calendar-week-number", component.Markup);
|
||||
Assert.Equal(7, component.FindAll(".rz-calendar-view th").Count());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -701,7 +701,7 @@ namespace Radzen.Blazor.Tests
|
||||
parameter.Add(p => p.CalendarWeekTitle, "Wk");
|
||||
});
|
||||
|
||||
var weekNumberHeader = component.Find(".rz-datepicker-calendar th.rz-datepicker-week-number");
|
||||
var weekNumberHeader = component.Find(".rz-calendar-view th.rz-datepicker-week-number");
|
||||
Assert.Contains("Wk", weekNumberHeader.InnerHtml);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Icon, value));
|
||||
|
||||
Assert.Contains(@$"<i class=""rzi"">{value}</i>", component.Markup);
|
||||
Assert.Contains(@$"<i class=""notranslate rzi"">{value}</i>", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -104,11 +104,11 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AllowCollapse, true));
|
||||
|
||||
Assert.Contains(@"<span class=""rz-fieldset-toggler rzi rzi-w rzi-minus""></span>", component.Markup);
|
||||
Assert.Contains(@"<span class=""notranslate rz-fieldset-toggler rzi rzi-w rzi-minus""></span>", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.Collapsed, true));
|
||||
|
||||
Assert.Contains(@"<span class=""rz-fieldset-toggler rzi rzi-w rzi-plus""></span>", component.Markup);
|
||||
Assert.Contains(@"<span class=""notranslate rz-fieldset-toggler rzi rzi-w rzi-plus""></span>", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Radzen.Blazor.Tests
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Icon, icon));
|
||||
|
||||
Assert.Contains(@$">{icon}</i>", component.Markup);
|
||||
Assert.Contains(@$"class=""rzi""", component.Markup);
|
||||
Assert.Contains(@$"class=""notranslate rzi""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Icon, icon));
|
||||
|
||||
Assert.Contains(@$"<i class=""rzi"">{icon}</i>", component.Markup);
|
||||
Assert.Contains(@$"<i class=""notranslate rzi"">{icon}</i>", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
@@ -119,12 +119,12 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
var component = ctx.RenderComponent<RadzenMask>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, false));
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", false));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""off""", component.Markup);
|
||||
Assert.Contains(@$"aria-autocomplete=""none""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""on""", component.Markup);
|
||||
Assert.DoesNotContain(@$"aria-autocomplete", component.Markup);
|
||||
@@ -135,7 +135,7 @@ namespace Radzen.Blazor.Tests
|
||||
Assert.DoesNotContain(@$"aria-autocomplete", component.Markup);
|
||||
|
||||
component.Instance.DefaultAutoCompleteAttribute = "autocomplete-custom";
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.AutoComplete, false));
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", false));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""autocomplete-custom""", component.Markup);
|
||||
Assert.Contains(@$"aria-autocomplete=""none""", component.Markup);
|
||||
@@ -148,22 +148,22 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
var component = ctx.RenderComponent<RadzenMask>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, false));
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", false));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.On));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""off""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.Off));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""off""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.AdditionalName));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""{AutoCompleteType.AdditionalName.GetAutoCompleteValue()}""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.Email));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""{AutoCompleteType.Email.GetAutoCompleteValue()}""", component.Markup);
|
||||
|
||||
@@ -60,6 +60,19 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
Assert.False(component.Instance.Validate(null));
|
||||
}
|
||||
[Fact]
|
||||
public void Returns_True_If_Value_Is_Null_And_AllowNull_Is_True()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenNumericRangeValidatorTestDouble>();
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Min, 0).Add(p => p.Max, 10).Add(p => p.AllowNull, true));
|
||||
});
|
||||
|
||||
Assert.True(component.Instance.Validate(null));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Returns_False_If_Value_Overflows()
|
||||
|
||||
@@ -16,9 +16,9 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
component.Render();
|
||||
|
||||
Assert.Contains(@$"rz-spinner", component.Markup);
|
||||
Assert.Contains(@$"rz-spinner-up", component.Markup);
|
||||
Assert.Contains(@$"rz-spinner-down", component.Markup);
|
||||
Assert.Contains(@$"rz-numeric", component.Markup);
|
||||
Assert.Contains(@$"rz-numeric-up", component.Markup);
|
||||
Assert.Contains(@$"rz-numeric-down", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -54,7 +54,7 @@ namespace Radzen.Blazor.Tests
|
||||
parameters.Add<decimal?>(p => p.Min, minValue);
|
||||
});
|
||||
|
||||
component.Find(".rz-spinner-down").Click();
|
||||
component.Find(".rz-numeric-down").Click();
|
||||
|
||||
Assert.False(raised, $"Numeric value should Change event if value is less than min value.");
|
||||
}
|
||||
@@ -108,7 +108,7 @@ namespace Radzen.Blazor.Tests
|
||||
parameters.Add<decimal?>(p => p.Max, maxValue);
|
||||
});
|
||||
|
||||
component.Find(".rz-spinner-up").Click();
|
||||
component.Find(".rz-numeric-up").Click();
|
||||
|
||||
Assert.False(raised, $"Numeric value should Change event if value is less than min value.");
|
||||
}
|
||||
@@ -216,12 +216,12 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
var component = ctx.RenderComponent<RadzenNumeric<double>>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, false));
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", false));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""off""", component.Markup);
|
||||
Assert.Contains(@$"aria-autocomplete=""none""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""on""", component.Markup);
|
||||
Assert.DoesNotContain(@$"aria-autocomplete", component.Markup);
|
||||
@@ -232,7 +232,7 @@ namespace Radzen.Blazor.Tests
|
||||
Assert.DoesNotContain(@$"aria-autocomplete", component.Markup);
|
||||
|
||||
component.Instance.DefaultAutoCompleteAttribute = "autocomplete-custom";
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.AutoComplete, false));
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", false));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""autocomplete-custom""", component.Markup);
|
||||
Assert.Contains(@$"aria-autocomplete=""none""", component.Markup);
|
||||
@@ -245,22 +245,22 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
var component = ctx.RenderComponent<RadzenNumeric<double>>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, false));
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", false));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.On));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""off""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.Off));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""off""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.BdayMonth));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""{AutoCompleteType.BdayMonth.GetAutoCompleteValue()}""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.BdayYear));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""{AutoCompleteType.BdayYear.GetAutoCompleteValue()}""", component.Markup);
|
||||
@@ -329,7 +329,7 @@ namespace Radzen.Blazor.Tests
|
||||
parameters.Add(p => p.Change, args => { raised = true; newValue = args; });
|
||||
});
|
||||
|
||||
component.Find(".rz-spinner-up").Click();
|
||||
component.Find(".rz-numeric-up").Click();
|
||||
|
||||
Assert.True(raised, "Numeric Change should be raised on step up");
|
||||
Assert.True(object.Equals(expectedValue, newValue), $"Numeric value should be incremented on step up. Expected value: {expectedValue}, value: {newValue}");
|
||||
@@ -338,7 +338,7 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.ValueChanged, args => { raised = true; }));
|
||||
|
||||
component.Find(".rz-spinner-up").Click();
|
||||
component.Find(".rz-numeric-up").Click();
|
||||
|
||||
Assert.True(raised, "Numeric ValueChanged should be raised on step up");
|
||||
}
|
||||
@@ -364,7 +364,7 @@ namespace Radzen.Blazor.Tests
|
||||
parameters.Add(p => p.Change, args => { raised = true; newValue = args; });
|
||||
});
|
||||
|
||||
component.Find(".rz-spinner-down").Click();
|
||||
component.Find(".rz-numeric-down").Click();
|
||||
|
||||
Assert.True(raised, "Numeric Change should be raised on step up");
|
||||
Assert.True(object.Equals(expectedValue, newValue), $"Numeric value should be incremented on step up. Expected value: {expectedValue}, value: {newValue}");
|
||||
@@ -373,7 +373,7 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.ValueChanged, args => { raised = true; }));
|
||||
|
||||
component.Find(".rz-spinner-down").Click();
|
||||
component.Find(".rz-numeric-down").Click();
|
||||
|
||||
Assert.True(raised, "Numeric ValueChanged should be raised on step up");
|
||||
}
|
||||
@@ -387,9 +387,9 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
component.Render();
|
||||
|
||||
Assert.Contains(@$"rz-spinner-button-icon", component.Markup);
|
||||
Assert.Contains(@$"rz-spinner-up", component.Markup);
|
||||
Assert.Contains(@$"rz-spinner-down", component.Markup);
|
||||
Assert.Contains(@$"rz-numeric-button-icon", component.Markup);
|
||||
Assert.Contains(@$"rz-numeric-up", component.Markup);
|
||||
Assert.Contains(@$"rz-numeric-down", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -401,9 +401,9 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
component.Render();
|
||||
|
||||
Assert.DoesNotContain(@$"rz-spinner-button-icon", component.Markup);
|
||||
Assert.DoesNotContain(@$"rz-spinner-up", component.Markup);
|
||||
Assert.DoesNotContain(@$"rz-spinner-down", component.Markup);
|
||||
Assert.DoesNotContain(@$"rz-numeric-button-icon", component.Markup);
|
||||
Assert.DoesNotContain(@$"rz-numeric-up", component.Markup);
|
||||
Assert.DoesNotContain(@$"rz-numeric-down", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
@@ -23,14 +23,14 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
component.Render();
|
||||
|
||||
Assert.Contains(@$"rz-paginator", component.Markup);
|
||||
Assert.Contains(@$"rz-pager", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<int>(p => p.PageSize, 101);
|
||||
parameters.Add<int>(p => p.Count, 100);
|
||||
});
|
||||
Assert.DoesNotContain(@$"rz-paginator", component.Markup);
|
||||
Assert.DoesNotContain(@$"rz-pager", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -49,7 +49,7 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
component.Render();
|
||||
|
||||
Assert.Contains(@$"rz-paginator", component.Markup);
|
||||
Assert.Contains(@$"rz-pager", component.Markup);
|
||||
Assert.Contains(@$"rz-dropdown-trigger", component.Markup);
|
||||
}
|
||||
|
||||
@@ -67,13 +67,13 @@ namespace Radzen.Blazor.Tests
|
||||
await component.Instance.GoToPage(2);
|
||||
component.Render();
|
||||
|
||||
Assert.Contains(@$"rz-paginator-summary", component.Markup);
|
||||
Assert.Contains(@$"rz-pager-summary", component.Markup);
|
||||
Assert.Contains(@$"Page 3 of 10 (100 items)", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
parameters.Add<bool>(p => p.ShowPagingSummary, false);
|
||||
});
|
||||
Assert.DoesNotContain(@$"rz-paginator-summary", component.Markup);
|
||||
Assert.DoesNotContain(@$"rz-pager-summary", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -109,5 +109,51 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
Assert.Contains(@$"rz-density-compact", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void RadzenPager_First_And_Prev_Buttons_Are_Disabled_When_On_The_First_Page()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPager>(parameters => {
|
||||
parameters.Add<int>(p => p.PageSize, 10);
|
||||
parameters.Add<int>(p => p.Count, 100);
|
||||
parameters.Add<bool>(p => p.ShowPagingSummary, true);
|
||||
});
|
||||
|
||||
await component.Instance.GoToPage(0);
|
||||
component.Render();
|
||||
|
||||
var firstPageButton = component.Find("a.rz-pager-first");
|
||||
Assert.True(firstPageButton.HasAttribute("disabled"));
|
||||
|
||||
var prevPageButton = component.Find("a.rz-pager-prev");
|
||||
Assert.True(prevPageButton.HasAttribute("disabled"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void RadzenPager_Last_And_Next_Buttons_Are_Disabled_When_On_The_Last_Page()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPager>(parameters => {
|
||||
parameters.Add<int>(p => p.PageSize, 10);
|
||||
parameters.Add<int>(p => p.Count, 100);
|
||||
parameters.Add<bool>(p => p.ShowPagingSummary, true);
|
||||
});
|
||||
|
||||
await component.Instance.GoToPage(9);
|
||||
component.Render();
|
||||
|
||||
var lastPageButton = component.Find("a.rz-pager-last");
|
||||
Assert.True(lastPageButton.HasAttribute("disabled"));
|
||||
|
||||
var nextPageButton = component.Find("a.rz-pager-next");
|
||||
Assert.True(nextPageButton.HasAttribute("disabled"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Icon, value));
|
||||
|
||||
Assert.Contains(@$"<i class=""rzi"">{value}</i>", component.Markup);
|
||||
Assert.Contains(@$"<i class=""notranslate rzi"">{value}</i>", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -119,11 +119,11 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AllowCollapse, true));
|
||||
|
||||
Assert.Contains(@"<span class=""rzi rzi-minus""></span>", component.Markup);
|
||||
Assert.Contains(@"<span class=""notranslate rzi rzi-minus""></span>", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.Collapsed, true));
|
||||
|
||||
Assert.Contains(@"<span class=""rzi rzi-plus""></span>", component.Markup);
|
||||
Assert.Contains(@"<span class=""notranslate rzi rzi-plus""></span>", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
@@ -119,11 +119,11 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPassword>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, false));
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", false));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""new-password""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""on""", component.Markup);
|
||||
|
||||
@@ -139,22 +139,22 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPassword>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, false));
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", false));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.On));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""new-password""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.Off));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""off""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.CurrentPassword));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""{AutoCompleteType.CurrentPassword.GetAutoCompleteValue()}""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.NewPassword));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""{AutoCompleteType.NewPassword.GetAutoCompleteValue()}""", component.Markup);
|
||||
|
||||
@@ -72,7 +72,7 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Style, value));
|
||||
|
||||
Assert.Contains(@$"style=""{value}""", component.Markup);
|
||||
Assert.Contains(@$"style=""--rz-progressbar-value: 0%;{value}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -118,7 +118,7 @@ namespace Radzen.Blazor.Tests
|
||||
parameters.Add<double>(p => p.Max, max);
|
||||
});
|
||||
|
||||
Assert.Contains(@$"style=""width: {Math.Min(value / max * 100, 100).ToInvariantString()}%;""", component.Markup);
|
||||
Assert.Contains(@$"style=""--rz-progressbar-value: {Math.Min(value / max * 100, 100).ToInvariantString()}%;""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace Radzen.Blazor.Tests
|
||||
component.SetParametersAndRender(parameters => parameters.Add<int>(p => p.Value, value));
|
||||
|
||||
Assert.Contains(@$"style=""width: {Math.Round((value / max * 100)).ToInvariantString()}%;""", component.Markup);
|
||||
Assert.Contains(@$"style=""left: {Math.Round((value / max * 100)).ToInvariantString()}%;""", component.Markup);
|
||||
Assert.Contains(@$"style=""inset-inline-start: {Math.Round((value / max * 100)).ToInvariantString()}%;""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -55,9 +55,9 @@ namespace Radzen.Blazor.Tests
|
||||
parameters.Add<IEnumerable<int>>(p => p.Value, new int[] { 4, 30 });
|
||||
});
|
||||
|
||||
Assert.Contains(@$"left: 4%", component.Markup);
|
||||
Assert.Contains(@$"left: 30%", component.Markup);
|
||||
Assert.Contains(@$"left: 4%; width: 26%;", component.Markup);
|
||||
Assert.Contains(@$"inset-inline-start: 4%", component.Markup);
|
||||
Assert.Contains(@$"inset-inline-start: 30%", component.Markup);
|
||||
Assert.Contains(@$"inset-inline-start: 4%; width: 26%;", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Bunit;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
@@ -44,7 +45,7 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Icon, icon));
|
||||
|
||||
Assert.Contains(@$"<i class=""rz-button-icon-left rzi"">{icon}</i>", component.Markup);
|
||||
Assert.Contains(@$"<i class=""notranslate rz-button-icon-left rzi"">{icon}</i>", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -59,10 +60,10 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
parameters.Add(p => p.Text, text);
|
||||
parameters.Add(p => p.Icon, icon);
|
||||
parameters.Add(p => p.Icon, icon);
|
||||
});
|
||||
|
||||
Assert.Contains(@$"<i class=""rz-button-icon-left rzi"">{icon}</i>", component.Markup);
|
||||
Assert.Contains(@$"<i class=""notranslate rz-button-icon-left rzi"">{icon}</i>", component.Markup);
|
||||
Assert.Contains(@$"<span class=""rz-button-text"">{text}</span>", component.Markup);
|
||||
}
|
||||
|
||||
@@ -77,7 +78,7 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Image, image));
|
||||
|
||||
Assert.Contains(@$"<img class=""rz-button-icon-left rzi"" src=""{image}"" alt=""image"" />", component.Markup);
|
||||
Assert.Contains(@$"<img class=""notranslate rz-button-icon-left rzi"" src=""{image}"" alt=""image"" />", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -96,10 +97,26 @@ namespace Radzen.Blazor.Tests
|
||||
parameters.Add(p => p.ImageAlternateText, text);
|
||||
});
|
||||
|
||||
Assert.Contains(@$"<img class=""rz-button-icon-left rzi"" src=""{image}"" alt=""{text}"" />", component.Markup);
|
||||
Assert.Contains(@$"<img class=""notranslate rz-button-icon-left rzi"" src=""{image}"" alt=""{text}"" />", component.Markup);
|
||||
Assert.Contains(@$"<span class=""rz-button-text"">{text}</span>", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SplitButton_Renders_ButtonContent()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
RenderFragment buttonContent = (builder) => builder.AddMarkupContent(0, "<strong>Custom button content</strong>");
|
||||
|
||||
var text = "Test";
|
||||
var component = ctx.RenderComponent<RadzenSplitButton>(parameters => parameters
|
||||
.Add(p => p.ButtonContent, buttonContent)
|
||||
.Add(p => p.Text, text));
|
||||
|
||||
Assert.Contains(@$"<strong>Custom button content</strong>", component.Markup);
|
||||
Assert.DoesNotContain(@$"<span class=""rz-button-text"">{text}</span>", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SplitButton_Renders_DisabledParameter()
|
||||
{
|
||||
|
||||
@@ -119,12 +119,12 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
var component = ctx.RenderComponent<RadzenTextBox>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, false));
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", false));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""off""", component.Markup);
|
||||
Assert.Contains(@$"aria-autocomplete=""none""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""on""", component.Markup);
|
||||
Assert.DoesNotContain(@$"aria-autocomplete", component.Markup);
|
||||
@@ -135,7 +135,7 @@ namespace Radzen.Blazor.Tests
|
||||
Assert.DoesNotContain(@$"aria-autocomplete", component.Markup);
|
||||
|
||||
component.Instance.DefaultAutoCompleteAttribute = "autocomplete-custom";
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.AutoComplete, false));
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", false));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""autocomplete-custom""", component.Markup);
|
||||
Assert.Contains(@$"aria-autocomplete=""none""", component.Markup);
|
||||
@@ -148,22 +148,22 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
var component = ctx.RenderComponent<RadzenTextBox>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, false));
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", false));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.On));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""off""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.Off));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""off""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.AdditionalName));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""{AutoCompleteType.AdditionalName.GetAutoCompleteValue()}""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.FamilyName));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""{AutoCompleteType.FamilyName.GetAutoCompleteValue()}""", component.Markup);
|
||||
|
||||
@@ -5,7 +5,7 @@ using System.Linq;
|
||||
using System.Linq.Dynamic.Core;
|
||||
using Radzen.Blazor.Rendering;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections;
|
||||
using System.Net.Mime;
|
||||
using Microsoft.AspNetCore.Components.Rendering;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
@@ -92,6 +92,12 @@ namespace Radzen.Blazor
|
||||
throw new ArgumentException($"Property {propertyName} does not exist");
|
||||
}
|
||||
|
||||
#if NET6_0_OR_GREATER
|
||||
if(PropertyAccess.IsDateOnly(property))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return PropertyAccess.IsDate(property);
|
||||
}
|
||||
|
||||
@@ -404,7 +410,7 @@ namespace Radzen.Blazor
|
||||
|
||||
if (IsDate(CategoryProperty) || IsNumeric(CategoryProperty))
|
||||
{
|
||||
Items = Items.AsQueryable().OrderBy(CategoryProperty).ToList();
|
||||
Items = Items.AsQueryable().OrderBy(DynamicLinqCustomTypeProvider.ParsingConfig, CategoryProperty).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -481,18 +487,62 @@ namespace Radzen.Blazor
|
||||
|
||||
return builder =>
|
||||
{
|
||||
builder.OpenComponent<ChartTooltip>(0);
|
||||
builder.AddAttribute(1, nameof(ChartTooltip.X), x + marginLeft);
|
||||
builder.AddAttribute(2, nameof(ChartTooltip.Y), y + marginTop);
|
||||
|
||||
builder.AddAttribute(3, nameof(ChartTooltip.ChildContent), TooltipTemplate?.Invoke(item));
|
||||
if (Chart.Tooltip.Shared)
|
||||
{
|
||||
var category = PropertyAccess.GetValue(item, CategoryProperty);
|
||||
builder.OpenComponent<ChartSharedTooltip>(0);
|
||||
builder.AddAttribute(1, nameof(ChartSharedTooltip.X), x + marginLeft);
|
||||
builder.AddAttribute(2, nameof(ChartSharedTooltip.Y), y + marginTop);
|
||||
builder.AddAttribute(3, nameof(ChartSharedTooltip.Class), TooltipClass(item));
|
||||
builder.AddAttribute(4, nameof(ChartSharedTooltip.Title), TooltipTitle(item));
|
||||
builder.AddAttribute(4, nameof(ChartSharedTooltip.ChildContent), RenderSharedTooltipItems(category));
|
||||
builder.CloseComponent();
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.OpenComponent<ChartTooltip>(0);
|
||||
builder.AddAttribute(1, nameof(ChartTooltip.X), x + marginLeft);
|
||||
builder.AddAttribute(2, nameof(ChartTooltip.Y), y + marginTop);
|
||||
builder.AddAttribute(3, nameof(ChartTooltip.ChildContent), TooltipTemplate?.Invoke(item));
|
||||
builder.AddAttribute(4, nameof(ChartTooltip.Title), TooltipTitle(item));
|
||||
builder.AddAttribute(5, nameof(ChartTooltip.Label), TooltipLabel(item));
|
||||
builder.AddAttribute(6, nameof(ChartTooltip.Value), TooltipValue(item));
|
||||
builder.AddAttribute(7, nameof(ChartTooltip.Class), TooltipClass(item));
|
||||
builder.AddAttribute(8, nameof(ChartTooltip.Style), TooltipStyle(item));
|
||||
builder.CloseComponent();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
builder.AddAttribute(4, nameof(ChartTooltip.Title), TooltipTitle(item));
|
||||
builder.AddAttribute(5, nameof(ChartTooltip.Label), TooltipLabel(item));
|
||||
builder.AddAttribute(6, nameof(ChartTooltip.Value), TooltipValue(item));
|
||||
builder.AddAttribute(7, nameof(ChartTooltip.Class), TooltipClass(item));
|
||||
builder.AddAttribute(8, nameof(ChartTooltip.Style), TooltipStyle(item));
|
||||
builder.CloseComponent();
|
||||
private RenderFragment RenderSharedTooltipItems(object category)
|
||||
{
|
||||
return builder =>
|
||||
{
|
||||
var visibleSeries = Chart.Series.Where(s => s.Visible).ToList();
|
||||
|
||||
foreach (var series in visibleSeries)
|
||||
{
|
||||
builder.AddContent(1, series.RenderSharedTooltipItem(category));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual RenderFragment RenderSharedTooltipItem(object category)
|
||||
{
|
||||
return builder =>
|
||||
{
|
||||
var item = Items.FirstOrDefault(i => object.Equals(PropertyAccess.GetValue(i, CategoryProperty), category));
|
||||
|
||||
if (item != null)
|
||||
{
|
||||
builder.OpenComponent<ChartSharedTooltipItem>(0);
|
||||
builder.AddAttribute(1, nameof(ChartSharedTooltipItem.Value), TooltipValue(item));
|
||||
builder.AddAttribute(2, nameof(ChartSharedTooltipItem.ChildContent), TooltipTemplate?.Invoke(item));
|
||||
builder.AddAttribute(3, nameof(ChartSharedTooltipItem.LegendItem), RenderLegendItem(false));
|
||||
builder.CloseComponent();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -516,6 +566,14 @@ namespace Radzen.Blazor
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual RenderFragment RenderLegendItem()
|
||||
{
|
||||
return RenderLegendItem(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders the legend item for this series.
|
||||
/// </summary>
|
||||
protected virtual RenderFragment RenderLegendItem(bool clickable)
|
||||
{
|
||||
var style = new List<string>();
|
||||
|
||||
@@ -534,6 +592,7 @@ namespace Radzen.Blazor
|
||||
builder.AddAttribute(5, nameof(LegendItem.MarkerSize), MarkerSize);
|
||||
builder.AddAttribute(6, nameof(LegendItem.Text), GetTitle());
|
||||
builder.AddAttribute(7, nameof(LegendItem.Click), EventCallback.Factory.Create(this, OnLegendItemClick));
|
||||
builder.AddAttribute(8, nameof(LegendItem.Clickable), clickable);
|
||||
builder.CloseComponent();
|
||||
};
|
||||
}
|
||||
|
||||
@@ -291,6 +291,7 @@ namespace Radzen
|
||||
services.AddScoped<NotificationService>();
|
||||
services.AddScoped<TooltipService>();
|
||||
services.AddScoped<ContextMenuService>();
|
||||
services.AddScoped<ThemeService>();
|
||||
|
||||
return services;
|
||||
}
|
||||
@@ -505,6 +506,112 @@ namespace Radzen
|
||||
void Refresh();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Supplies information about RadzenDropZoneContainer CanDrop function and RadzenDropZone Drop event.
|
||||
/// </summary>
|
||||
public class RadzenDropZoneItemEventArgs<TItem>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the dragged item zone.
|
||||
/// </summary>
|
||||
public RadzenDropZone<TItem> FromZone { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the drop zone.
|
||||
/// </summary>
|
||||
public RadzenDropZone<TItem> ToZone { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the dragged item.
|
||||
/// </summary>
|
||||
public TItem Item { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the dropped item.
|
||||
/// </summary>
|
||||
public TItem ToItem { get; internal set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Supplies information about RadzenDropZoneContainer ItemRender event.
|
||||
/// </summary>
|
||||
public class RadzenDropZoneItemRenderEventArgs<TItem>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the drop zone.
|
||||
/// </summary>
|
||||
public RadzenDropZone<TItem> Zone { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the dragged item.
|
||||
/// </summary>
|
||||
public TItem Item { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this item is visible.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if visible; otherwise, <c>false</c>.</value>
|
||||
[Parameter]
|
||||
public bool Visible { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the row HTML attributes.
|
||||
/// </summary>
|
||||
public IDictionary<string, object> Attributes { get; private set; } = new Dictionary<string, object>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Supplies information about RadzenDropDown ItemRender event.
|
||||
/// </summary>
|
||||
public class DropDownBaseItemRenderEventArgs<TValue>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the data item.
|
||||
/// </summary>
|
||||
public object Item { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this item is visible.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if visible; otherwise, <c>false</c>.</value>
|
||||
[Parameter]
|
||||
public bool Visible { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this item is visible.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if visible; otherwise, <c>false</c>.</value>
|
||||
[Parameter]
|
||||
public bool Disabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the row HTML attributes.
|
||||
/// </summary>
|
||||
public IDictionary<string, object> Attributes { get; private set; } = new Dictionary<string, object>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Supplies information about RadzenDropDown ItemRender event.
|
||||
/// </summary>
|
||||
public class DropDownItemRenderEventArgs<TValue> : DropDownBaseItemRenderEventArgs<TValue>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the DropDown.
|
||||
/// </summary>
|
||||
public RadzenDropDown<TValue> DropDown { get; internal set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Supplies information about RadzenDropDown ItemRender event.
|
||||
/// </summary>
|
||||
public class ListBoxItemRenderEventArgs<TValue> : DropDownBaseItemRenderEventArgs<TValue>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the DropDown.
|
||||
/// </summary>
|
||||
public RadzenListBox<TValue> ListBox { get; internal set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Supplies information about a <see cref="RadzenDatePicker{TValue}.DateRender" /> event that is being raised.
|
||||
/// </summary>
|
||||
@@ -591,12 +698,12 @@ namespace Radzen
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the appointment data.
|
||||
/// </summary>
|
||||
/// </summary>
|
||||
public AppointmentData Appointment { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the time span.
|
||||
/// </summary>
|
||||
/// </summary>
|
||||
public TimeSpan TimeSpan { get; set; }
|
||||
}
|
||||
|
||||
@@ -651,6 +758,11 @@ namespace Radzen
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if expandable; otherwise, <c>false</c>.</value>
|
||||
public bool Expandable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating row index.
|
||||
/// </summary>
|
||||
public int Index { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -681,23 +793,6 @@ namespace Radzen
|
||||
public bool FirstRender { get; internal set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Supplies information about a <see cref="RadzenGrid{TItem}.Render" /> event that is being raised.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public class GridRenderEventArgs<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the instance of the RadzenGrid component which has rendered.
|
||||
/// </summary>
|
||||
public RadzenGrid<T> Grid { get; internal set; }
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this is the first time the RadzenGrid has rendered.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this is the first time; otherwise, <c>false</c>.</value>
|
||||
public bool FirstRender { get; internal set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Supplies information about a <see cref="RadzenDataGrid{TItem}.Render" /> event that is being raised.
|
||||
/// </summary>
|
||||
@@ -726,18 +821,6 @@ namespace Radzen
|
||||
public DataGridSettings Settings { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Supplies information about a <see cref="RadzenGrid{TItem}.CellRender" /> event that is being raised.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public class CellRenderEventArgs<T> : RowRenderEventArgs<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the RadzenGridColumn which this cells represents.
|
||||
/// </summary>
|
||||
public RadzenGridColumn<T> Column { get; internal set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Supplies information about a <see cref="RadzenDataGrid{TItem}.CellRender" /> event that is being raised.
|
||||
/// </summary>
|
||||
@@ -767,6 +850,22 @@ namespace Radzen
|
||||
public RadzenDataGridColumn<T> Column { get; internal set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Supplies information about a <see cref="RadzenTree.ItemContextMenu" /> event that is being raised.
|
||||
/// </summary>
|
||||
public class TreeItemContextMenuEventArgs : Microsoft.AspNetCore.Components.Web.MouseEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the tree item text.
|
||||
/// </summary>
|
||||
public string Text { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the tree item value.
|
||||
/// </summary>
|
||||
public object Value { get; internal set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Supplies information about a <see cref="RadzenDataGrid{TItem}.RowClick" /> or <see cref="RadzenDataGrid{TItem}.RowDoubleClick" /> event that is being raised.
|
||||
/// </summary>
|
||||
@@ -841,12 +940,8 @@ namespace Radzen
|
||||
/// <summary>
|
||||
/// Represents a file which the user selects for upload via <see cref="RadzenUpload" />.
|
||||
/// </summary>
|
||||
public class FileInfo
|
||||
#if NET5_0_OR_GREATER
|
||||
: IBrowserFile
|
||||
#endif
|
||||
public class FileInfo : IBrowserFile
|
||||
{
|
||||
#if NET5_0_OR_GREATER
|
||||
/// <summary>
|
||||
/// Creates FileInfo.
|
||||
/// </summary>
|
||||
@@ -863,20 +958,16 @@ namespace Radzen
|
||||
{
|
||||
this.source = source;
|
||||
}
|
||||
#endif
|
||||
|
||||
string _name;
|
||||
/// <summary>
|
||||
/// Gets the name of the selected file.
|
||||
/// </summary>
|
||||
public string Name
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
#if NET5_0_OR_GREATER
|
||||
return _name ?? source.Name;
|
||||
#else
|
||||
return _name;
|
||||
#endif
|
||||
}
|
||||
set
|
||||
{
|
||||
@@ -892,11 +983,7 @@ namespace Radzen
|
||||
{
|
||||
get
|
||||
{
|
||||
#if NET5_0_OR_GREATER
|
||||
return _size != default(long) ? _size : source.Size;
|
||||
#else
|
||||
return _size;
|
||||
#endif
|
||||
return _size != default(long) ? _size : source != null ? source.Size : 0;
|
||||
}
|
||||
set
|
||||
{
|
||||
@@ -904,7 +991,6 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
#if NET5_0_OR_GREATER
|
||||
/// <summary>
|
||||
/// Gets the IBrowserFile.
|
||||
/// </summary>
|
||||
@@ -927,7 +1013,6 @@ namespace Radzen
|
||||
{
|
||||
return source.OpenReadStream(maxAllowedSize, cancellationToken);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1283,11 +1368,11 @@ namespace Radzen
|
||||
/// </summary>
|
||||
Light,
|
||||
/// <summary>
|
||||
/// Dark styling. Similar to dark buttons.
|
||||
/// Base styling. Similar to base buttons.
|
||||
/// </summary>
|
||||
Base,
|
||||
/// <summary>
|
||||
/// The default styling.
|
||||
/// Dark styling. Similar to dark buttons.
|
||||
/// </summary>
|
||||
Dark,
|
||||
/// <summary>
|
||||
@@ -1372,11 +1457,11 @@ namespace Radzen
|
||||
/// </summary>
|
||||
Light,
|
||||
/// <summary>
|
||||
/// Dark styling. Similar to dark buttons.
|
||||
/// Base styling. Similar to base buttons.
|
||||
/// </summary>
|
||||
Base,
|
||||
/// <summary>
|
||||
/// The default styling.
|
||||
/// Dark styling. Similar to dark buttons.
|
||||
/// </summary>
|
||||
Dark,
|
||||
/// <summary>
|
||||
@@ -1430,6 +1515,10 @@ namespace Radzen
|
||||
/// </summary>
|
||||
Light,
|
||||
/// <summary>
|
||||
/// Base styling. Similar to base buttons.
|
||||
/// </summary>
|
||||
Base,
|
||||
/// <summary>
|
||||
/// Dark styling. Similar to dark buttons.
|
||||
/// </summary>
|
||||
Dark,
|
||||
@@ -1657,6 +1746,10 @@ namespace Radzen
|
||||
/// </summary>
|
||||
Light,
|
||||
/// <summary>
|
||||
/// The base UI styling.
|
||||
/// </summary>
|
||||
Base,
|
||||
/// <summary>
|
||||
/// A button with dark styling.
|
||||
/// </summary>
|
||||
Dark,
|
||||
@@ -1744,7 +1837,11 @@ namespace Radzen
|
||||
/// <summary>
|
||||
/// The component displays a popup filtering UI and allows you to pick filtering operator and or filter by multiple values.
|
||||
/// </summary>
|
||||
Advanced
|
||||
Advanced,
|
||||
/// <summary>
|
||||
/// The component displays a popup filtering UI and allows you to pick multiple values from list of all values.
|
||||
/// </summary>
|
||||
CheckBoxList
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1939,6 +2036,10 @@ namespace Radzen
|
||||
/// </summary>
|
||||
Light,
|
||||
/// <summary>
|
||||
/// Base styling. Similar to base buttons.
|
||||
/// </summary>
|
||||
Base,
|
||||
/// <summary>
|
||||
/// Dark styling. Similar to dark buttons.
|
||||
/// </summary>
|
||||
Dark,
|
||||
@@ -1978,6 +2079,10 @@ namespace Radzen
|
||||
/// </summary>
|
||||
Light,
|
||||
/// <summary>
|
||||
/// Base styling. Similar to base buttons.
|
||||
/// </summary>
|
||||
Base,
|
||||
/// <summary>
|
||||
/// Dark styling. Similar to dark buttons.
|
||||
/// </summary>
|
||||
Dark,
|
||||
@@ -2099,6 +2204,28 @@ namespace Radzen
|
||||
public double Width { get; internal set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Supplies information about a <see cref="RadzenDataGrid{TItem}.ColumnReordering" /> event that is being raised.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public class DataGridColumnReorderingEventArgs<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the reordered RadzenDataGridColumn.
|
||||
/// </summary>
|
||||
public RadzenDataGridColumn<T> Column { get; internal set; }
|
||||
/// <summary>
|
||||
/// Gets the reordered to RadzenDataGridColumn.
|
||||
/// </summary>
|
||||
public RadzenDataGridColumn<T> ToColumn { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value which will cancel the event.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> to cancel the event; otherwise, <c>false</c>.</value>
|
||||
public bool Cancel { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Supplies information about a <see cref="RadzenDataGrid{TItem}.ColumnReordered" /> event that is being raised.
|
||||
/// </summary>
|
||||
@@ -2119,22 +2246,6 @@ namespace Radzen
|
||||
public int NewIndex { get; internal set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Supplies information about a <see cref="RadzenGrid{TItem}.ColumnResized" /> event that is being raised.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public class ColumnResizedEventArgs<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the resized RadzenGridColumn.
|
||||
/// </summary>
|
||||
public RadzenGridColumn<T> Column { get; internal set; }
|
||||
/// <summary>
|
||||
/// Gets the new width of the column.
|
||||
/// </summary>
|
||||
public double Width { get; internal set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a filter in a component that supports filtering.
|
||||
/// </summary>
|
||||
@@ -2345,6 +2456,46 @@ namespace Radzen
|
||||
internal IEnumerable<T> Data { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Supplies information about a <see cref="RadzenDataGrid{TItem}.LoadColumnFilterData" /> event that is being raised.
|
||||
/// </summary>
|
||||
public class DataGridLoadColumnFilterDataEventArgs<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the data.
|
||||
/// </summary>
|
||||
/// <value>The data.</value>
|
||||
public IEnumerable Data { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the total data count.
|
||||
/// </summary>
|
||||
/// <value>The total data count.</value>
|
||||
public int Count { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets how many items to skip. Related to paging and the current page. Usually used with the <see cref="Enumerable.Skip{TSource}(IEnumerable{TSource}, int)"/> LINQ method.
|
||||
/// </summary>
|
||||
public int? Skip { get; set; }
|
||||
/// <summary>
|
||||
/// Gets how many items to take. Related to paging and the current page size. Usually used with the <see cref="Enumerable.Take{TSource}(IEnumerable{TSource}, int)"/> LINQ method.
|
||||
/// </summary>
|
||||
/// <value>The top.</value>
|
||||
public int? Top { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the filter expression as a string.
|
||||
/// </summary>
|
||||
/// <value>The filter.</value>
|
||||
public string Filter { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the column.
|
||||
/// </summary>
|
||||
/// <value>The column.</value>
|
||||
public RadzenDataGridColumn<T> Column { get; internal set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Supplies information about a <see cref="RadzenPager.PageChanged" /> event that is being raised.
|
||||
/// </summary>
|
||||
@@ -2614,10 +2765,18 @@ namespace Radzen
|
||||
/// </summary>
|
||||
public Func<object, string> Text { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the function which returns a value for the <see cref="RadzenTreeItem.Checkable" /> of a child item.
|
||||
/// </summary>
|
||||
public Func<object, bool> Checkable { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the property which provides the value for the <see cref="RadzenTreeItem.Text" /> of a child item.
|
||||
/// </summary>
|
||||
public string TextProperty { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the property which provides the value for the <see cref="RadzenTreeItem.Checkable" /> of a child item.
|
||||
/// </summary>
|
||||
public string CheckableProperty { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets a function which returns whether a child item has children of its own. Called with an item from <see cref="Data" />.
|
||||
/// By default all items are considered to have children.
|
||||
/// </summary>
|
||||
@@ -2645,7 +2804,7 @@ namespace Radzen
|
||||
public class TreeItemRenderEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the item HTML attributes.
|
||||
/// Gets or sets the item HTML attributes.
|
||||
/// </summary>
|
||||
public IDictionary<string, object> Attributes { get; private set; } = new Dictionary<string, object>();
|
||||
|
||||
@@ -2660,7 +2819,7 @@ namespace Radzen
|
||||
/// Gets or sets a value indicating whether this item is checked.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if expanded; otherwise, <c>false</c>.</value>
|
||||
public bool? Checked
|
||||
public bool? Checked
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -2832,10 +2991,48 @@ namespace Radzen
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
#if NET6_0_OR_GREATER
|
||||
if (type == typeof(DateOnly))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified type is a DateOnly.
|
||||
/// </summary>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <returns><c>true</c> if the specified type is a DateOnly instance or nullable DateOnly; otherwise, <c>false</c>.</returns>
|
||||
public static bool IsDateOnly(Type source)
|
||||
{
|
||||
if (source == null) return false;
|
||||
var type = source.IsGenericType ? source.GetGenericArguments()[0] : source;
|
||||
|
||||
#if NET6_0_OR_GREATER
|
||||
if (type == typeof(DateOnly))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified type is a DateOnly.
|
||||
/// </summary>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <returns><c>true</c> if the specified type is a DateOnly instance or nullable DateOnly; otherwise, <c>false</c>.</returns>
|
||||
public static object DateOnlyFromDateTime(DateTime source)
|
||||
{
|
||||
object result = null;
|
||||
#if NET6_0_OR_GREATER
|
||||
result = DateOnly.FromDateTime(source);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the element of a collection time.
|
||||
/// </summary>
|
||||
@@ -2921,7 +3118,7 @@ namespace Radzen
|
||||
{
|
||||
var type = data.GetType();
|
||||
var arg = Expression.Parameter(typeof(object));
|
||||
var body = Expression.Property(Expression.Convert(arg, type), propertyName);
|
||||
var body = Expression.Convert(Expression.Property(Expression.Convert(arg, type), propertyName), typeof(T));
|
||||
|
||||
return Expression.Lambda<Func<object, T>>(body, arg).Compile();
|
||||
}
|
||||
@@ -3098,6 +3295,21 @@ namespace Radzen
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the dynamic property expression when binding to IDictionary.
|
||||
/// </summary>
|
||||
/// <param name="name">The property name.</param>
|
||||
/// <param name="type">The property type.</param>
|
||||
/// <returns>Dynamic property expression.</returns>
|
||||
public static string GetDynamicPropertyExpression(string name, Type type)
|
||||
{
|
||||
var isEnum = type.IsEnum || Nullable.GetUnderlyingType(type)?.IsEnum == true;
|
||||
var typeName = isEnum ? "Enum" : (Nullable.GetUnderlyingType(type) ?? type).Name;
|
||||
var typeFunc = $@"{typeName}{(!isEnum && Nullable.GetUnderlyingType(type) != null ? "?" : "")}";
|
||||
|
||||
return $@"{typeFunc}(it[""{name}""])";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -3157,12 +3369,11 @@ namespace Radzen
|
||||
/// </summary>
|
||||
/// <value>The field identifier.</value>
|
||||
FieldIdentifier FieldIdentifier { get; }
|
||||
#if NET5_0_OR_GREATER
|
||||
|
||||
/// <summary>
|
||||
/// Sets the focus.
|
||||
/// </summary>
|
||||
ValueTask FocusAsync();
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
110
Radzen.Blazor/CookieThemeService.cs
Normal file
110
Radzen.Blazor/CookieThemeService.cs
Normal file
@@ -0,0 +1,110 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.JSInterop;
|
||||
|
||||
namespace Radzen
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for the <see cref="CookieThemeService" />.
|
||||
/// </summary>
|
||||
public class CookieThemeServiceOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the cookie name.
|
||||
/// </summary>
|
||||
public string Name { get; set; } = "Theme";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the cookie duration.
|
||||
/// </summary>
|
||||
public TimeSpan Duration { get; set; } = TimeSpan.FromDays(365);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Persist the current theme in a cookie. Requires <see cref="ThemeService" /> to be registered in the DI container.
|
||||
/// </summary>
|
||||
public class CookieThemeService
|
||||
{
|
||||
private readonly CookieThemeServiceOptions options;
|
||||
private readonly IJSRuntime jsRuntime;
|
||||
private readonly ThemeService themeService;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CookieThemeService" /> class.
|
||||
/// </summary>
|
||||
public CookieThemeService(IJSRuntime jsRuntime, ThemeService themeService, IOptions<CookieThemeServiceOptions> options)
|
||||
{
|
||||
this.jsRuntime = jsRuntime;
|
||||
this.themeService = themeService;
|
||||
this.options = options.Value;
|
||||
|
||||
themeService.ThemeChanged += OnThemeChanged;
|
||||
|
||||
_ = InitializeAsync();
|
||||
}
|
||||
|
||||
private async Task InitializeAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var cookies = await jsRuntime.InvokeAsync<string>("eval", "document.cookie");
|
||||
|
||||
var themeCookie = cookies?.Split("; ").Select(x =>
|
||||
{
|
||||
var parts = x.Split("=");
|
||||
|
||||
return (Key: parts[0], Value: parts[1]);
|
||||
})
|
||||
.FirstOrDefault(x => x.Key == options.Name);
|
||||
|
||||
var theme = themeCookie?.Value;
|
||||
|
||||
if (!string.IsNullOrEmpty(theme) && themeService.Theme != theme)
|
||||
{
|
||||
themeService.SetTheme(theme);
|
||||
}
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private void OnThemeChanged()
|
||||
{
|
||||
var expiration = DateTime.Now.Add(options.Duration);
|
||||
|
||||
_ = jsRuntime.InvokeVoidAsync("eval", $"document.cookie = \"{options.Name}={themeService.Theme}; expires={expiration:R}; path=/\"");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extension methods to register the <see cref="CookieThemeService" />.
|
||||
/// </summary>
|
||||
public static class CookieThemeServiceCollectionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds the <see cref="CookieThemeService" /> to the service collection.
|
||||
/// </summary>
|
||||
public static IServiceCollection AddRadzenCookieThemeService(this IServiceCollection services)
|
||||
{
|
||||
services.AddOptions<CookieThemeServiceOptions>();
|
||||
services.AddScoped<CookieThemeService>();
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the <see cref="CookieThemeService" /> to the service collection with the specified configuration.
|
||||
/// </summary>
|
||||
public static IServiceCollection AddRadzenCookieThemeService(this IServiceCollection services, Action<CookieThemeServiceOptions> configure)
|
||||
{
|
||||
services.Configure(configure);
|
||||
services.AddScoped<CookieThemeService>();
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Forms;
|
||||
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using Radzen.Blazor;
|
||||
using Radzen.Blazor.Rendering;
|
||||
|
||||
@@ -278,7 +278,7 @@ namespace Radzen
|
||||
|
||||
query.Add($"{Enum.GetName(typeof(StringFilterOperator), FilterOperator)}(@0)");
|
||||
|
||||
_view = Query.Where(String.Join(".", query), ignoreCase ? searchText.ToLower() : searchText);
|
||||
_view = Query.Where(DynamicLinqCustomTypeProvider.ParsingConfig, string.Join(".", query), ignoreCase ? searchText.ToLower() : searchText);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -392,13 +392,12 @@ namespace Radzen
|
||||
.AddDisabled(Disabled)
|
||||
.Add(FieldIdentifier, EditContext)
|
||||
.Add("rz-state-empty", !HasValue);
|
||||
#if NET5_0_OR_GREATER
|
||||
|
||||
/// <inheritdoc/>
|
||||
public virtual async ValueTask FocusAsync()
|
||||
{
|
||||
await Element.FocusAsync();
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary> Provides support for RadzenFormField integration. </summary>
|
||||
[CascadingParameter]
|
||||
@@ -406,5 +405,20 @@ namespace Radzen
|
||||
|
||||
/// <summary> Gets the current placeholder. Returns empty string if this component is inside a RadzenFormField.</summary>
|
||||
protected string CurrentPlaceholder => FormFieldContext?.AllowFloatingLabel == true ? " " : Placeholder;
|
||||
|
||||
/// <summary>
|
||||
/// Handles the <see cref="E:ContextMenu" /> event.
|
||||
/// </summary>
|
||||
/// <param name="args">The <see cref="MouseEventArgs"/> instance containing the event data.</param>
|
||||
/// <returns>Task.</returns>
|
||||
public override Task OnContextMenu(MouseEventArgs args)
|
||||
{
|
||||
if (!Disabled)
|
||||
{
|
||||
return base.OnContextMenu(args);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using Microsoft.JSInterop;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -24,7 +25,7 @@ namespace Radzen
|
||||
/// <div class="row">
|
||||
/// <div class="col-md-12">
|
||||
/// <RadzenButton Text="Ok" Click="() => ds.Close(true)" Style="margin-bottom: 10px; width: 150px" />
|
||||
/// <RadzenButton Text="Cancel" Click="() => ds.Close(false)" ButtonStyle="ButtonStyle.Secondary" Style="margin-bottom: 10px; width: 150px"/>
|
||||
/// <RadzenButton Text="Cancel" Click="() => ds.Close(false)" ButtonStyle="ButtonStyle.Base" Style="margin-bottom: 10px; width: 150px"/>
|
||||
/// <RadzenButton Text="Refresh" Click="(() => { orderID = 10249; ds.Refresh(); })" ButtonStyle="ButtonStyle.Info" Style="margin-bottom: 10px; width: 150px"/>
|
||||
/// Order ID: @orderID
|
||||
/// </div>
|
||||
@@ -279,6 +280,9 @@ namespace Radzen
|
||||
CssClass = options != null ? options.CssClass : "",
|
||||
WrapperCssClass = options != null ? options.WrapperCssClass : "",
|
||||
CloseTabIndex = options != null ? options.CloseTabIndex : 0,
|
||||
ContentCssClass = options != null ? options.ContentCssClass : "",
|
||||
Resize = options?.Resize,
|
||||
Drag = options?.Drag
|
||||
});
|
||||
}
|
||||
|
||||
@@ -364,7 +368,7 @@ namespace Radzen
|
||||
|
||||
b.OpenComponent<Blazor.RadzenButton>(i++);
|
||||
b.AddAttribute(i++, "Text", options != null ? options.CancelButtonText : "Cancel");
|
||||
b.AddAttribute(i++, "ButtonStyle", ButtonStyle.Secondary);
|
||||
b.AddAttribute(i++, "ButtonStyle", ButtonStyle.Base);
|
||||
b.AddAttribute(i++, "Click", EventCallback.Factory.Create<Microsoft.AspNetCore.Components.Web.MouseEventArgs>(this, () => ds.Close(false)));
|
||||
b.CloseComponent();
|
||||
|
||||
@@ -401,6 +405,7 @@ namespace Radzen
|
||||
CloseDialogOnEsc = options != null ? options.CloseDialogOnEsc : true,
|
||||
CssClass = options != null ? $"rz-dialog-alert {options.CssClass}" : "rz-dialog-alert",
|
||||
WrapperCssClass = options != null ? $"rz-dialog-wrapper {options.WrapperCssClass}" : "rz-dialog-wrapper",
|
||||
ContentCssClass = options != null ? $"rz-dialog-content {options.ContentCssClass}" : "rz-dialog-content",
|
||||
CloseTabIndex = options != null ? options.CloseTabIndex : 0,
|
||||
};
|
||||
|
||||
@@ -476,7 +481,12 @@ namespace Radzen
|
||||
/// Gets or sets the CSS classes added to the dialog's wrapper element.
|
||||
/// </summary>
|
||||
public string WrapperCssClass { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the CSS classes added to the dialog's content element.
|
||||
/// </summary>
|
||||
public string ContentCssClass { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value the dialog escape tabindex. Set to <c>0</c> by default.
|
||||
/// </summary>
|
||||
@@ -502,6 +512,11 @@ namespace Radzen
|
||||
/// Whether to show a mask on the background or not
|
||||
/// </summary>
|
||||
public bool ShowMask { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to focus the first focusable HTML element. Set to <c>true</c> by default.
|
||||
/// </summary>
|
||||
public bool AutoFocusFirstElement { get; set; } = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -537,11 +552,25 @@ namespace Radzen
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if resizable; otherwise, <c>false</c>.</value>
|
||||
public bool Resizable { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the change.
|
||||
/// </summary>
|
||||
/// <value>The change.</value>
|
||||
public Action<Size> Resize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the dialog is draggable. Set to <c>false</c> by default.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if draggable; otherwise, <c>false</c>.</value>
|
||||
public bool Draggable { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the change.
|
||||
/// </summary>
|
||||
/// <value>The change.</value>
|
||||
public Action<Point> Drag { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the X coordinate of the dialog. Maps to the <c>left</c> CSS attribute.
|
||||
/// </summary>
|
||||
|
||||
@@ -17,7 +17,6 @@ namespace Radzen
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public class DropDownBase<T> : DataBoundFormComponent<T>
|
||||
{
|
||||
#if NET5_0_OR_GREATER
|
||||
/// <summary>
|
||||
/// Gets or sets a value that determines how many additional items will be rendered before and after the visible region. This help to reduce the frequency of rendering during scrolling. However, higher values mean that more elements will be present in the page.
|
||||
/// </summary>
|
||||
@@ -46,7 +45,7 @@ namespace Radzen
|
||||
var totalItemsCount = LoadData.HasDelegate ? Count : view.Count();
|
||||
var top = request.Count;
|
||||
|
||||
if(top <= 0)
|
||||
if (top <= 0)
|
||||
{
|
||||
top = PageSize;
|
||||
}
|
||||
@@ -78,27 +77,19 @@ namespace Radzen
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public int PageSize { get; set; } = 5;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether virtualization is allowed.
|
||||
/// </summary>
|
||||
/// <returns><c>true</c> if virtualization is allowed; otherwise, <c>false</c>.</returns>
|
||||
internal bool IsVirtualizationAllowed()
|
||||
{
|
||||
#if NET5_0_OR_GREATER
|
||||
return AllowVirtualization;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
internal int GetVirtualizationOverscanCount()
|
||||
{
|
||||
#if NET5_0_OR_GREATER
|
||||
return VirtualizationOverscanCount;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -109,7 +100,6 @@ namespace Radzen
|
||||
{
|
||||
return new RenderFragment(builder =>
|
||||
{
|
||||
#if NET5_0_OR_GREATER
|
||||
if (AllowVirtualization)
|
||||
{
|
||||
builder.OpenComponent(0, typeof(Microsoft.AspNetCore.Components.Web.Virtualization.Virtualize<object>));
|
||||
@@ -122,7 +112,7 @@ namespace Radzen
|
||||
});
|
||||
}));
|
||||
|
||||
if(VirtualizationOverscanCount != default(int))
|
||||
if (VirtualizationOverscanCount != default(int))
|
||||
{
|
||||
builder.AddAttribute(3, "OverscanCount", VirtualizationOverscanCount);
|
||||
}
|
||||
@@ -138,12 +128,6 @@ namespace Radzen
|
||||
RenderItem(builder, item);
|
||||
}
|
||||
}
|
||||
#else
|
||||
foreach (var item in LoadData.HasDelegate ? Data : View)
|
||||
{
|
||||
RenderItem(builder, item);
|
||||
}
|
||||
#endif
|
||||
});
|
||||
}
|
||||
|
||||
@@ -194,6 +178,13 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the header template.
|
||||
/// </summary>
|
||||
/// <value>The header template.</value>
|
||||
[Parameter]
|
||||
public RenderFragment HeaderTemplate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether filtering is allowed. Set to <c>false</c> by default.
|
||||
/// </summary>
|
||||
@@ -264,12 +255,19 @@ namespace Radzen
|
||||
[Parameter]
|
||||
public string SearchAriaLabel { get; set; } = "Search";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the empty value aria label text.
|
||||
/// </summary>
|
||||
/// <value>The empty value aria label text.</value>
|
||||
[Parameter]
|
||||
public string EmptyAriaLabel { get; set; } = "Empty";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the selected item changed.
|
||||
/// </summary>
|
||||
/// <value>The selected item changed.</value>
|
||||
[Parameter]
|
||||
public Action<object> SelectedItemChanged { get; set; }
|
||||
public EventCallback<object> SelectedItemChanged { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The selected items
|
||||
@@ -283,7 +281,7 @@ namespace Radzen
|
||||
/// <summary>
|
||||
/// Selects all.
|
||||
/// </summary>
|
||||
protected async System.Threading.Tasks.Task SelectAll()
|
||||
protected virtual async System.Threading.Tasks.Task SelectAll()
|
||||
{
|
||||
if (Disabled)
|
||||
{
|
||||
@@ -337,6 +335,8 @@ namespace Radzen
|
||||
await Change.InvokeAsync(internalValue);
|
||||
|
||||
StateHasChanged();
|
||||
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.focusElement", GetId());
|
||||
}
|
||||
|
||||
internal bool IsAllSelected()
|
||||
@@ -441,21 +441,34 @@ namespace Radzen
|
||||
|
||||
if (!string.IsNullOrEmpty(ValueProperty))
|
||||
{
|
||||
valuePropertyGetter = PropertyAccess.Getter<object, object>(ValueProperty, type);
|
||||
valuePropertyGetter = GetGetter(ValueProperty, type);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(TextProperty))
|
||||
{
|
||||
textPropertyGetter = PropertyAccess.Getter<object, object>(TextProperty, type);
|
||||
textPropertyGetter = GetGetter(TextProperty, type);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(DisabledProperty))
|
||||
{
|
||||
disabledPropertyGetter = PropertyAccess.Getter<object, object>(DisabledProperty, type);
|
||||
disabledPropertyGetter = GetGetter(DisabledProperty, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Func<object, object> GetGetter(string propertyName, Type type)
|
||||
{
|
||||
if (propertyName?.Contains("[") == true)
|
||||
{
|
||||
var getter = typeof(PropertyAccess).GetMethod("Getter", [typeof(string), typeof(Type)]);
|
||||
var getterMethod = getter.MakeGenericMethod([type, typeof(object)]);
|
||||
|
||||
return (i) => getterMethod.Invoke(i, [propertyName, type]);
|
||||
}
|
||||
|
||||
return PropertyAccess.Getter<object, object>(propertyName, type);
|
||||
}
|
||||
|
||||
internal Func<object, object> valuePropertyGetter;
|
||||
internal Func<object, object> textPropertyGetter;
|
||||
internal Func<object, object> disabledPropertyGetter;
|
||||
@@ -493,7 +506,6 @@ namespace Radzen
|
||||
return item;
|
||||
}
|
||||
|
||||
#if NET5_0_OR_GREATER
|
||||
/// <inheritdoc/>
|
||||
protected override async Task OnDataChanged()
|
||||
{
|
||||
@@ -504,7 +516,6 @@ namespace Radzen
|
||||
await InvokeAsync(Virtualize.RefreshDataAsync);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Gets the popup identifier.
|
||||
@@ -522,7 +533,7 @@ namespace Radzen
|
||||
/// Gets the search identifier.
|
||||
/// </summary>
|
||||
/// <value>The search identifier.</value>
|
||||
protected string SearchID
|
||||
public string SearchID
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -624,9 +635,7 @@ namespace Radzen
|
||||
{
|
||||
if (IsVirtualizationAllowed())
|
||||
{
|
||||
#if NET5_0_OR_GREATER
|
||||
items = virtualItems;
|
||||
#endif
|
||||
items = virtualItems ?? Enumerable.Empty<object>().ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -648,7 +657,11 @@ namespace Radzen
|
||||
|
||||
if (!Multiple && !popupOpened && shouldSelectOnChange != false)
|
||||
{
|
||||
await OnSelectItem(items.ElementAt(selectedIndex), true);
|
||||
var itemToSelect = items.ElementAtOrDefault(selectedIndex);
|
||||
if (itemToSelect != null)
|
||||
{
|
||||
await OnSelectItem(itemToSelect, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
@@ -662,8 +675,14 @@ namespace Radzen
|
||||
|
||||
if (selectedIndex >= 0 && selectedIndex <= items.Count() - 1)
|
||||
{
|
||||
var itemToSelect = items.ElementAtOrDefault(selectedIndex);
|
||||
|
||||
await JSRuntime.InvokeAsync<string>("Radzen.setInputValue", search, $"{searchText}".Trim());
|
||||
await OnSelectItem(items.ElementAt(selectedIndex), true);
|
||||
|
||||
if (itemToSelect != null)
|
||||
{
|
||||
await OnSelectItem(itemToSelect, true);
|
||||
}
|
||||
}
|
||||
|
||||
var popupOpened = await JSRuntime.InvokeAsync<bool>("Radzen.popupOpened", PopupID);
|
||||
@@ -676,7 +695,7 @@ namespace Radzen
|
||||
{
|
||||
if (!Multiple)
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.closePopup", PopupID);
|
||||
await ClosePopup(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -688,7 +707,7 @@ namespace Radzen
|
||||
}
|
||||
else if (key == "Escape" || key == "Tab")
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.closePopup", PopupID);
|
||||
await ClosePopup(key);
|
||||
}
|
||||
else if (key == "Delete" && AllowClear)
|
||||
{
|
||||
@@ -711,12 +730,9 @@ namespace Radzen
|
||||
|
||||
Debounce(DebounceFilter, FilterDelay);
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
var filteredItems = GetView(items.AsQueryable(),
|
||||
args.Key,
|
||||
StringFilterOperator.StartsWith,
|
||||
FilterCaseSensitivity.CaseInsensitive)
|
||||
var filteredItems = Query.Where(TextProperty, args.Key, StringFilterOperator.StartsWith, FilterCaseSensitivity.CaseInsensitive)
|
||||
.Cast<object>()
|
||||
.ToList();
|
||||
|
||||
@@ -724,7 +740,7 @@ namespace Radzen
|
||||
if (previousKey != args.Key)
|
||||
{
|
||||
previousKey = args.Key;
|
||||
itemIndex = 0;
|
||||
itemIndex = -1;
|
||||
}
|
||||
|
||||
itemIndex = itemIndex + 1 >= filteredItems.Count() ? 0 : itemIndex + 1;
|
||||
@@ -745,13 +761,18 @@ namespace Radzen
|
||||
selectedIndex = result.Index;
|
||||
}
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.selectListItem", list, list, result.Index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
preventKeydown = false;
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual async Task ClosePopup(string key)
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.closePopup", PopupID);
|
||||
}
|
||||
|
||||
int itemIndex;
|
||||
string previousKey;
|
||||
|
||||
@@ -774,13 +795,11 @@ namespace Radzen
|
||||
_view = null;
|
||||
if (IsVirtualizationAllowed())
|
||||
{
|
||||
#if NET5_0_OR_GREATER
|
||||
if (virtualize != null)
|
||||
{
|
||||
await virtualize.RefreshDataAsync();
|
||||
}
|
||||
await InvokeAsync(() => { StateHasChanged(); });
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -791,7 +810,6 @@ namespace Radzen
|
||||
{
|
||||
if (IsVirtualizationAllowed())
|
||||
{
|
||||
#if NET5_0_OR_GREATER
|
||||
if (virtualize != null)
|
||||
{
|
||||
await InvokeAsync(virtualize.RefreshDataAsync);
|
||||
@@ -801,7 +819,6 @@ namespace Radzen
|
||||
await LoadData.InvokeAsync(await GetLoadDataArgs());
|
||||
}
|
||||
await InvokeAsync(() => { StateHasChanged(); });
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -851,7 +868,6 @@ namespace Radzen
|
||||
/// <returns>LoadDataArgs.</returns>
|
||||
internal virtual async System.Threading.Tasks.Task<LoadDataArgs> GetLoadDataArgs()
|
||||
{
|
||||
#if NET5_0_OR_GREATER
|
||||
if (AllowVirtualization)
|
||||
{
|
||||
return await Task.FromResult(new Radzen.LoadDataArgs() { Skip = 0, Top = PageSize, Filter = searchText });
|
||||
@@ -860,9 +876,6 @@ namespace Radzen
|
||||
{
|
||||
return await Task.FromResult(new Radzen.LoadDataArgs() { Filter = searchText });
|
||||
}
|
||||
#else
|
||||
return await Task.FromResult(new Radzen.LoadDataArgs() { Filter = searchText });
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -897,13 +910,12 @@ namespace Radzen
|
||||
/// <returns>A Task representing the asynchronous operation.</returns>
|
||||
public override async Task SetParametersAsync(ParameterView parameters)
|
||||
{
|
||||
#if NET5_0_OR_GREATER
|
||||
var pageSize = parameters.GetValueOrDefault<int>(nameof(PageSize));
|
||||
if(pageSize != default(int))
|
||||
if (pageSize != default(int))
|
||||
{
|
||||
PageSize = pageSize;
|
||||
}
|
||||
#endif
|
||||
|
||||
var selectedItemChanged = parameters.DidParameterChange(nameof(SelectedItem), SelectedItem);
|
||||
if (selectedItemChanged)
|
||||
{
|
||||
@@ -941,7 +953,7 @@ namespace Radzen
|
||||
|
||||
if (valueAsEnumerable != null)
|
||||
{
|
||||
if (!valueAsEnumerable.Cast<object>().SequenceEqual(selectedItems.Select(i => GetItemOrValueFromProperty(i, ValueProperty))))
|
||||
if (!valueAsEnumerable.Cast<object>().SequenceEqual(selectedItems.Select(i => string.IsNullOrEmpty(ValueProperty) ? i : GetItemOrValueFromProperty(i, ValueProperty))))
|
||||
{
|
||||
selectedItems.Clear();
|
||||
}
|
||||
@@ -1024,71 +1036,6 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
IQueryable GetView(IQueryable source, string value, StringFilterOperator? op = null, FilterCaseSensitivity? cs = null)
|
||||
{
|
||||
IQueryable result;
|
||||
|
||||
if (!string.IsNullOrEmpty(value))
|
||||
{
|
||||
var ignoreCase = (cs ?? FilterCaseSensitivity) == FilterCaseSensitivity.CaseInsensitive;
|
||||
|
||||
var query = new List<string>();
|
||||
|
||||
if (!string.IsNullOrEmpty(TextProperty))
|
||||
{
|
||||
query.Add(TextProperty);
|
||||
}
|
||||
|
||||
if (typeof(EnumerableQuery).IsAssignableFrom(source.GetType()))
|
||||
{
|
||||
query.Add("ToString()");
|
||||
}
|
||||
|
||||
if (ignoreCase)
|
||||
{
|
||||
query.Add("ToLower()");
|
||||
}
|
||||
|
||||
query.Add($"{Enum.GetName(typeof(StringFilterOperator), op ?? FilterOperator)}(@0)");
|
||||
|
||||
var search = ignoreCase ? value.ToLower() : value;
|
||||
|
||||
if (source.ElementType == typeof(Enum))
|
||||
{
|
||||
result = source.Cast<Enum>()
|
||||
.Where((Func<Enum, bool>)(i =>
|
||||
{
|
||||
var v = ignoreCase ? i.GetDisplayDescription().ToLower() : i.GetDisplayDescription();
|
||||
|
||||
if (FilterOperator == StringFilterOperator.Contains)
|
||||
{
|
||||
return v.Contains(search);
|
||||
}
|
||||
else if (FilterOperator == StringFilterOperator.StartsWith)
|
||||
{
|
||||
return v.StartsWith(search);
|
||||
}
|
||||
else if (FilterOperator == StringFilterOperator.EndsWith)
|
||||
{
|
||||
return v.EndsWith(search);
|
||||
}
|
||||
|
||||
return v == search;
|
||||
})).AsQueryable();
|
||||
}
|
||||
else
|
||||
{
|
||||
result = source.Where(String.Join(".", query), search);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = source;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the view.
|
||||
/// </summary>
|
||||
@@ -1099,7 +1046,7 @@ namespace Radzen
|
||||
{
|
||||
if (_view == null && Query != null)
|
||||
{
|
||||
_view = GetView(Query, searchText);
|
||||
_view = Query.Where(TextProperty, searchText, FilterOperator, FilterCaseSensitivity);
|
||||
}
|
||||
|
||||
return _view;
|
||||
@@ -1147,7 +1094,7 @@ namespace Radzen
|
||||
/// <param name="raiseChange">if set to <c>true</c> [raise change].</param>
|
||||
public async System.Threading.Tasks.Task SelectItem(object item, bool raiseChange = true)
|
||||
{
|
||||
if (disabledPropertyGetter != null && disabledPropertyGetter(item) as bool? == true)
|
||||
if (disabledPropertyGetter != null && item != null && disabledPropertyGetter(item) as bool? == true)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -1169,7 +1116,7 @@ namespace Radzen
|
||||
|
||||
SetSelectedIndexFromSelectedItem();
|
||||
|
||||
SelectedItemChanged?.Invoke(selectedItem);
|
||||
await SelectedItemChanged.InvokeAsync(selectedItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1267,7 +1214,7 @@ namespace Radzen
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedItems = selectedItems.AsQueryable().Where($@"!object.Equals(it.{ValueProperty},@0)", value).ToList();
|
||||
selectedItems = selectedItems.AsQueryable().Where(DynamicLinqCustomTypeProvider.ParsingConfig, $@"!object.Equals(it.{ValueProperty},@0)", value).ToList();
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1302,7 +1249,7 @@ namespace Radzen
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectedItem = view.AsQueryable().Where($@"{ValueProperty} == @0", value).FirstOrDefault();
|
||||
SelectedItem = view.AsQueryable().Where(DynamicLinqCustomTypeProvider.ParsingConfig, $@"{ValueProperty} == @0", value).FirstOrDefault();
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1311,8 +1258,6 @@ namespace Radzen
|
||||
}
|
||||
|
||||
SetSelectedIndexFromSelectedItem();
|
||||
|
||||
SelectedItemChanged?.Invoke(selectedItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1331,10 +1276,10 @@ namespace Radzen
|
||||
}
|
||||
else
|
||||
{
|
||||
item = view.AsQueryable().Where($@"{ValueProperty} == @0", v).FirstOrDefault();
|
||||
item = view.AsQueryable().Where(DynamicLinqCustomTypeProvider.ParsingConfig, $@"{ValueProperty} == @0", v).FirstOrDefault();
|
||||
}
|
||||
|
||||
if (!object.Equals(item, null) && !selectedItems.AsQueryable().Where($@"object.Equals(it.{ValueProperty},@0)", v).Any())
|
||||
if (!object.Equals(item, null) && !selectedItems.AsQueryable().Where(DynamicLinqCustomTypeProvider.ParsingConfig, $@"object.Equals(it.{ValueProperty},@0)", v).Any())
|
||||
{
|
||||
selectedItems.Add(item);
|
||||
}
|
||||
|
||||
18
Radzen.Blazor/DynamicLinqCustomTypeProvider.cs
Normal file
18
Radzen.Blazor/DynamicLinqCustomTypeProvider.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Dynamic.Core;
|
||||
using System.Linq.Dynamic.Core.CustomTypeProviders;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
class DynamicLinqCustomTypeProvider : IDynamicLinkCustomTypeProvider
|
||||
{
|
||||
static readonly HashSet<Type> empty = [];
|
||||
public HashSet<Type> GetCustomTypes() => empty;
|
||||
public Dictionary<Type, List<MethodInfo>> GetExtensionMethods() => throw new NotSupportedException();
|
||||
public Type ResolveType(string typeName) => throw new NotSupportedException();
|
||||
public Type ResolveTypeBySimpleName(string simpleTypeName) => throw new NotSupportedException();
|
||||
public static ParsingConfig ParsingConfig = new() { CustomTypeProvider = new DynamicLinqCustomTypeProvider() };
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,8 @@ namespace Radzen.Blazor
|
||||
/// </summary>
|
||||
public static IEnumerable<object> EnumAsKeyValuePair(Type enumType, Func<string, string> translationFunction = null)
|
||||
{
|
||||
return Enum.GetValues(enumType).Cast<Enum>().Distinct().Select(val => new { Value = Convert.ToInt32(val), Text = val.GetDisplayDescription(translationFunction) });
|
||||
Type underlyingType = Enum.GetUnderlyingType(enumType);
|
||||
return Enum.GetValues(enumType).Cast<Enum>().Distinct().Select(val => new { Value = Convert.ChangeType(val, underlyingType), Text = val.GetDisplayDescription(translationFunction) });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -16,13 +16,6 @@ namespace Radzen
|
||||
/// </summary>
|
||||
public class FormComponentWithAutoComplete<T> : FormComponent<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating the browser built-in autocomplete is enabled.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if input automatic complete is enabled; otherwise, <c>false</c>.</value>
|
||||
[Parameter]
|
||||
public virtual bool AutoComplete { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating the type of built-in autocomplete
|
||||
/// the browser should use.
|
||||
@@ -44,8 +37,8 @@ namespace Radzen
|
||||
/// AutoCompleteType.</value>
|
||||
public virtual string AutoCompleteAttribute
|
||||
{
|
||||
get => !AutoComplete ? DefaultAutoCompleteAttribute :
|
||||
autoComplete as string ?? AutoCompleteType.GetAutoCompleteValue();
|
||||
get => Attributes != null && Attributes.ContainsKey("AutoComplete") && $"{Attributes["AutoComplete"]}".ToLower() == "false" ? DefaultAutoCompleteAttribute :
|
||||
Attributes != null && Attributes.ContainsKey("AutoComplete") ? Attributes["AutoComplete"] as string ?? AutoCompleteType.GetAutoCompleteValue() : AutoCompleteType.GetAutoCompleteValue();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -53,18 +46,11 @@ namespace Radzen
|
||||
/// </summary>
|
||||
public virtual string DefaultAutoCompleteAttribute { get; set; } = "off";
|
||||
|
||||
object autoComplete;
|
||||
object ariaAutoComplete;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async Task SetParametersAsync(ParameterView parameters)
|
||||
{
|
||||
parameters = parameters.TryGetValue(nameof(AutoComplete).ToLower(), out autoComplete) ?
|
||||
ParameterView.FromDictionary(parameters
|
||||
.ToDictionary().Where(i => i.Key != nameof(AutoComplete).ToLower()).ToDictionary(i => i.Key, i => i.Value)
|
||||
.ToDictionary(i => i.Key, i => i.Value))
|
||||
: parameters;
|
||||
|
||||
parameters = parameters.TryGetValue("aria-autocomplete", out ariaAutoComplete) ?
|
||||
ParameterView.FromDictionary(parameters
|
||||
.ToDictionary().Where(i => i.Key != "aria-autocomplete").ToDictionary(i => i.Key, i => i.Value)
|
||||
@@ -326,12 +312,11 @@ namespace Radzen
|
||||
|
||||
/// <summary> Gets the current placeholder. Returns empty string if this component is inside a RadzenFormField.</summary>
|
||||
protected string CurrentPlaceholder => FormFieldContext?.AllowFloatingLabel == true ? " " : Placeholder;
|
||||
#if NET5_0_OR_GREATER
|
||||
|
||||
/// <inheritdoc/>
|
||||
public virtual async ValueTask FocusAsync()
|
||||
{
|
||||
await Element.FocusAsync();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,6 +60,10 @@ namespace Radzen.Blazor
|
||||
/// <returns>RenderFragment.</returns>
|
||||
RenderFragment RenderTooltip(object data, double marginLeft, double marginTop, double chartHeight);
|
||||
/// <summary>
|
||||
/// Renders a tooltip item with the specified data to be displayed in a shared tooltip
|
||||
/// </summary>
|
||||
RenderFragment RenderSharedTooltipItem(object category);
|
||||
/// <summary>
|
||||
/// Renders the legend item.
|
||||
/// </summary>
|
||||
/// <returns>RenderFragment.</returns>
|
||||
|
||||
@@ -16,5 +16,11 @@ namespace Radzen.Blazor
|
||||
/// Gets the values for category.
|
||||
/// </summary>
|
||||
IEnumerable<double> ValuesForCategory(double category);
|
||||
/// <summary>
|
||||
/// Gets the items for category.
|
||||
/// </summary>
|
||||
/// <param name="category"></param>
|
||||
/// <returns></returns>
|
||||
IEnumerable<object> ItemsForCategory(double category);
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,13 @@ namespace Radzen.Blazor
|
||||
/// </summary>
|
||||
IEnumerable<double> ValuesForCategory(double category);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the items for category.
|
||||
/// </summary>
|
||||
/// <param name="category"></param>
|
||||
/// <returns></returns>
|
||||
IEnumerable<object> ItemsForCategory(double category);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value at the specified index.
|
||||
/// </summary>
|
||||
|
||||
@@ -71,6 +71,12 @@ namespace Radzen.Blazor
|
||||
/// <param name="appointments">The appointments for this range.</param>
|
||||
Task<bool> SelectSlot(DateTime start, DateTime end, IEnumerable<AppointmentData> appointments);
|
||||
/// <summary>
|
||||
/// Selects the specified month.
|
||||
/// </summary>
|
||||
/// <param name="monthStart">The start of the month.</param>
|
||||
/// <param name="appointments">The appointments for this range.</param>
|
||||
Task SelectMonth(DateTime monthStart, IEnumerable<AppointmentData> appointments);
|
||||
/// <summary>
|
||||
/// Selects the specified more link.
|
||||
/// </summary>
|
||||
/// <param name="start">The start.</param>
|
||||
|
||||
@@ -88,11 +88,6 @@ namespace Radzen.Blazor
|
||||
if (Step is IConvertible)
|
||||
{
|
||||
step = Convert.ToDouble(Step);
|
||||
|
||||
if (step <= 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("Step must be greater than zero");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +97,7 @@ namespace Radzen.Blazor
|
||||
end = Math.Ceiling(end / step) * step;
|
||||
}
|
||||
|
||||
if (!Double.IsFinite(Input.Start) && !Double.IsFinite(Input.End))
|
||||
if (!double.IsFinite(Input.Start) || !double.IsFinite(Input.End))
|
||||
{
|
||||
Input.Start = start = 0;
|
||||
Input.End = end = 2;
|
||||
@@ -110,7 +105,7 @@ namespace Radzen.Blazor
|
||||
Round = false;
|
||||
}
|
||||
|
||||
if (!Double.IsFinite(start) && !Double.IsFinite(end))
|
||||
if (!double.IsFinite(start) || !double.IsFinite(end))
|
||||
{
|
||||
Input.Start = start = 0;
|
||||
Input.End = end = 2;
|
||||
@@ -118,6 +113,11 @@ namespace Radzen.Blazor
|
||||
Round = false;
|
||||
}
|
||||
|
||||
if (step <= 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("Step must be greater than zero");
|
||||
}
|
||||
|
||||
return (start, end, step);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,9 +231,10 @@ namespace Radzen
|
||||
/// <param name="orderby">The orderby.</param>
|
||||
/// <param name="expand">The expand.</param>
|
||||
/// <param name="select">The select.</param>
|
||||
/// <param name="apply">The apply.</param>
|
||||
/// <param name="count">if set to <c>true</c> [count].</param>
|
||||
/// <returns>Uri.</returns>
|
||||
public static Uri GetODataUri(this Uri uri, string filter = null, int? top = null, int? skip = null, string orderby = null, string expand = null, string select = null, bool? count = null)
|
||||
public static Uri GetODataUri(this Uri uri, string filter = null, int? top = null, int? skip = null, string orderby = null, string expand = null, string select = null, string apply = null, bool? count = null)
|
||||
{
|
||||
var uriBuilder = new UriBuilder(uri);
|
||||
var queryString = HttpUtility.ParseQueryString(uriBuilder.Query);
|
||||
@@ -268,6 +269,11 @@ namespace Radzen
|
||||
queryString["$select"] = $"{select}";
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(apply))
|
||||
{
|
||||
queryString["$apply"] = $"{apply}";
|
||||
}
|
||||
|
||||
if (count != null)
|
||||
{
|
||||
queryString["$count"] = $"{count}".ToLower();
|
||||
|
||||
189
Radzen.Blazor/QueryStringThemeService.cs
Normal file
189
Radzen.Blazor/QueryStringThemeService.cs
Normal file
@@ -0,0 +1,189 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Routing;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Radzen
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for the <see cref="QueryStringThemeService" />.
|
||||
/// </summary>
|
||||
public class QueryStringThemeServiceOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the query string parameter for the theme.
|
||||
/// </summary>
|
||||
public string ThemeParameter { get; set; } = "theme";
|
||||
/// <summary>
|
||||
/// Gets or sets the query string parameter for the wcag compatible color theme.
|
||||
/// </summary>
|
||||
public string WcagParameter { get; set; } = "wcag";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the query string parameter for the right to left theme.
|
||||
/// </summary>
|
||||
public string RightToLeftParameter { get; set; } = "rtl";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Persist the current theme in the query string. Requires <see cref="ThemeService" /> to be registered in the DI container.
|
||||
/// </summary>
|
||||
public class QueryStringThemeService : IDisposable
|
||||
{
|
||||
private readonly NavigationManager navigationManager;
|
||||
private readonly ThemeService themeService;
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
private readonly IDisposable registration;
|
||||
#endif
|
||||
private readonly QueryStringThemeServiceOptions options;
|
||||
private readonly PropertyInfo hasAttachedJSRuntimeProperty;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="QueryStringThemeService" /> class.
|
||||
/// </summary>
|
||||
public QueryStringThemeService(NavigationManager navigationManager, ThemeService themeService, IOptions<QueryStringThemeServiceOptions> options)
|
||||
{
|
||||
this.navigationManager = navigationManager;
|
||||
|
||||
this.themeService = themeService;
|
||||
|
||||
this.options = options.Value;
|
||||
|
||||
hasAttachedJSRuntimeProperty = navigationManager.GetType().GetProperty("HasAttachedJSRuntime");
|
||||
|
||||
var state = GetStateFromQueryString(navigationManager.Uri);
|
||||
|
||||
if (state.theme != null && RequiresChange(state))
|
||||
{
|
||||
themeService.SetTheme(new ThemeOptions
|
||||
{
|
||||
Theme = state.theme,
|
||||
Wcag = state.wcag,
|
||||
RightToLeft = state.rightToLeft,
|
||||
TriggerChange = true
|
||||
});
|
||||
}
|
||||
|
||||
themeService.ThemeChanged += OnThemeChanged;
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
try
|
||||
{
|
||||
registration = navigationManager.RegisterLocationChangingHandler(OnLocationChanging);
|
||||
}
|
||||
catch (NotSupportedException)
|
||||
{
|
||||
// HttpNavigationManager does not support that
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private bool RequiresChange((string theme, bool? wcag, bool? rightToLeft) state) =>
|
||||
(state.theme != null && !string.Equals(themeService.Theme, state.theme, StringComparison.OrdinalIgnoreCase)) ||
|
||||
themeService.Wcag != state.wcag || themeService.RightToLeft != state.rightToLeft;
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
private ValueTask OnLocationChanging(LocationChangingContext context)
|
||||
{
|
||||
var state = GetStateFromQueryString(context.TargetLocation);
|
||||
|
||||
if (RequiresChange(state))
|
||||
{
|
||||
context.PreventNavigation();
|
||||
|
||||
navigationManager.NavigateTo(GetUriWithStateQueryParameters(context.TargetLocation), replace: true);
|
||||
}
|
||||
|
||||
return ValueTask.CompletedTask;
|
||||
}
|
||||
#endif
|
||||
|
||||
private (string theme, bool? wcag, bool? rightToLeft) GetStateFromQueryString(string uri)
|
||||
{
|
||||
var queryString = uri.Contains('?') ? uri[(uri.IndexOf('?') + 1)..] : string.Empty;
|
||||
|
||||
var query = HttpUtility.ParseQueryString(queryString.Contains('#') ? queryString[..queryString.IndexOf('#')] : queryString);
|
||||
|
||||
bool? wcag = query.Get(options.WcagParameter) != null ? query.Get(options.WcagParameter) == "true" : null;
|
||||
bool? rtl = query.Get(options.RightToLeftParameter) != null ? query.Get(options.RightToLeftParameter) == "true" : null;
|
||||
|
||||
return (query.Get(options.ThemeParameter), wcag, rtl);
|
||||
}
|
||||
|
||||
private string GetUriWithStateQueryParameters(string uri)
|
||||
{
|
||||
var parameters = new Dictionary<string, object>
|
||||
{
|
||||
{ options.ThemeParameter, themeService.Theme.ToLowerInvariant() },
|
||||
};
|
||||
|
||||
if (themeService.Wcag.HasValue)
|
||||
{
|
||||
parameters.Add(options.WcagParameter, themeService.Wcag.Value ? "true" : "false");
|
||||
}
|
||||
|
||||
if (themeService.RightToLeft.HasValue)
|
||||
{
|
||||
parameters.Add(options.RightToLeftParameter, themeService.RightToLeft.Value ? "true" : "false");
|
||||
}
|
||||
|
||||
return navigationManager.GetUriWithQueryParameters(uri, parameters);
|
||||
}
|
||||
|
||||
private void OnThemeChanged()
|
||||
{
|
||||
|
||||
if (hasAttachedJSRuntimeProperty is null || hasAttachedJSRuntimeProperty.GetValue(navigationManager) is true)
|
||||
{
|
||||
var state = GetStateFromQueryString(navigationManager.Uri);
|
||||
|
||||
navigationManager.NavigateTo(GetUriWithStateQueryParameters(navigationManager.Uri),
|
||||
forceLoad: state.rightToLeft != themeService.RightToLeft);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
themeService.ThemeChanged -= OnThemeChanged;
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
registration?.Dispose();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extension methods to register the <see cref="QueryStringThemeService" />.
|
||||
/// </summary>
|
||||
public static class QueryStringThemeServiceCollectionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds the <see cref="QueryStringThemeService" /> to the service collection.
|
||||
/// </summary>
|
||||
public static IServiceCollection AddRadzenQueryStringThemeService(this IServiceCollection services)
|
||||
{
|
||||
services.AddOptions<QueryStringThemeServiceOptions>();
|
||||
services.AddScoped<QueryStringThemeService>();
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the <see cref="QueryStringThemeService" /> to the service collection with the specified condiguration.
|
||||
/// </summary>
|
||||
public static IServiceCollection AddRadzenQueryStringThemeService(this IServiceCollection services, Action<QueryStringThemeServiceOptions> configure)
|
||||
{
|
||||
services.Configure(configure);
|
||||
services.AddScoped<QueryStringThemeService>();
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -90,60 +90,6 @@ namespace Radzen
|
||||
return (IList)genericToList.Invoke(null, new[] { query });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts to filterstring.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="columns">The columns.</param>
|
||||
/// <returns>System.String.</returns>
|
||||
public static string ToFilterString<T>(this IEnumerable<RadzenGridColumn<T>> columns)
|
||||
{
|
||||
Func<RadzenGridColumn<T>, bool> canFilter = (c) => c.Filterable && !string.IsNullOrEmpty(c.Type) &&
|
||||
!(c.FilterValue == null || c.FilterValue as string == string.Empty) && c.GetFilterProperty() != null;
|
||||
|
||||
var columnsWithFilter = columns.Where(canFilter).ToList();
|
||||
|
||||
if (columnsWithFilter.Any())
|
||||
{
|
||||
var gridLogicalFilterOperator = columns.FirstOrDefault()?.Grid?.LogicalFilterOperator;
|
||||
var gridBooleanOperator = gridLogicalFilterOperator == LogicalFilterOperator.And ? "and" : "or";
|
||||
|
||||
var whereList = new List<string>();
|
||||
foreach (var column in columnsWithFilter)
|
||||
{
|
||||
var value = (string)Convert.ChangeType(column.FilterValue, typeof(string));
|
||||
var secondValue = (string)Convert.ChangeType(column.SecondFilterValue, typeof(string));
|
||||
|
||||
var columnType = column.Type;
|
||||
var columnFormat = column.Format;
|
||||
|
||||
if (!string.IsNullOrEmpty(columnType) && !string.IsNullOrEmpty(value))
|
||||
{
|
||||
var linqOperator = FilterOperators[column.FilterOperator];
|
||||
if (linqOperator == null)
|
||||
{
|
||||
linqOperator = "==";
|
||||
}
|
||||
|
||||
var booleanOperator = column.LogicalFilterOperator == LogicalFilterOperator.And ? "and" : "or";
|
||||
|
||||
if (string.IsNullOrEmpty(secondValue))
|
||||
{
|
||||
whereList.Add(GetColumnFilter(column));
|
||||
}
|
||||
else
|
||||
{
|
||||
whereList.Add($"({GetColumnFilter(column)} {booleanOperator} {GetColumnFilter(column, true)})");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return string.Join($" {gridBooleanOperator} ", whereList.Where(i => !string.IsNullOrEmpty(i)));
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts to filterstring.
|
||||
/// </summary>
|
||||
@@ -180,22 +126,40 @@ namespace Radzen
|
||||
{
|
||||
if (v != null)
|
||||
{
|
||||
value = v is DateTime ? ((DateTime)v).ToString("yyyy-MM-ddTHH:mm:ss.fffZ", CultureInfo.InvariantCulture) : v is DateTimeOffset ? ((DateTimeOffset)v).UtcDateTime.ToString("yyyy-MM-ddTHH:mm:ss.fffZ", CultureInfo.InvariantCulture) : "";
|
||||
|
||||
value =
|
||||
v is DateTime ? ((DateTime) v).ToString("yyyy-MM-ddTHH:mm:ss.fffZ", CultureInfo.InvariantCulture)
|
||||
: v is DateTimeOffset ? ((DateTimeOffset) v).UtcDateTime.ToString("yyyy-MM-ddTHH:mm:ss.fffZ", CultureInfo.InvariantCulture)
|
||||
:
|
||||
#if NET6_0_OR_GREATER
|
||||
v is DateOnly ? ((DateOnly) v).ToString("yyy-MM-dd", CultureInfo.InvariantCulture) : "";
|
||||
#else
|
||||
"";
|
||||
#endif
|
||||
}
|
||||
if (sv != null)
|
||||
{
|
||||
secondValue = sv is DateTime ? ((DateTime)sv).ToString("yyyy-MM-ddTHH:mm:ss.fffZ", CultureInfo.InvariantCulture) : sv is DateTimeOffset ? ((DateTimeOffset)sv).UtcDateTime.ToString("yyyy-MM-ddTHH:mm:ss.fffZ", CultureInfo.InvariantCulture) : "";
|
||||
secondValue =
|
||||
sv is DateTime ? ((DateTime)sv).ToString("yyyy-MM-ddTHH:mm:ss.fffZ", CultureInfo.InvariantCulture)
|
||||
: sv is DateTimeOffset ? ((DateTimeOffset)sv).UtcDateTime.ToString("yyyy-MM-ddTHH:mm:ss.fffZ", CultureInfo.InvariantCulture)
|
||||
:
|
||||
#if NET6_0_OR_GREATER
|
||||
sv is DateOnly ? ((DateOnly) sv).ToString("yyy-MM-dd", CultureInfo.InvariantCulture) : "";
|
||||
#else
|
||||
"";
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if (PropertyAccess.IsEnum(column.FilterPropertyType) || PropertyAccess.IsNullableEnum(column.FilterPropertyType))
|
||||
{
|
||||
Type enumType = Enum.GetUnderlyingType(Nullable.GetUnderlyingType(column.FilterPropertyType) ?? column.FilterPropertyType);
|
||||
if (v != null)
|
||||
{
|
||||
value = ((int)v).ToString();
|
||||
value = Convert.ChangeType(v, enumType).ToString();
|
||||
}
|
||||
if (sv != null)
|
||||
{
|
||||
secondValue = ((int)sv).ToString();
|
||||
secondValue = Convert.ChangeType(sv, enumType).ToString();
|
||||
}
|
||||
}
|
||||
else if (IsEnumerable(column.FilterPropertyType) && column.FilterPropertyType != typeof(string))
|
||||
@@ -293,93 +257,216 @@ namespace Radzen
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the column filter.
|
||||
/// Converts a RadzenDataFilter to a Linq-compatibly filter string
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="column">The column.</param>
|
||||
/// <param name="second">if set to <c>true</c> [second].</param>
|
||||
/// <returns>System.String.</returns>
|
||||
private static string GetColumnFilter<T>(RadzenGridColumn<T> column, bool second = false)
|
||||
/// <typeparam name="T">The type that is being filtered</typeparam>
|
||||
/// <param name="dataFilter">The RadzenDataFilter component</param>
|
||||
/// <returns>A Linq-compatible filter string</returns>
|
||||
public static string ToFilterString<T>(this RadzenDataFilter<T> dataFilter)
|
||||
{
|
||||
var property = PropertyAccess.GetProperty(column.GetFilterProperty());
|
||||
Func<CompositeFilterDescriptor, bool> canFilter = (c) => dataFilter.properties.Where(col => col.Property == c.Property).FirstOrDefault()?.FilterPropertyType != null &&
|
||||
(!(c.FilterValue == null || c.FilterValue as string == string.Empty)
|
||||
|| c.FilterOperator == FilterOperator.IsNotNull || c.FilterOperator == FilterOperator.IsNull
|
||||
|| c.FilterOperator == FilterOperator.IsEmpty || c.FilterOperator == FilterOperator.IsNotEmpty)
|
||||
&& c.Property != null;
|
||||
|
||||
if (property.IndexOf(".") != -1)
|
||||
if (dataFilter.Filters.Concat(dataFilter.Filters.SelectManyRecursive(i => i.Filters ?? Enumerable.Empty<CompositeFilterDescriptor>())).Where(canFilter).Any())
|
||||
{
|
||||
return CompositeFilterToFilterString<T>(dataFilter.Filters, dataFilter, dataFilter.LogicalFilterOperator);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a Linq-compatible filter string for a list of CompositeFilterDescriptions
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type that is being filtered</typeparam>
|
||||
/// <param name="filters">The list if filters</param>
|
||||
/// <param name="Datafilter">The RadzenDataFilter component</param>
|
||||
/// <param name="filterOperator">Whether filter elements should be and-ed or or-ed</param>
|
||||
/// <returns></returns>
|
||||
private static string CompositeFilterToFilterString<T>(IEnumerable<CompositeFilterDescriptor> filters, RadzenDataFilter<T> Datafilter, LogicalFilterOperator filterOperator)
|
||||
{
|
||||
if (filters.Any())
|
||||
{
|
||||
var LogicalFilterOperator = filterOperator;
|
||||
var BooleanOperator = LogicalFilterOperator == LogicalFilterOperator.And ? "&&" : "||";
|
||||
|
||||
var whereList = new List<string>();
|
||||
foreach (var column in filters)
|
||||
{
|
||||
if (column.Filters is not null && column.Filters.Any())
|
||||
{
|
||||
whereList.Add($"({CompositeFilterToFilterString(column.Filters, Datafilter, column.LogicalFilterOperator)})");
|
||||
}
|
||||
if (column.Property is not null)
|
||||
{
|
||||
whereList.Add($"{GetColumnFilter(Datafilter, column, Datafilter.FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive)}");
|
||||
}
|
||||
}
|
||||
|
||||
return string.Join($" {BooleanOperator} ", whereList.Where(i => !string.IsNullOrEmpty(i)));
|
||||
}
|
||||
|
||||
return "";
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a single linq-compatible filter string for one datafilter element (includes sub-lists)
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type that is being filtered</typeparam>
|
||||
/// <param name="dataFilter">The RadzenDataFilter component</param>
|
||||
/// <param name="column">The filter elements for which to create the filter string</param>
|
||||
/// <param name="caseSensitive">Whether filtering is case sensitive or not</param>
|
||||
/// <returns></returns>
|
||||
private static string GetColumnFilter<T>(RadzenDataFilter<T> dataFilter, CompositeFilterDescriptor column, bool caseSensitive)
|
||||
{
|
||||
var property = column.Property;
|
||||
|
||||
if (property.Contains(".", StringComparison.CurrentCulture))
|
||||
{
|
||||
property = $"({property})";
|
||||
}
|
||||
|
||||
if (column.Type == "string" && string.IsNullOrEmpty(column.Format))
|
||||
var columnInfo = dataFilter.properties.Where(c => c.Property == column.Property).FirstOrDefault();
|
||||
if (columnInfo == null) return "";
|
||||
|
||||
var columnType = columnInfo.FilterPropertyType;
|
||||
|
||||
var columnFilterOperator = column.FilterOperator;
|
||||
|
||||
var linqOperator = LinqFilterOperators[columnFilterOperator.Value];
|
||||
linqOperator ??= "==";
|
||||
|
||||
var value = "";
|
||||
|
||||
if (columnType == typeof(string))
|
||||
{
|
||||
property = $@"({property} == null ? """" : {property})";
|
||||
}
|
||||
value = (string)Convert.ChangeType(column.FilterValue, typeof(string));
|
||||
value = value?.Replace("\"", "\\\"");
|
||||
|
||||
var columnFilterOperator = !second ? column.FilterOperator : column.SecondFilterOperator;
|
||||
string filterCaseSensitivityOperator = caseSensitive ? ".ToLower()" : "";
|
||||
|
||||
var linqOperator = FilterOperators[columnFilterOperator];
|
||||
if (linqOperator == null)
|
||||
{
|
||||
linqOperator = "==";
|
||||
}
|
||||
|
||||
var value = !second ? (string)Convert.ChangeType(column.FilterValue, typeof(string)) :
|
||||
(string)Convert.ChangeType(column.SecondFilterValue, typeof(string));
|
||||
value = value?.Replace("\"", "\\\"");
|
||||
|
||||
var columnType = column.Type;
|
||||
var columnFormat = column.Format;
|
||||
|
||||
if (columnType == "string")
|
||||
{
|
||||
string filterCaseSensitivityOperator = column.Grid.FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ? ".ToLower()" : "";
|
||||
|
||||
if (columnFormat == "date-time" || columnFormat == "date")
|
||||
{
|
||||
var dateTimeValue = DateTime.Parse(value, CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.RoundtripKind);
|
||||
var finalDate = dateTimeValue.TimeOfDay == TimeSpan.Zero ? dateTimeValue.Date : dateTimeValue;
|
||||
var dateFormat = dateTimeValue.TimeOfDay == TimeSpan.Zero ? "yyyy-MM-dd" : "yyyy-MM-ddTHH:mm:ss.fffZ";
|
||||
|
||||
return $@"{property} {linqOperator} DateTime(""{finalDate.ToString(dateFormat, CultureInfo.InvariantCulture)}"")";
|
||||
}
|
||||
else if (columnFormat == "time")
|
||||
{
|
||||
return $"{property} {linqOperator} duration'{value}'";
|
||||
}
|
||||
else if (columnFormat == "uuid")
|
||||
{
|
||||
return $@"{property} {linqOperator} Guid(""{value}"")";
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == "contains")
|
||||
if (!string.IsNullOrEmpty(value) && column.FilterOperator == FilterOperator.Contains)
|
||||
{
|
||||
return $@"({property} == null ? """" : {property}){filterCaseSensitivityOperator}.Contains(""{value}""{filterCaseSensitivityOperator})";
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == "DoesNotContain")
|
||||
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == FilterOperator.DoesNotContain)
|
||||
{
|
||||
return $@"({property} == null ? """" : !{property}){filterCaseSensitivityOperator}.Contains(""{value}""{filterCaseSensitivityOperator})";
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == "startswith")
|
||||
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == FilterOperator.StartsWith)
|
||||
{
|
||||
return $@"({property} == null ? """" : {property}){filterCaseSensitivityOperator}.StartsWith(""{value}""{filterCaseSensitivityOperator})";
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == "endswith")
|
||||
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == FilterOperator.EndsWith)
|
||||
{
|
||||
return $@"({property} == null ? """" : {property}){filterCaseSensitivityOperator}.EndsWith(""{value}""{filterCaseSensitivityOperator})";
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == "eq")
|
||||
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == FilterOperator.Equals)
|
||||
{
|
||||
return $@"({property} == null ? """" : {property}){filterCaseSensitivityOperator} == ""{value}""{filterCaseSensitivityOperator}";
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == "ne")
|
||||
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == FilterOperator.NotEquals)
|
||||
{
|
||||
return $@"({property} == null ? """" : {property}){filterCaseSensitivityOperator} != ""{value}""{filterCaseSensitivityOperator}";
|
||||
}
|
||||
else if (columnFilterOperator == FilterOperator.IsNull)
|
||||
{
|
||||
return property + " == null";
|
||||
}
|
||||
else if (columnFilterOperator == FilterOperator.IsEmpty)
|
||||
{
|
||||
return property + @" == """"";
|
||||
}
|
||||
else if (columnFilterOperator == FilterOperator.IsNotEmpty)
|
||||
{
|
||||
return property + @" != """"";
|
||||
}
|
||||
else if (columnFilterOperator == FilterOperator.IsNotNull)
|
||||
{
|
||||
return property + @" != null";
|
||||
}
|
||||
}
|
||||
else if (columnType == "number" || columnType == "integer")
|
||||
else if (PropertyAccess.IsNumeric(columnType))
|
||||
{
|
||||
return $"{property} {linqOperator} {value}";
|
||||
value = (string)Convert.ChangeType(column.FilterValue, typeof(string));
|
||||
|
||||
if (columnFilterOperator == FilterOperator.IsNull || columnFilterOperator == FilterOperator.IsNotNull)
|
||||
{
|
||||
return $"{property} {linqOperator} null";
|
||||
}
|
||||
else if (columnFilterOperator == FilterOperator.IsEmpty || columnFilterOperator == FilterOperator.IsNotEmpty)
|
||||
{
|
||||
return $@"{property} {linqOperator} """"";
|
||||
}
|
||||
else
|
||||
{
|
||||
return $"{property} {linqOperator} {value}";
|
||||
}
|
||||
}
|
||||
else if (columnType == "boolean")
|
||||
else if (columnType == typeof(bool) || columnType == typeof(bool?))
|
||||
{
|
||||
return $"{property} == {value}";
|
||||
value = (string)Convert.ChangeType(column.FilterValue, typeof(string));
|
||||
|
||||
return $"{property} {linqOperator} {(columnFilterOperator == FilterOperator.IsNull || columnFilterOperator == FilterOperator.IsNotNull ? "null" : value)}";
|
||||
}
|
||||
else if (PropertyAccess.IsDate(columnType))
|
||||
{
|
||||
var v = column.FilterValue;
|
||||
if (v != null)
|
||||
{
|
||||
value = $@"DateTime(""{(v is DateTime time ? time.ToString("yyyy-MM-ddTHH:mm:ss.fffZ", CultureInfo.InvariantCulture) : v is DateTimeOffset offset ? offset.UtcDateTime.ToString("yyyy-MM-ddTHH:mm:ss.fffZ", CultureInfo.InvariantCulture) : "")}"")";
|
||||
}
|
||||
}
|
||||
else if (PropertyAccess.IsEnum(columnType) || PropertyAccess.IsNullableEnum(columnType))
|
||||
{
|
||||
var v = column.FilterValue;
|
||||
if (v != null)
|
||||
{
|
||||
value = ((int)v).ToString();
|
||||
}
|
||||
}
|
||||
else if (IsEnumerable(columnType) && columnType != typeof(string))
|
||||
{
|
||||
var v = column.FilterValue;
|
||||
var enumerableValue = ((IEnumerable)(v ?? Enumerable.Empty<object>())).AsQueryable();
|
||||
|
||||
string baseType = columnType.GetGenericArguments().Count() == 1 ? columnType.GetGenericArguments()[0].Name : "";
|
||||
|
||||
var enumerableValueAsString = "new " + baseType + "[]{" + String.Join(",",
|
||||
(enumerableValue.ElementType == typeof(string) ? enumerableValue.Cast<string>().Select(i => $@"""{i}""").Cast<object>() : enumerableValue.Cast<object>())) + "}";
|
||||
|
||||
|
||||
if (enumerableValue?.Any() == true)
|
||||
{
|
||||
if (property.Contains("."))
|
||||
{
|
||||
property = $"({property})";
|
||||
}
|
||||
|
||||
if (columnFilterOperator == FilterOperator.Contains || columnFilterOperator == FilterOperator.DoesNotContain)
|
||||
{
|
||||
return $@"{(columnFilterOperator == FilterOperator.DoesNotContain ? "!" : "")}({enumerableValueAsString}).Contains({property})";
|
||||
}
|
||||
else if (columnFilterOperator == FilterOperator.In || columnFilterOperator == FilterOperator.NotIn)
|
||||
{
|
||||
return $@"({property}).{(columnFilterOperator == FilterOperator.NotIn ? "Except" : "Intersect")}({enumerableValueAsString}).Any()";
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
value = (string)Convert.ChangeType(column.FilterValue, typeof(string), CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(value) || column.FilterOperator == FilterOperator.IsNotNull
|
||||
|| column.FilterOperator == FilterOperator.IsNull
|
||||
|| column.FilterOperator == FilterOperator.IsEmpty
|
||||
|| column.FilterOperator == FilterOperator.IsNotEmpty)
|
||||
{
|
||||
return $"({property} {linqOperator} {(columnFilterOperator == FilterOperator.IsNull || columnFilterOperator == FilterOperator.IsNotNull ? "null" : value)})";
|
||||
}
|
||||
|
||||
return "";
|
||||
@@ -396,13 +483,14 @@ namespace Radzen
|
||||
private static string GetColumnFilter<T>(RadzenDataGridColumn<T> column, string value, bool second = false)
|
||||
{
|
||||
var property = PropertyAccess.GetProperty(column.GetFilterProperty());
|
||||
var propertyType = !string.IsNullOrEmpty(property) ? PropertyAccess.GetPropertyType(typeof(T), property) : null;
|
||||
|
||||
if (property.IndexOf(".") != -1)
|
||||
{
|
||||
property = $"({property})";
|
||||
}
|
||||
bool hasNp = property.Contains("np(");
|
||||
string npProperty = hasNp ? property : $@"np({property})";
|
||||
string npProperty = hasNp ? property : (propertyType != null ? Nullable.GetUnderlyingType(propertyType) != null : true) ? $@"np({property})" : property;
|
||||
|
||||
var columnFilterOperator = !second ? column.GetFilterOperator() : column.GetSecondFilterOperator();
|
||||
|
||||
@@ -416,12 +504,20 @@ namespace Radzen
|
||||
{
|
||||
linqOperator = "==";
|
||||
}
|
||||
bool isDateOnly = false;
|
||||
|
||||
#if NET6_0_OR_GREATER
|
||||
if (column.FilterPropertyType == typeof(DateOnly) || column.FilterPropertyType == typeof(DateOnly?))
|
||||
{
|
||||
isDateOnly = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (column.FilterPropertyType == typeof(string))
|
||||
{
|
||||
string filterCaseSensitivityOperator = column.Grid.FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ? ".ToLower()" : "";
|
||||
value = value?.Replace("\"", "\\\"");
|
||||
|
||||
|
||||
if (!string.IsNullOrEmpty(value) && columnFilterOperator == FilterOperator.Contains)
|
||||
{
|
||||
return $@"({property} == null ? """" : {property}){filterCaseSensitivityOperator}.Contains(""{value}""{filterCaseSensitivityOperator})";
|
||||
@@ -481,7 +577,7 @@ namespace Radzen
|
||||
else if (column.FilterPropertyType == typeof(DateTime) ||
|
||||
column.FilterPropertyType == typeof(DateTime?) ||
|
||||
column.FilterPropertyType == typeof(DateTimeOffset) ||
|
||||
column.FilterPropertyType == typeof(DateTimeOffset?))
|
||||
column.FilterPropertyType == typeof(DateTimeOffset?) || isDateOnly)
|
||||
{
|
||||
if (columnFilterOperator == FilterOperator.IsNull || columnFilterOperator == FilterOperator.IsNotNull)
|
||||
{
|
||||
@@ -496,14 +592,25 @@ namespace Radzen
|
||||
var dateTimeValue = DateTime.Parse(value, CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.RoundtripKind);
|
||||
var finalDate = dateTimeValue.TimeOfDay == TimeSpan.Zero ? dateTimeValue.Date : dateTimeValue;
|
||||
var dateFormat = dateTimeValue.TimeOfDay == TimeSpan.Zero ? "yyyy-MM-dd" : "yyyy-MM-ddTHH:mm:ss.fffZ";
|
||||
var dateFunction = column.FilterPropertyType == typeof(DateTimeOffset) || column.FilterPropertyType == typeof(DateTimeOffset?) ? "DateTimeOffset" : "DateTime";
|
||||
|
||||
string dateFunction = "DateTime"; //fallback to datetime, if it's an offset or dateonly use that
|
||||
if (column.FilterPropertyType == typeof(DateTimeOffset) || column.FilterPropertyType == typeof(DateTimeOffset?))
|
||||
dateFunction = "DateTimeOffset";
|
||||
else
|
||||
{
|
||||
#if NET6_0_OR_GREATER
|
||||
if (column.FilterPropertyType == typeof(DateOnly) || column.FilterPropertyType == typeof(DateOnly?))
|
||||
dateFunction = "DateOnly";
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
return $@"{property} {linqOperator} {dateFunction}(""{finalDate.ToString(dateFormat, CultureInfo.InvariantCulture)}"")";
|
||||
}
|
||||
}
|
||||
else if (column.FilterPropertyType == typeof(bool) || column.FilterPropertyType == typeof(bool?))
|
||||
{
|
||||
return $"{property} == {value}";
|
||||
return $"{property} {linqOperator} {(columnFilterOperator == FilterOperator.IsNull || columnFilterOperator == FilterOperator.IsNotNull ? "null" : value)}";
|
||||
}
|
||||
else if (column.FilterPropertyType == typeof(Guid) || column.FilterPropertyType == typeof(Guid?))
|
||||
{
|
||||
@@ -524,93 +631,6 @@ namespace Radzen
|
||||
return "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the column o data filter.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="column">The column.</param>
|
||||
/// <param name="second">if set to <c>true</c> [second].</param>
|
||||
/// <returns>System.String.</returns>
|
||||
private static string GetColumnODataFilter<T>(RadzenGridColumn<T> column, bool second = false)
|
||||
{
|
||||
var columnType = column.Type;
|
||||
var columnFormat = column.Format;
|
||||
|
||||
var property = column.GetFilterProperty().Replace('.', '/');
|
||||
|
||||
var columnFilterOperator = !second ? column.FilterOperator : column.SecondFilterOperator;
|
||||
|
||||
var value = !second ? (string)Convert.ChangeType(column.FilterValue, typeof(string)) :
|
||||
(string)Convert.ChangeType(column.SecondFilterValue, typeof(string));
|
||||
|
||||
if (column.Grid.FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive && columnType == "string" && string.IsNullOrEmpty(columnFormat))
|
||||
{
|
||||
property = $"tolower({property})";
|
||||
}
|
||||
|
||||
if (columnType == "string")
|
||||
{
|
||||
if (columnFormat == "date-time" || columnFormat == "date")
|
||||
{
|
||||
return $"{property} {columnFilterOperator} {DateTime.Parse(value, CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.RoundtripKind).ToString("yyyy-MM-ddTHH:mm:ss.fffZ", CultureInfo.InvariantCulture)}";
|
||||
}
|
||||
else if (columnFormat == "time")
|
||||
{
|
||||
return $"{property} {columnFilterOperator} duration'{value}'";
|
||||
}
|
||||
else if (columnFormat == "uuid")
|
||||
{
|
||||
return $"{property} {columnFilterOperator} {value}";
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == "contains")
|
||||
{
|
||||
return column.Grid.FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ?
|
||||
$"contains({property}, tolower('{value}'))" :
|
||||
$"contains({property}, '{value}')";
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == "DoesNotContain")
|
||||
{
|
||||
return column.Grid.FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ?
|
||||
$"not(contains({property}, tolower('{value}')))" :
|
||||
$"not(contains({property}, '{value}'))";
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == "startswith")
|
||||
{
|
||||
return column.Grid.FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ?
|
||||
$"startswith({property}, tolower('{value}'))" :
|
||||
$"startswith({property}, '{value}')";
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == "endswith")
|
||||
{
|
||||
return column.Grid.FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ?
|
||||
$"endswith({property}, tolower('{value}'))" :
|
||||
$"endswith({property}, '{value}')";
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == "eq")
|
||||
{
|
||||
return column.Grid.FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ?
|
||||
$"{property} eq tolower('{value}')" :
|
||||
$"{property} eq '{value}'";
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == "ne")
|
||||
{
|
||||
return column.Grid.FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ?
|
||||
$"{property} ne tolower('{value}')" :
|
||||
$"{property} ne '{value}'";
|
||||
}
|
||||
}
|
||||
else if (columnType == "number" || columnType == "integer")
|
||||
{
|
||||
return $"{property} {columnFilterOperator} {value}";
|
||||
}
|
||||
else if (columnType == "boolean")
|
||||
{
|
||||
return $"{property} eq {value.ToLower()}";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the column o data filter.
|
||||
/// </summary>
|
||||
@@ -627,7 +647,8 @@ namespace Radzen
|
||||
|
||||
var value = IsEnumerable(column.FilterPropertyType) && column.FilterPropertyType != typeof(string)
|
||||
? null
|
||||
: (string)Convert.ChangeType(filterValue, typeof(string), CultureInfo.InvariantCulture);
|
||||
: (string)Convert.ChangeType(filterValue is DateTimeOffset ?
|
||||
((DateTimeOffset)filterValue).UtcDateTime : filterValue, typeof(string), CultureInfo.InvariantCulture);
|
||||
|
||||
if (column.Grid.FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive && column.FilterPropertyType == typeof(string))
|
||||
{
|
||||
@@ -715,7 +736,14 @@ namespace Radzen
|
||||
}
|
||||
else if (PropertyAccess.IsNumeric(column.FilterPropertyType))
|
||||
{
|
||||
return $"{property} {odataFilterOperator} {value}";
|
||||
if (columnFilterOperator == FilterOperator.IsNull || columnFilterOperator == FilterOperator.IsNotNull)
|
||||
{
|
||||
return $"{property} {odataFilterOperator} null";
|
||||
}
|
||||
else
|
||||
{
|
||||
return $"{property} {odataFilterOperator} {value}";
|
||||
}
|
||||
}
|
||||
else if (column.FilterPropertyType == typeof(bool) || column.FilterPropertyType == typeof(bool?))
|
||||
{
|
||||
@@ -758,62 +786,6 @@ namespace Radzen
|
||||
return "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts to odatafilterstring.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="columns">The columns.</param>
|
||||
/// <returns>System.String.</returns>
|
||||
public static string ToODataFilterString<T>(this IEnumerable<RadzenGridColumn<T>> columns)
|
||||
{
|
||||
Func<RadzenGridColumn<T>, bool> canFilter = (c) => c.Filterable && !string.IsNullOrEmpty(c.Type) &&
|
||||
!(c.FilterValue == null || c.FilterValue as string == string.Empty) && c.GetFilterProperty() != null;
|
||||
|
||||
var columnsWithFilter = columns.Where(canFilter).ToList();
|
||||
|
||||
if (columnsWithFilter.Any())
|
||||
{
|
||||
var gridLogicalFilterOperator = columns.FirstOrDefault()?.Grid?.LogicalFilterOperator;
|
||||
var gridBooleanOperator = gridLogicalFilterOperator == LogicalFilterOperator.And ? "and" : "or";
|
||||
|
||||
var whereList = new List<string>();
|
||||
foreach (var column in columnsWithFilter)
|
||||
{
|
||||
var property = column.GetFilterProperty().Replace('.', '/');
|
||||
|
||||
var value = (string)Convert.ChangeType(column.FilterValue, typeof(string));
|
||||
var secondValue = (string)Convert.ChangeType(column.SecondFilterValue, typeof(string));
|
||||
|
||||
var columnType = column.Type;
|
||||
var columnFormat = column.Format;
|
||||
|
||||
if (!string.IsNullOrEmpty(columnType) && !string.IsNullOrEmpty(value))
|
||||
{
|
||||
var linqOperator = FilterOperators[column.FilterOperator];
|
||||
if (linqOperator == null)
|
||||
{
|
||||
linqOperator = "==";
|
||||
}
|
||||
|
||||
var booleanOperator = column.LogicalFilterOperator == LogicalFilterOperator.And ? "and" : "or";
|
||||
|
||||
if (string.IsNullOrEmpty(secondValue))
|
||||
{
|
||||
whereList.Add(GetColumnODataFilter(column));
|
||||
}
|
||||
else
|
||||
{
|
||||
whereList.Add($"({GetColumnODataFilter(column)} {booleanOperator} {GetColumnODataFilter(column, true)})");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return string.Join($" {gridBooleanOperator} ", whereList.Where(i => !string.IsNullOrEmpty(i)));
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts to odatafilterstring.
|
||||
/// </summary>
|
||||
@@ -873,89 +845,6 @@ namespace Radzen
|
||||
return "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wheres the specified columns.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="columns">The columns.</param>
|
||||
/// <returns>IQueryable<T>.</returns>
|
||||
public static IQueryable<T> Where<T>(this IQueryable<T> source, IEnumerable<RadzenGridColumn<T>> columns)
|
||||
{
|
||||
Func<RadzenGridColumn<T>, bool> canFilter = (c) => c.Filterable && !string.IsNullOrEmpty(c.Type) &&
|
||||
!(c.FilterValue == null || c.FilterValue as string == string.Empty) && c.GetFilterProperty() != null;
|
||||
|
||||
if (columns.Where(canFilter).Any())
|
||||
{
|
||||
var gridLogicalFilterOperator = columns.FirstOrDefault()?.Grid?.LogicalFilterOperator;
|
||||
var gridBooleanOperator = gridLogicalFilterOperator == LogicalFilterOperator.And ? "and" : "or";
|
||||
|
||||
var index = 0;
|
||||
var whereList = new Dictionary<string, IEnumerable<object>>();
|
||||
foreach (var column in columns.Where(canFilter))
|
||||
{
|
||||
var property = PropertyAccess.GetProperty(column.GetFilterProperty());
|
||||
|
||||
if (property.IndexOf(".") != -1)
|
||||
{
|
||||
property = $"({property})";
|
||||
}
|
||||
|
||||
if (column.Type == "string" && string.IsNullOrEmpty(column.Format))
|
||||
{
|
||||
property = $@"({property} == null ? """" : {property})";
|
||||
}
|
||||
|
||||
string filterCaseSensitivityOperator = column.Type == "string" && string.IsNullOrEmpty(column.Format) &&
|
||||
column.Grid.FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ? ".ToLower()" : "";
|
||||
|
||||
var comparison = FilterOperators[column.FilterOperator];
|
||||
|
||||
var booleanOperator = column.LogicalFilterOperator == LogicalFilterOperator.And ? "and" : "or";
|
||||
|
||||
if (column.SecondFilterValue == null)
|
||||
{
|
||||
if (comparison == "StartsWith" || comparison == "EndsWith" || comparison == "Contains")
|
||||
{
|
||||
whereList.Add($@"{property}{filterCaseSensitivityOperator}.{comparison}(@{index}{filterCaseSensitivityOperator})", new object[] { column.FilterValue });
|
||||
index++;
|
||||
}
|
||||
else if (comparison == "DoesNotContain")
|
||||
{
|
||||
whereList.Add($@"!{property}{filterCaseSensitivityOperator}.Contains(@{index}{filterCaseSensitivityOperator})", new object[] { column.FilterValue });
|
||||
index++;
|
||||
}
|
||||
else
|
||||
{
|
||||
whereList.Add($@"{property}{filterCaseSensitivityOperator} {comparison} @{index}{filterCaseSensitivityOperator}", new object[] { column.FilterValue });
|
||||
index++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var firstFilter = comparison == "StartsWith" || comparison == "EndsWith" || comparison == "Contains" ?
|
||||
$@"{property}{filterCaseSensitivityOperator}.{comparison}(@{index}{filterCaseSensitivityOperator})" :
|
||||
comparison == "DoesNotContain" ? $@"!{property}{filterCaseSensitivityOperator}.Contains(@{index}{filterCaseSensitivityOperator})" :
|
||||
$@"{property}{filterCaseSensitivityOperator} {comparison} @{index}{filterCaseSensitivityOperator}";
|
||||
index++;
|
||||
|
||||
var secondComparison = FilterOperators[column.SecondFilterOperator];
|
||||
var secondFilter = secondComparison == "StartsWith" || secondComparison == "EndsWith" || secondComparison == "Contains" ?
|
||||
$@"{property}{filterCaseSensitivityOperator}.{secondComparison}(@{index}{filterCaseSensitivityOperator})" :
|
||||
secondComparison == "DoesNotContain" ? $@"!{property}{filterCaseSensitivityOperator}.Contains(@{index}{filterCaseSensitivityOperator})" :
|
||||
$@"{property}{filterCaseSensitivityOperator} {secondComparison} @{index}{filterCaseSensitivityOperator}";
|
||||
index++;
|
||||
|
||||
whereList.Add($@"({firstFilter} {booleanOperator} {secondFilter})", new object[] { column.FilterValue, column.SecondFilterValue });
|
||||
}
|
||||
}
|
||||
|
||||
return source.Where(string.Join($" {gridBooleanOperator} ", whereList.Keys), whereList.Values.SelectMany(i => i.ToArray()).ToArray());
|
||||
}
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets if type is IEnumerable.
|
||||
/// </summary>
|
||||
@@ -1029,11 +918,25 @@ namespace Radzen
|
||||
{
|
||||
if (IsEnumerable(column.FilterPropertyType) && column.FilterPropertyType != typeof(string) && comparison == "Contains")
|
||||
{
|
||||
whereList.Add($@"(@{index}).Contains({property})", new object[] { column.GetFilterValue() });
|
||||
if (column.Property != column.FilterProperty && !string.IsNullOrEmpty(column.FilterProperty))
|
||||
{
|
||||
whereList.Add($@"{column.Property}.Any(i => i.{column.FilterProperty}{filterCaseSensitivityOperator}.Contains(@{index}{filterCaseSensitivityOperator}))", new object[] { column.GetFilterValue() });
|
||||
}
|
||||
else
|
||||
{
|
||||
whereList.Add($@"(@{index}).Contains({property})", new object[] { column.GetFilterValue() });
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
whereList.Add($@"{property}{filterCaseSensitivityOperator}.{comparison}(@{index}{filterCaseSensitivityOperator})", new object[] { column.GetFilterValue() });
|
||||
if (IsEnumerable(column.FilterPropertyType) && column.FilterPropertyType != typeof(string) && column.Property != column.FilterProperty && !string.IsNullOrEmpty(column.FilterProperty))
|
||||
{
|
||||
whereList.Add($@"{column.Property}.Any(i => i.{column.FilterProperty}{filterCaseSensitivityOperator}.{comparison}(@{index}{filterCaseSensitivityOperator}))", new object[] { column.GetFilterValue() });
|
||||
}
|
||||
else
|
||||
{
|
||||
whereList.Add($@"{property}{filterCaseSensitivityOperator}.{comparison}(@{index}{filterCaseSensitivityOperator})", new object[] { column.GetFilterValue() });
|
||||
}
|
||||
}
|
||||
|
||||
index++;
|
||||
@@ -1042,7 +945,14 @@ namespace Radzen
|
||||
{
|
||||
if (IsEnumerable(column.FilterPropertyType) && column.FilterPropertyType != typeof(string) && comparison == "DoesNotContain")
|
||||
{
|
||||
whereList.Add($@"!(@{index}).Contains({property})", new object[] { column.GetFilterValue() });
|
||||
if (column.Property != column.FilterProperty && !string.IsNullOrEmpty(column.FilterProperty))
|
||||
{
|
||||
whereList.Add($@"!{column.Property}.Any(i => i.{column.FilterProperty}{filterCaseSensitivityOperator}.Contains(@{index}{filterCaseSensitivityOperator}))", new object[] { column.GetFilterValue() });
|
||||
}
|
||||
else
|
||||
{
|
||||
whereList.Add($@"!(@{index}).Contains({property})", new object[] { column.GetFilterValue() });
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1053,19 +963,23 @@ namespace Radzen
|
||||
}
|
||||
else if (comparison == "In" || comparison == "NotIn")
|
||||
{
|
||||
if (IsEnumerable(column.FilterPropertyType) && column.FilterPropertyType != typeof(string) &&
|
||||
if (IsEnumerable(column.FilterPropertyType) && column.FilterPropertyType != typeof(string) &&
|
||||
IsEnumerable(column.PropertyType) && column.PropertyType != typeof(string))
|
||||
{
|
||||
whereList.Add($@"{(comparison == "NotIn" ? "!" : "")}{property}.Any(i => i in @{index})", new object[] { column.GetFilterValue() });
|
||||
index++;
|
||||
}
|
||||
else if (IsEnumerable(column.FilterPropertyType) && column.FilterPropertyType != typeof(string) &&
|
||||
else if (IsEnumerable(column.FilterPropertyType) && column.FilterPropertyType != typeof(string) &&
|
||||
column.Property != column.FilterProperty && !string.IsNullOrEmpty(column.FilterProperty))
|
||||
{
|
||||
whereList.Add($@"{(comparison == "NotIn" ? "!" : "")}{column.Property}.Any(i => i.{column.FilterProperty} in @{index})", new object[] { column.GetFilterValue() });
|
||||
index++;
|
||||
}
|
||||
}
|
||||
else if (IsEnumerable(column.FilterPropertyType) && column.FilterPropertyType != typeof(string) && column.Property != column.FilterProperty && !string.IsNullOrEmpty(column.FilterProperty))
|
||||
{
|
||||
whereList.Add($@"{column.Property}.Any(i => i.{column.FilterProperty}{filterCaseSensitivityOperator} {comparison} @{index}{filterCaseSensitivityOperator})", new object[] { column.GetFilterValue() });
|
||||
}
|
||||
else if (!(IsEnumerable(column.FilterPropertyType) && column.FilterPropertyType != typeof(string)))
|
||||
{
|
||||
whereList.Add($@"{property}{filterCaseSensitivityOperator} {comparison} @{index}{filterCaseSensitivityOperator}", new object[] { column.GetFilterValue() });
|
||||
@@ -1109,7 +1023,7 @@ namespace Radzen
|
||||
}
|
||||
|
||||
return whereList.Keys.Any() ?
|
||||
source.Where(string.Join($" {gridBooleanOperator} ", whereList.Keys), whereList.Values.SelectMany(i => i.ToArray()).ToArray())
|
||||
source.Where(DynamicLinqCustomTypeProvider.ParsingConfig, string.Join($" {gridBooleanOperator} ", whereList.Keys), whereList.Values.SelectMany(i => i.ToArray()).ToArray())
|
||||
: source;
|
||||
}
|
||||
|
||||
@@ -1143,7 +1057,7 @@ namespace Radzen
|
||||
}
|
||||
|
||||
return filterExpressions.Any() ?
|
||||
source.Where(string.Join($" {dataFilter.LogicalFilterOperator.ToString().ToLower()} ", filterExpressions), filterValues.SelectMany(i => i.ToArray()).ToArray())
|
||||
source.Where(DynamicLinqCustomTypeProvider.ParsingConfig, string.Join($" {dataFilter.LogicalFilterOperator.ToString().ToLower()} ", filterExpressions), filterValues.SelectMany(i => i.ToArray()).ToArray())
|
||||
: source;
|
||||
}
|
||||
|
||||
@@ -1169,7 +1083,8 @@ namespace Radzen
|
||||
else
|
||||
{
|
||||
if (filter.Property == null || filter.FilterOperator == null || (filter.FilterValue == null &&
|
||||
filter.FilterOperator != FilterOperator.IsNull && filter.FilterOperator != FilterOperator.IsNotNull))
|
||||
filter.FilterOperator != FilterOperator.IsNull && filter.FilterOperator != FilterOperator.IsNotNull &&
|
||||
filter.FilterOperator != FilterOperator.IsEmpty && filter.FilterOperator != FilterOperator.IsNotEmpty))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -1265,6 +1180,80 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wheres the specified filters.
|
||||
/// </summary>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="property">The property.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <param name="op">The StringFilterOperator.</param>
|
||||
/// <param name="cs">The FilterCaseSensitivity.</param>
|
||||
/// <returns>IQueryable<T>.</returns>
|
||||
public static IQueryable Where(this IQueryable source, string property, string value, StringFilterOperator op, FilterCaseSensitivity cs)
|
||||
{
|
||||
IQueryable result;
|
||||
|
||||
if (!string.IsNullOrEmpty(value))
|
||||
{
|
||||
var ignoreCase = cs == FilterCaseSensitivity.CaseInsensitive;
|
||||
|
||||
var query = new List<string>();
|
||||
|
||||
if (!string.IsNullOrEmpty(property))
|
||||
{
|
||||
query.Add(property);
|
||||
}
|
||||
|
||||
if (typeof(EnumerableQuery).IsAssignableFrom(source.GetType()))
|
||||
{
|
||||
query.Add("ToString()");
|
||||
}
|
||||
|
||||
if (ignoreCase)
|
||||
{
|
||||
query.Add("ToLower()");
|
||||
}
|
||||
|
||||
query.Add($"{Enum.GetName(typeof(StringFilterOperator), op)}(@0)");
|
||||
|
||||
var search = ignoreCase ? value.ToLower() : value;
|
||||
|
||||
if (source.ElementType == typeof(Enum))
|
||||
{
|
||||
result = source.Cast<Enum>()
|
||||
.Where((Func<Enum, bool>)(i =>
|
||||
{
|
||||
var v = ignoreCase ? i.GetDisplayDescription().ToLower() : i.GetDisplayDescription();
|
||||
|
||||
if (op == StringFilterOperator.Contains)
|
||||
{
|
||||
return v.Contains(search);
|
||||
}
|
||||
else if (op == StringFilterOperator.StartsWith)
|
||||
{
|
||||
return v.StartsWith(search);
|
||||
}
|
||||
else if (op == StringFilterOperator.EndsWith)
|
||||
{
|
||||
return v.EndsWith(search);
|
||||
}
|
||||
|
||||
return v == search;
|
||||
})).AsQueryable();
|
||||
}
|
||||
else
|
||||
{
|
||||
result = source.Where(DynamicLinqCustomTypeProvider.ParsingConfig, string.Join(".", query), search);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = source;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Converts to OData filter expression.
|
||||
@@ -1440,7 +1429,7 @@ namespace Radzen
|
||||
.Where(c => c.Filterable
|
||||
&& c.FilterPropertyType != null
|
||||
&& (!(c.GetFilterValue() == null || c.GetFilterValue() as string == string.Empty)
|
||||
|| c.CanSetFilterValue()
|
||||
|| !c.CanSetFilterValue()
|
||||
|| c.HasCustomFilter())
|
||||
&& c.GetFilterProperty() != null)
|
||||
.ToList();
|
||||
|
||||
@@ -1,105 +0,0 @@
|
||||
## Radzen Blazor is a set of 70+ free native Blazor UI controls packed with DataGrid, Scheduler, Charts and robust theming including Material design and Fluent UI.
|
||||
|
||||

|
||||
|
||||
## Why choose Radzen Blazor Components?
|
||||
|
||||
### :sparkles: Free
|
||||
|
||||
Radzen Blazor Components are open source and free for commercial use. You can install them from [nuget](https://www.nuget.org/packages/Radzen.Blazor) or build your own copy from source.
|
||||
|
||||
Paid support is available as part of the [Radzen Professional subscription](https://www.radzen.com/blazor-studio/pricing/).
|
||||
|
||||
### :computer: Native
|
||||
|
||||
The components are implemented in C# and take full advantage of the Blazor framework. They do not depend on or wrap existing JavaScript frameworks or libraries.
|
||||
|
||||
Blazor Server and Blazor WebAssembly are fully supported.
|
||||
|
||||
### :seedling: Growing
|
||||
|
||||
We add new components and features on a regular basis.
|
||||
|
||||
Short development cycle. We release as soon as new stuff is available. No more quarterly releases.
|
||||
|
||||
## Support exceeding your expectations
|
||||
|
||||
### :speech_balloon: Community Support
|
||||
Everybody is welcome to visit the [Radzen Community forum](https://forum.radzen.com/). Join the growing community and participate in the discussions!
|
||||
|
||||
### :dart: Dedicated Support
|
||||
|
||||
The Radzen team monitors the forum threads, but does not guarantee a response to every question. For guaranteed responses you may consider the dedicated support option.
|
||||
|
||||
Dedicated support for the Radzen Blazor Components is available as part of the [Radzen Professional subscription](https://www.radzen.com/blazor-studio/pricing/).
|
||||
|
||||
Our flagship product [Radzen Blazor Studio](https://www.radzen.com/blazor-studio/) provides tons of productivity features for Blazor developers:
|
||||
- An industry-leading WYSIWYG Blazor design time canvas
|
||||
- Scaffolding a complete CRUD applications from a database
|
||||
- Built-in security - authentication and authorization
|
||||
- Visual Studio Code and Professional support
|
||||
- Deployment to IIS and Azure
|
||||
- Dedicated support with 24 hour guaranteed response time
|
||||
|
||||
## Get started with Radzen Blazor Components
|
||||
|
||||
### 1. Install
|
||||
|
||||
Radzen Blazor Components are distributed as a [Radzen.Blazor nuget package](https://www.nuget.org/packages/Radzen.Blazor). You can add them to your project in one of the following ways
|
||||
- Install the package from command line by running `dotnet add package Radzen.Blazor`
|
||||
- Add the project from the Visual Nuget Package Manager
|
||||
- Manually edit the .csproj file and add a project reference
|
||||
|
||||
### 2. Import the namespace
|
||||
|
||||
Open the `_Imports.razor` file of your Blazor application and add this line `@using Radzen.Blazor`.
|
||||
|
||||
### 3. Include a theme
|
||||
Radzen Blazor components come with five free themes: Material, Standard, Default, Dark, Software and Humanistic.
|
||||
|
||||
To use a theme
|
||||
1. Pick a theme. The [online demos](https://blazor.radzen.com/colors) allow you to preview the available options via the theme dropdown located in the header. The Material theme is currently selected by default.
|
||||
1. Include the theme CSS file in your Blazor application. Open `Pages\_Layout.cshtml` (Blazor Server .NET 6), `Pages\_Host.cshtml` (Blazor Server .NET 7) or `wwwroot/index.html` (Blazor WebAssembly) and include a theme CSS file by adding this snippet
|
||||
```html
|
||||
<link rel="stylesheet" href="_content/Radzen.Blazor/css/material-base.css">
|
||||
```
|
||||
|
||||
To include a different theme (i.e. Standard) just change the name of the CSS file:
|
||||
```
|
||||
<link rel="stylesheet" href="_content/Radzen.Blazor/css/standard-base.css">
|
||||
```
|
||||
|
||||
### 4. Include Radzen.Blazor.js
|
||||
|
||||
Open `Pages\_Layout.cshtml` (Blazor Server .NET 6), `Pages\_Host.cshtml` (Blazor Server .NET 7) or `wwwroot/index.html` (Blazor WebAssembly) and include this snippet:
|
||||
|
||||
```html
|
||||
<script src="_content/Radzen.Blazor/Radzen.Blazor.js?v=@(typeof(Radzen.Colors).Assembly.GetName().Version)"></script>
|
||||
```
|
||||
|
||||
### 5. Use a component
|
||||
Use any Radzen Blazor component by typing its tag name in a Blazor page e.g.
|
||||
```html
|
||||
<RadzenButton Text="Hi"></RadzenButton>
|
||||
```
|
||||
|
||||
#### Data-binding a property
|
||||
```razor
|
||||
<RadzenButton Text=@text />
|
||||
<RadzenTextBox @bind-Value=@text />
|
||||
@code {
|
||||
string text = "Hi";
|
||||
}
|
||||
```
|
||||
|
||||
#### Handing events
|
||||
|
||||
```razor
|
||||
<RadzenButton Click="@ButtonClicked" Text="Hi"></RadzenButton>
|
||||
@code {
|
||||
void ButtonClicked()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -1,46 +1,43 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Razor">
|
||||
<PropertyGroup>
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||
<NoWarn>BL9993;BL0007;BL0005</NoWarn>
|
||||
<TargetFrameworks>netstandard2.1;net5.0;net6.0;net7.0;net8.0</TargetFrameworks>
|
||||
<RazorLangVersion>3.0</RazorLangVersion>
|
||||
<TargetFrameworks>net6.0;net7.0;net8.0</TargetFrameworks>
|
||||
<RazorLangVersion>7.0</RazorLangVersion>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<OutputType>Library</OutputType>
|
||||
<IsPackable>true</IsPackable>
|
||||
<PackageId>Radzen.Blazor</PackageId>
|
||||
<Product>Radzen.Blazor</Product>
|
||||
<Version>4.29.2</Version>
|
||||
<Version>5.2.11</Version>
|
||||
<Copyright>Radzen Ltd.</Copyright>
|
||||
<Authors>Radzen Ltd.</Authors>
|
||||
<Description>Radzen Blazor is a set of 70+ free native Blazor UI controls packed with DataGrid, Scheduler, Charts and robust theming including Material design and Fluent UI.</Description>
|
||||
<Description>Radzen Blazor is a set of 90+ free native Blazor UI controls packed with DataGrid, Scheduler, Charts and robust theming including Material design and Fluent UI.</Description>
|
||||
<PackageTags>blazor material design fluent fluentui components datagrid scheduler charts</PackageTags>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
<PackageProjectUrl>https://www.radzen.com</PackageProjectUrl>
|
||||
<PackageIcon>icon.png</PackageIcon>
|
||||
<PackageLicenseFile>LICENSE.txt</PackageLicenseFile>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<Title>Radzen Components for Blazor</Title>
|
||||
<RepositoryUrl>https://github.com/radzenhq/radzen-blazor</RepositoryUrl>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DartSassBuilder" Version="1.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components" Condition="'$(TargetFramework)' == 'netstandard2.1'" Version="3.1.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Condition="'$(TargetFramework)' == 'netstandard2.1'" Version="3.1.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components" Condition="'$(TargetFramework)' == 'net5.0'" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Condition="'$(TargetFramework)' == 'net5.0'" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components" Condition="'$(TargetFramework)' == 'net6.0'" Version="6.0.25" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Condition="'$(TargetFramework)' == 'net6.0'" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components" Condition="'$(TargetFramework)' == 'net7.0'" Version="7.0.14" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Condition="'$(TargetFramework)' == 'net7.0'" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components" Condition="'$(TargetFramework)' == 'net8.0'" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Condition="'$(TargetFramework)' == 'net8.0'" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" Condition="'$(TargetFramework)' == 'netstandard2.1'" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components" Condition="'$(TargetFramework)' == 'net6.0'" Version="6.0.25" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Condition="'$(TargetFramework)' == 'net6.0'" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components" Condition="'$(TargetFramework)' == 'net7.0'" Version="7.0.14" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Condition="'$(TargetFramework)' == 'net7.0'" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components" Condition="'$(TargetFramework)' == 'net8.0'" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Condition="'$(TargetFramework)' == 'net8.0'" Version="8.0.0" />
|
||||
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.3.7" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="LICENSE.txt" Pack="true" PackagePath="" />
|
||||
<None Include="icon.png" Pack="true" PackagePath="" />
|
||||
<None Include="README.md" Pack="true" PackagePath="\" />
|
||||
<None Include="..\README.md" Pack="true" PackagePath="\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -74,4 +71,4 @@
|
||||
<Move SourceFiles="@(CssFile)" DestinationFolder="$(MSBuildProjectDirectory)/wwwroot/css/" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -24,15 +24,15 @@
|
||||
id="@($"rz-accordiontab-{items.IndexOf(item)}")" aria-controls="@($"rz-accordiontab-{items.IndexOf(item)}-content")" aria-expanded="true">
|
||||
@if (IsSelected(i, item))
|
||||
{
|
||||
<span class="rz-accordion-toggle-icon rzi rzi-chevron-down"></span>
|
||||
<span class="notranslate rz-accordion-toggle-icon rzi rzi-chevron-down"></span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="rz-accordion-toggle-icon rzi rzi-chevron-right"></span>
|
||||
<span class="notranslate rz-accordion-toggle-icon rzi rzi-chevron-right"></span>
|
||||
}
|
||||
@if (!string.IsNullOrEmpty(item.Icon))
|
||||
{
|
||||
<i class="rzi" style="@(!string.IsNullOrEmpty(item.IconColor) ? $"color:{item.IconColor}" : null)">@((MarkupString)item.Icon)</i>
|
||||
<i class="notranslate rzi" style="@(!string.IsNullOrEmpty(item.IconColor) ? $"color:{item.IconColor}" : null)">@((MarkupString)item.Icon)</i>
|
||||
}
|
||||
@if (item.Template != null)
|
||||
{
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<div class="rz-alert-item">
|
||||
@if (ShowIcon)
|
||||
{
|
||||
<RadzenIcon Icon="@GetIcon()" IconColor="@IconColor" Class="rz-alert-icon" />
|
||||
<RadzenIcon Icon="@GetIcon()" IconColor="@IconColor" class="rz-alert-icon" />
|
||||
}
|
||||
<div class="rz-alert-message">
|
||||
@if (!string.IsNullOrEmpty(Title))
|
||||
|
||||
@@ -176,15 +176,15 @@ namespace Radzen.Blazor
|
||||
switch (AlertStyle)
|
||||
{
|
||||
case AlertStyle.Success:
|
||||
return "check_circle_outline";
|
||||
return "check_circle";
|
||||
case AlertStyle.Danger:
|
||||
return "error_outline";
|
||||
return "error";
|
||||
case AlertStyle.Warning:
|
||||
return "warning_amber";
|
||||
case AlertStyle.Info:
|
||||
return "info_outline";
|
||||
return "info";
|
||||
default:
|
||||
return "lightbulb_outline";
|
||||
return "lightbulb";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
2
Radzen.Blazor/RadzenAppearanceToggle.razor
Normal file
2
Radzen.Blazor/RadzenAppearanceToggle.razor
Normal file
@@ -0,0 +1,2 @@
|
||||
@inherits RadzenComponent
|
||||
<RadzenToggleButton Visible=@Visible @attributes=@Attributes Icon=@Icon Change=@OnChange Value=@value Variant="Variant" ButtonStyle="ButtonStyle" ToggleButtonStyle="ToggleButtonStyle" ToggleShade="ToggleShade" />
|
||||
112
Radzen.Blazor/RadzenAppearanceToggle.razor.cs
Normal file
112
Radzen.Blazor/RadzenAppearanceToggle.razor.cs
Normal file
@@ -0,0 +1,112 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// Dark or light theme switch. Requires <see cref="ThemeService" /> to be registered in the DI container.
|
||||
/// </summary>
|
||||
public partial class RadzenAppearanceToggle : RadzenComponent
|
||||
{
|
||||
[Inject]
|
||||
private ThemeService ThemeService { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the switch button variant.
|
||||
/// </summary>
|
||||
/// <value>The switch button variant.</value>
|
||||
[Parameter]
|
||||
public Variant Variant { get; set; } = Variant.Text;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the switch button style.
|
||||
/// </summary>
|
||||
/// <value>The switch button style.</value>
|
||||
[Parameter]
|
||||
public ButtonStyle ButtonStyle { get; set; } = ButtonStyle.Base;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the switch button toggled shade.
|
||||
/// </summary>
|
||||
/// <value>The switch button toggled shade.</value>
|
||||
[Parameter]
|
||||
public Shade ToggleShade { get; set; } = Shade.Default;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the switch button toggled style.
|
||||
/// </summary>
|
||||
/// <value>The switch button toggled style.</value>
|
||||
[Parameter]
|
||||
public ButtonStyle ToggleButtonStyle { get; set; } = ButtonStyle.Base;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the light theme. Not set by default - the component uses the light version of the current theme.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string LightTheme { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the dark theme. Not set by default - the component uses the dark version of the current theme.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string DarkTheme { get; set; }
|
||||
|
||||
private string CurrentLightTheme => LightTheme ?? ThemeService.Theme?.ToLowerInvariant() switch
|
||||
{
|
||||
"dark" => "default",
|
||||
"material-dark" => "material",
|
||||
"fluent-dark" => "fluent",
|
||||
"material3-dark" => "material3",
|
||||
"software-dark" => "software",
|
||||
"humanistic-dark" => "humanistic",
|
||||
"standard-dark" => "standard",
|
||||
_ => ThemeService.Theme,
|
||||
};
|
||||
|
||||
private string CurrentDarkTheme => DarkTheme ?? ThemeService.Theme?.ToLowerInvariant() switch
|
||||
{
|
||||
"default" => "dark",
|
||||
"material" => "material-dark",
|
||||
"fluent" => "fluent-dark",
|
||||
"material3" => "material3-dark",
|
||||
"software" => "software-dark",
|
||||
"humanistic" => "humanistic-dark",
|
||||
"standard" => "standard-dark",
|
||||
_ => ThemeService.Theme,
|
||||
};
|
||||
|
||||
private bool value;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
base.OnInitialized();
|
||||
|
||||
ThemeService.ThemeChanged += OnThemeChanged;
|
||||
|
||||
value = ThemeService.Theme != CurrentDarkTheme;
|
||||
}
|
||||
|
||||
private void OnThemeChanged()
|
||||
{
|
||||
value = ThemeService.Theme != CurrentDarkTheme;
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
void OnChange(bool value)
|
||||
{
|
||||
ThemeService.SetTheme(value ? CurrentLightTheme : CurrentDarkTheme);
|
||||
}
|
||||
|
||||
private string Icon => value ? "dark_mode" : "light_mode";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Dispose()
|
||||
{
|
||||
base.Dispose();
|
||||
|
||||
ThemeService.ThemeChanged -= OnThemeChanged;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
@using Radzen
|
||||
@using Radzen.Blazor.Rendering
|
||||
@using System.Collections
|
||||
@using System.Linq.Dynamic.Core
|
||||
@using Microsoft.AspNetCore.Components.Forms
|
||||
@using Microsoft.JSInterop
|
||||
|
||||
@@ -13,7 +12,7 @@
|
||||
@if (Multiline)
|
||||
{
|
||||
<textarea @ref="@search" @attributes="InputAttributes" @onkeydown="@OnFilterKeyPress" value="@Value" disabled="@Disabled"
|
||||
oninput="@OpenScript()" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" @onchange="@OnChange"
|
||||
oninput="@OpenScript()" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" @onchange="@OnChange" onfocus="@(OpenOnFocus ? OpenScript() : null)"
|
||||
aria-autocomplete="list" aria-haspopup="true" autocomplete="off" role="combobox"
|
||||
class="@InputClassList" onblur="Radzen.activeElement = null"
|
||||
id="@Name" aria-expanded="true" placeholder="@CurrentPlaceholder" maxlength="@MaxLength" />
|
||||
@@ -21,7 +20,7 @@
|
||||
else
|
||||
{
|
||||
<input @ref="@search" @attributes="InputAttributes" @onkeydown="@OnFilterKeyPress" value="@Value" disabled="@Disabled"
|
||||
oninput="@OpenScript()" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" @onchange="@OnChange"
|
||||
oninput="@OpenScript()" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" @onchange="@OnChange" onfocus="@(OpenOnFocus ? OpenScript() : null)"
|
||||
aria-autocomplete="list" aria-haspopup="true" autocomplete="off" role="combobox"
|
||||
class="@InputClassList" onblur="Radzen.activeElement = null"
|
||||
type="@InputType" id="@Name" aria-expanded="true" placeholder="@CurrentPlaceholder" maxlength="@MaxLength" />
|
||||
|
||||
@@ -37,6 +37,13 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public bool Multiline { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether popup should open on focus. Set to <c>false</c> by default.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if popup should open on focus; otherwise, <c>false</c>.</value>
|
||||
[Parameter]
|
||||
public bool OpenOnFocus { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Popup height.
|
||||
/// </summary>
|
||||
@@ -79,6 +86,7 @@ namespace Radzen.Blazor
|
||||
/// Gets or sets the underlying max length.
|
||||
/// </summary>
|
||||
/// <value>The max length value.</value>
|
||||
[Parameter]
|
||||
public long? MaxLength { get; set; }
|
||||
|
||||
/// <summary>
|
||||
@@ -144,6 +152,8 @@ namespace Radzen.Blazor
|
||||
{
|
||||
var value = await JSRuntime.InvokeAsync<string>("Radzen.getInputValue", search);
|
||||
|
||||
value = $"{value}";
|
||||
|
||||
if (value.Length < MinLength)
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.closePopup", PopupID);
|
||||
@@ -203,7 +213,7 @@ namespace Radzen.Blazor
|
||||
|
||||
string textProperty = string.IsNullOrEmpty(TextProperty) ? string.Empty : $".{TextProperty}";
|
||||
|
||||
return Query.Where($"o=>o{textProperty}{filterCaseSensitivityOperator}.{Enum.GetName(typeof(StringFilterOperator), FilterOperator)}(@0)",
|
||||
return Query.Where(DynamicLinqCustomTypeProvider.ParsingConfig, $"o=>o{textProperty}{filterCaseSensitivityOperator}.{Enum.GetName(typeof(StringFilterOperator), FilterOperator)}(@0)",
|
||||
FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ? searchText.ToLower() : searchText);
|
||||
}
|
||||
|
||||
@@ -305,7 +315,6 @@ namespace Radzen.Blazor
|
||||
}
|
||||
}
|
||||
|
||||
#if NET5_0_OR_GREATER
|
||||
/// <summary>
|
||||
/// Sets the focus on the input element.
|
||||
/// </summary>
|
||||
@@ -313,6 +322,5 @@ namespace Radzen.Blazor
|
||||
{
|
||||
await search.FocusAsync();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,10 +32,11 @@
|
||||
{
|
||||
var y = category(data) - barHeight / 2 + index * height + index * padding;
|
||||
var x = value(data);
|
||||
var itemValue = Value(data);
|
||||
var itemValue = Value(data);
|
||||
var radius = Chart.BarOptions.Radius;
|
||||
var width = Math.Abs(x0 - x);
|
||||
|
||||
if (radius > height / 2)
|
||||
if (radius > height / 2 || radius > width)
|
||||
{
|
||||
radius = 0;
|
||||
}
|
||||
|
||||
@@ -25,11 +25,11 @@
|
||||
{
|
||||
@if (!string.IsNullOrEmpty(@Icon))
|
||||
{
|
||||
<i class="rz-button-icon-left rzi" style="@(!string.IsNullOrEmpty(IconColor) ? $"color:{IconColor}" : null)">@((MarkupString)Icon)</i>
|
||||
<i class="notranslate rz-button-icon-left rzi" style="@(!string.IsNullOrEmpty(IconColor) ? $"color:{IconColor}" : null)">@((MarkupString)Icon)</i>
|
||||
}
|
||||
@if (!string.IsNullOrEmpty(Image))
|
||||
{
|
||||
<img class="rz-button-icon-left rzi" src="@Image" alt="@ImageAlternateText" />
|
||||
<img class="notranslate rz-button-icon-left rzi" src="@Image" alt="@ImageAlternateText" />
|
||||
}
|
||||
@if (!string.IsNullOrEmpty(Text))
|
||||
{
|
||||
|
||||
@@ -52,17 +52,36 @@ namespace Radzen.Blazor
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public EventCallback<LegendClickEventArgs> LegendClick { get; set; }
|
||||
double? Width { get; set; }
|
||||
|
||||
double? Height { get; set; }
|
||||
/// <summary>
|
||||
/// Gets the runtime width of the chart.
|
||||
/// </summary>
|
||||
protected double? Width { get; set; }
|
||||
|
||||
double MarginTop { get; set; }
|
||||
/// <summary>
|
||||
/// Gets the runtime height of the chart.
|
||||
/// </summary>
|
||||
protected double? Height { get; set; }
|
||||
|
||||
double MarginLeft { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the top margin of the plot area.
|
||||
/// </summary>
|
||||
protected double MarginTop { get; set; }
|
||||
|
||||
double MarginRight { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the left margin of the plot area.
|
||||
/// </summary>
|
||||
protected double MarginLeft { get; set; }
|
||||
|
||||
double MarginBottom { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the right margin of the plot area.
|
||||
/// </summary>
|
||||
protected double MarginRight { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the bottom margin of the plot area.
|
||||
/// </summary>
|
||||
protected double MarginBottom { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the child content. Used to specify series and other configuration.
|
||||
@@ -93,7 +112,11 @@ namespace Radzen.Blazor
|
||||
Series.Remove(series);
|
||||
}
|
||||
|
||||
private bool ShouldRenderAxes()
|
||||
/// <summary>
|
||||
/// Returns whether the chart should render axes.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected bool ShouldRenderAxes()
|
||||
{
|
||||
var pieType = typeof(RadzenPieSeries<>);
|
||||
var donutType = typeof(RadzenDonutSeries<>);
|
||||
@@ -111,7 +134,11 @@ namespace Radzen.Blazor
|
||||
return Series.Count > 0 && Series.All(series => series is IChartBarSeries);
|
||||
}
|
||||
|
||||
private bool UpdateScales()
|
||||
/// <summary>
|
||||
/// Updates the scales based on the configuration.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected virtual bool UpdateScales()
|
||||
{
|
||||
var valueScale = ValueScale;
|
||||
var categoryScale = CategoryScale;
|
||||
@@ -309,7 +336,7 @@ namespace Radzen.Blazor
|
||||
if (squaredDistance < closestSeriesDistanceSquared)
|
||||
{
|
||||
closestSeries = series;
|
||||
closestSeriesData = seriesData;
|
||||
closestSeriesData = seriesData;
|
||||
closestSeriesDistanceSquared = squaredDistance;
|
||||
}
|
||||
}
|
||||
@@ -360,7 +387,7 @@ namespace Radzen.Blazor
|
||||
if (squaredDistance < closestSeriesDistanceSquared)
|
||||
{
|
||||
closestSeries = series;
|
||||
closestSeriesData = seriesData;
|
||||
closestSeriesData = seriesData;
|
||||
closestSeriesDistanceSquared = squaredDistance;
|
||||
}
|
||||
}
|
||||
@@ -370,7 +397,7 @@ namespace Radzen.Blazor
|
||||
if (closestSeriesData != null)
|
||||
{
|
||||
if (closestSeriesData != tooltipData)
|
||||
{
|
||||
{
|
||||
tooltipData = closestSeriesData;
|
||||
tooltip = closestSeries.RenderTooltip(closestSeriesData, MarginLeft, MarginTop, Height ?? 0);
|
||||
chartTooltipContainer.Refresh();
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace Radzen.Blazor
|
||||
public partial class RadzenChartTooltipOptions : RadzenChartComponentBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to show tooltips. By defaults RadzenChart displays tooltips.
|
||||
/// Gets or sets a value indicating whether to show tooltips. By default RadzenChart displays tooltips.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> to display tooltips; otherwise, <c>false</c>.</value>
|
||||
[Parameter]
|
||||
@@ -21,6 +21,12 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public string Style { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Enable or disable shared tooltips (one tooltip displaying data for all values for the same category). By default set to false (a separate tooltip is shown for each point in the category).
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool Shared { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Initialize()
|
||||
{
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace Radzen.Blazor
|
||||
.Add("rz-state-active", !object.Equals(Value, false))
|
||||
.AddDisabled(Disabled);
|
||||
|
||||
ClassList IconClassList => ClassList.Create("rz-chkbox-icon")
|
||||
ClassList IconClassList => ClassList.Create("notranslate rz-chkbox-icon")
|
||||
.Add("rzi rzi-check", object.Equals(Value, true))
|
||||
.Add("rzi rzi-times", object.Equals(Value, null));
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
<div @ref="@item.Element" id="@item.GetItemId()" @onclick="@(args => SelectItem(item))" @attributes="item.Attributes" class="@item.GetItemCssClass()" style="@item.Style">
|
||||
<div class="rz-chkbox" @onkeypress="@(args => OnKeyPress(args, SelectItem(item)))" @onkeypress:preventDefault=preventKeyPress @onkeypress:stopPropagation tabindex="@(Disabled || ReadOnly || item.Disabled || item.ReadOnly ? "-1" : $"{TabIndex}")">
|
||||
<div class="rz-helper-hidden-accessible">
|
||||
<input type="checkbox" name="@Name" value="@item.Value" disabled="@Disabled" readonly="@ReadOnly" tabindex="-1" aria-label="@(item.Text + " " + item.Value)" aria-checked="@((item.Value as bool? == true).ToString().ToLowerInvariant())">
|
||||
<input type="checkbox" name="@Name" value="@item.Value" disabled="@Disabled" readonly="@ReadOnly" tabindex="-1" aria-label="@(item.Text + " " + item.Value)" aria-checked="@(IsSelected(item).ToString().ToLowerInvariant())">
|
||||
</div>
|
||||
<div class=@ItemClassList(item)>
|
||||
<span class=@IconClassList(item)></span>
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace Radzen.Blazor
|
||||
.AddDisabled(Disabled || item.Disabled);
|
||||
|
||||
ClassList IconClassList(RadzenCheckBoxListItem<TValue> item) => ClassList.Create("rz-chkbox-icon")
|
||||
.Add("rzi rzi-check", IsSelected(item));
|
||||
.Add("notranslate rzi rzi-check", IsSelected(item));
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value property.
|
||||
@@ -108,7 +108,7 @@ namespace Radzen.Blazor
|
||||
|
||||
if (value == true)
|
||||
{
|
||||
Value = allItems.Select(i => i.Value);
|
||||
Value = allItems.Where(i => !i.Disabled).Select(i => i.Value);
|
||||
}
|
||||
else if (value == false)
|
||||
{
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
<div @ref=@Element style=@Style @onclick=@Toggle @attributes=@Attributes class=@GetCssClass() id=@GetId() tabindex="@(Disabled ? -1 : TabIndex)" @onkeypress="@(args => OnKeyPress(args, Toggle()))" @onkeypress:preventDefault=preventKeyPress @onkeypress:stopPropagation>
|
||||
@if (Icon != null)
|
||||
{
|
||||
<i class="rzi" style="@(!string.IsNullOrEmpty(IconColor) ? $"color:{IconColor}" : null)">@Icon</i>
|
||||
<i class="notranslate rzi" style="@(!string.IsNullOrEmpty(IconColor) ? $"color:{IconColor}" : null)">@Icon</i>
|
||||
}
|
||||
<div class="rz-colorpicker-value" style="background-color: @Value" ></div>
|
||||
<button type="button" tabindex="-1" class="rz-colorpicker-trigger" disabled=@Disabled @onclick:preventDefault><i class="rzi" /></button>
|
||||
<button aria-label="@ToggleAriaLabel" type="button" tabindex="-1" class="rz-colorpicker-trigger" disabled=@Disabled @onclick:preventDefault><i class="notranslate rzi" /></button>
|
||||
<Popup Lazy=@(PopupRenderMode == PopupRenderMode.OnDemand) @ref=@Popup class="rz-colorpicker-popup" Close=@OnClosePopup Open=@Open>
|
||||
@if (ShowHSV)
|
||||
{
|
||||
|
||||
@@ -18,6 +18,13 @@ namespace Radzen.Blazor
|
||||
/// </example>
|
||||
public partial class RadzenColorPicker : FormComponent<string>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the toggle popup aria label text.
|
||||
/// </summary>
|
||||
/// <value>The toggle popup aria label text.</value>
|
||||
[Parameter]
|
||||
public string ToggleAriaLabel { get; set; } = "Toggle";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the open callback.
|
||||
/// </summary>
|
||||
|
||||
@@ -32,8 +32,9 @@
|
||||
var y = value(data);
|
||||
var itemValue = Value(data);
|
||||
var radius = Chart.ColumnOptions.Radius;
|
||||
var height = Math.Abs(y0 - y);
|
||||
|
||||
if (radius > width / 2)
|
||||
if (radius > width / 2 || radius > height)
|
||||
{
|
||||
radius = 0;
|
||||
}
|
||||
|
||||
@@ -78,6 +78,13 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public CompareOperator Operator { get; set; } = CompareOperator.Equal;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this <see cref="RadzenCompareValidator"/> should be validated on value change of the specified Component.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if should be validated; otherwise, <c>false</c>.</value>
|
||||
[Parameter]
|
||||
public virtual bool ValidateOnComponentValueChange { get; set; } = true;
|
||||
|
||||
private int Compare(object componentValue)
|
||||
{
|
||||
switch (componentValue)
|
||||
@@ -94,13 +101,26 @@ namespace Radzen.Blazor
|
||||
/// <inheritdoc />
|
||||
public override async Task SetParametersAsync(ParameterView parameters)
|
||||
{
|
||||
var shouldValidate = parameters.DidParameterChange(nameof(Value), Value);
|
||||
var valueChanged = parameters.DidParameterChange(nameof(Value), Value);
|
||||
|
||||
await base.SetParametersAsync(parameters);
|
||||
|
||||
if (shouldValidate && !firstRender)
|
||||
if (ValidateOnComponentValueChange && valueChanged && !firstRender && Visible)
|
||||
{
|
||||
EditContext.Validate();
|
||||
var component = Form.FindComponent(Component);
|
||||
if (component != null && component.FieldIdentifier.FieldName != null)
|
||||
{
|
||||
IsValid = Validate(component);
|
||||
|
||||
messages?.Clear(component.FieldIdentifier);
|
||||
|
||||
if (!IsValid)
|
||||
{
|
||||
messages?.Add(component.FieldIdentifier, Text);
|
||||
}
|
||||
|
||||
EditContext?.NotifyValidationStateChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ namespace Radzen
|
||||
/// Gets the unique identifier.
|
||||
/// </summary>
|
||||
/// <returns>Returns the <c>id</c> attribute (if specified) or generates a random one.</returns>
|
||||
protected string GetId()
|
||||
protected virtual string GetId()
|
||||
{
|
||||
if (Attributes != null && Attributes.TryGetValue("id", out var id) && !string.IsNullOrEmpty(Convert.ToString(@id)))
|
||||
{
|
||||
|
||||
@@ -2,7 +2,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
#if NET5_0_OR_GREATER
|
||||
namespace Radzen
|
||||
{
|
||||
/// <summary>
|
||||
@@ -74,5 +73,4 @@ namespace Radzen
|
||||
return (IComponent)Activator.CreateInstance(componentType);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
73
Radzen.Blazor/RadzenDataAnnotationValidator.cs
Normal file
73
Radzen.Blazor/RadzenDataAnnotationValidator.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// A validator component which validates a component value using the data annotations
|
||||
/// defined on the corresponding model property.
|
||||
/// Must be placed inside a <see cref="RadzenTemplateForm{TItem}" />
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// <RadzenTemplateForm TItem="UserModel" Data=@user>
|
||||
/// <RadzenTextBox style="display: block" Name="Name" @bind-Value=@user.Name />
|
||||
/// <RadzenFieldValidator Component="Name" />
|
||||
/// </RadzenTemplateForm>
|
||||
/// @code {
|
||||
/// class UserModel
|
||||
/// {
|
||||
/// [Required(ErrorMessage = "Name is required.")]
|
||||
/// [StringLength(50, ErrorMessage = "Name must be less than 50 characters.")]
|
||||
/// public string Name { get; set; }
|
||||
/// }
|
||||
/// UserModel user = new UserModel();
|
||||
/// }
|
||||
/// </code>
|
||||
/// </example>
|
||||
public class RadzenDataAnnotationValidator : ValidatorBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the message displayed when the component is invalid.
|
||||
/// The message is generated from the data annotation attributes applied to the model property.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public override string Text { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the separator used to join multiple validation messages.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string MessageSeparator { get; set; } = " and ";
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override bool Validate(IRadzenFormComponent component)
|
||||
{
|
||||
var validationResults = new List<ValidationResult>();
|
||||
|
||||
var model = component.FieldIdentifier.Model;
|
||||
|
||||
var getter = PropertyAccess.Getter<object>(model, component.FieldIdentifier.FieldName);
|
||||
|
||||
var value = getter(model);
|
||||
|
||||
var validationContext = new ValidationContext(model)
|
||||
{
|
||||
MemberName = component.FieldIdentifier.FieldName
|
||||
};
|
||||
|
||||
var isValid = Validator.TryValidateProperty(value, validationContext, validationResults);
|
||||
|
||||
if (!isValid)
|
||||
{
|
||||
Text = string.Join(MessageSeparator, validationResults.Select(vr => vr.ErrorMessage));
|
||||
}
|
||||
|
||||
return isValid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<RadzenSelectBarItem Text="@OrOperatorText" Value="LogicalFilterOperator.Or" title="@OrOperatorText" />
|
||||
</Items>
|
||||
</RadzenSelectBar>
|
||||
<RadzenButton title="@ClearFilterText" class="rz-datafilter-item-clear rz-datafilter-all-items-clear" Icon="clear" Click="@(args => ClearFilters())" Visible=@(Filters.Any()) Variant="Variant.Text" Size="ButtonSize.Small" ButtonStyle="ButtonStyle.Dark" />
|
||||
<RadzenButton title="@ClearFilterText" class="rz-datafilter-item-clear rz-datafilter-all-items-clear" Icon="clear" Click="@(args => ClearFilters())" Visible=@(Filters.Any()) Variant="Variant.Text" Size="ButtonSize.Small" ButtonStyle="ButtonStyle.Base" />
|
||||
|
||||
<ul class="rz-datafilter-group">
|
||||
@foreach(var filter in Filters)
|
||||
@@ -28,7 +28,7 @@
|
||||
</li>
|
||||
}
|
||||
<li class="rz-datafilter-item rz-datafilter-bar">
|
||||
<RadzenSplitButton Icon="add" Click="@(args => AddFilter(args?.Value == "group"))" Size="ButtonSize.Small" Variant="Variant.Flat" ButtonStyle="ButtonStyle.Primary" Shade="Shade.Lighter">
|
||||
<RadzenSplitButton Icon="add" Click="@(args => AddFilter(args?.Value == "group"))" Size="ButtonSize.Small" Variant="Variant.Flat" ButtonStyle="ButtonStyle.Base">
|
||||
<RadzenSplitButtonItem Icon="add" Text="@AddFilterText" />
|
||||
<RadzenSplitButtonItem Icon="playlist_add" Value="group" Text="@AddFilterGroupText" />
|
||||
</RadzenSplitButton>
|
||||
|
||||
@@ -10,6 +10,9 @@ namespace Radzen.Blazor
|
||||
/// RadzenDataFilter component.
|
||||
/// </summary>
|
||||
/// <typeparam name="TItem">The type of the item.</typeparam>
|
||||
#if NET6_0_OR_GREATER
|
||||
[CascadingTypeParameter(nameof(TItem))]
|
||||
#endif
|
||||
public partial class RadzenDataFilter<TItem> : RadzenComponent
|
||||
{
|
||||
/// <inheritdoc />
|
||||
@@ -224,6 +227,20 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public string DoesNotContainText { get; set; } = "Does not contain";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the in operator text.
|
||||
/// </summary>
|
||||
/// <value>The in operator text.</value>
|
||||
[Parameter]
|
||||
public string InText { get; set; } = "In";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the not in operator text.
|
||||
/// </summary>
|
||||
/// <value>The not in operator text.</value>
|
||||
[Parameter]
|
||||
public string NotInText { get; set; } = "Not in";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the starts with text.
|
||||
/// </summary>
|
||||
|
||||
@@ -299,10 +299,10 @@ namespace Radzen.Blazor
|
||||
if (PropertyAccess.IsNullableEnum(FilterPropertyType))
|
||||
return new FilterOperator[] { FilterOperator.Equals, FilterOperator.NotEquals, FilterOperator.IsNull, FilterOperator.IsNotNull };
|
||||
|
||||
if ((typeof(IEnumerable).IsAssignableFrom(FilterPropertyType) || typeof(IEnumerable<>).IsAssignableFrom(FilterPropertyType))
|
||||
if ((typeof(IEnumerable).IsAssignableFrom(FilterPropertyType) || typeof(IEnumerable<>).IsAssignableFrom(FilterPropertyType))
|
||||
&& FilterPropertyType != typeof(string))
|
||||
{
|
||||
var operators = new FilterOperator[]
|
||||
var operators = new FilterOperator[]
|
||||
{
|
||||
FilterOperator.Contains,
|
||||
FilterOperator.DoesNotContain,
|
||||
@@ -344,6 +344,10 @@ namespace Radzen.Blazor
|
||||
return DataFilter?.ContainsText;
|
||||
case FilterOperator.DoesNotContain:
|
||||
return DataFilter?.DoesNotContainText;
|
||||
case FilterOperator.In:
|
||||
return DataFilter?.InText;
|
||||
case FilterOperator.NotIn:
|
||||
return DataFilter?.NotInText;
|
||||
case FilterOperator.EndsWith:
|
||||
return DataFilter?.EndsWithText;
|
||||
case FilterOperator.Equals:
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
@using System.Linq.Dynamic.Core
|
||||
@using Microsoft.JSInterop
|
||||
@using Microsoft.AspNetCore.Components.Forms
|
||||
@using Radzen
|
||||
@@ -37,8 +36,8 @@
|
||||
{
|
||||
<div class="rz-group-header-item">
|
||||
<span class="rz-group-header-item-title">@gd.GetTitle()</span>
|
||||
<a aria-label="@RemoveGroupArialLabel" @onclick:preventDefault="true" @onclick=@(args => RemoveGroupAsync(gd)) role="button" class="rz-dialog-titlebar-icon rz-dialog-titlebar-close">
|
||||
<span class="rzi rzi-times"></span>
|
||||
<a id="@(GetId() + "rg")" aria-label="@RemoveGroupAriaLabel" @onclick:preventDefault="true" @onclick=@(args => RemoveGroupAsync(gd)) role="button" class="rz-dialog-titlebar-icon rz-dialog-titlebar-close">
|
||||
<span class="notranslate rzi rzi-times"></span>
|
||||
</a>
|
||||
</div>
|
||||
}
|
||||
@@ -54,7 +53,7 @@
|
||||
{
|
||||
<div class="rz-column-picker">
|
||||
<RadzenDropDown SelectAllText="@AllColumnsText" AllowSelectAll="@AllowPickAllColumns"
|
||||
MaxSelectedLabels="@ColumnsPickerMaxSelectedLabels" InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", SelectVisibleColumnsArialLabel }})"
|
||||
MaxSelectedLabels="@ColumnsPickerMaxSelectedLabels" InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", SelectVisibleColumnsAriaLabel }})"
|
||||
SelectedItemsText="@ColumnsShowingText" Change=@ToggleColumns
|
||||
@bind-Value="@selectedColumns" FilterCaseSensitivity=FilterCaseSensitivity.CaseInsensitive
|
||||
Multiple="true" AllowFiltering="@ColumnsPickerAllowFiltering"
|
||||
@@ -84,10 +83,15 @@
|
||||
|
||||
<div class="rz-data-grid-data" tabindex="-1">
|
||||
<table class="rz-grid-table rz-grid-table-fixed @(AllowAlternatingRows ? "rz-grid-table-striped" : "") @(allColumns.Any(c => c.Parent != null) ? "rz-grid-table-composite" : "") @(getGridLinesCSSClass())">
|
||||
@if(allColumns.All(c => c.Parent == null))
|
||||
{
|
||||
<colgroup>
|
||||
@foreach (var g in Groups)
|
||||
@if (ShowGroupExpandColumn)
|
||||
{
|
||||
<col>
|
||||
@foreach (var g in Groups)
|
||||
{
|
||||
<col>
|
||||
}
|
||||
}
|
||||
@if (Template != null && ShowExpandColumn)
|
||||
{
|
||||
@@ -98,6 +102,7 @@
|
||||
<col id=@(getColumnUniqueId(visibleColumns.IndexOf(column)) + "-col") style="@column.GetStyle(false, false, true)">
|
||||
}
|
||||
</colgroup>
|
||||
}
|
||||
<thead>
|
||||
@for (var i = 0; i < deepestChildColumnLevel + 1; i++)
|
||||
{
|
||||
@@ -141,7 +146,7 @@
|
||||
}
|
||||
</tr>
|
||||
}
|
||||
@if (AllowFiltering && (FilterMode == FilterMode.Simple || FilterMode == FilterMode.SimpleWithMenu) && columns.Where(column => column.Filterable && (!string.IsNullOrEmpty(column.GetFilterProperty()) || column.FilterTemplate != null)).Any())
|
||||
@if (AllowFiltering && (visibleColumns.Any(c => c.FilterMode == FilterMode.Simple || c.FilterMode == FilterMode.SimpleWithMenu) || FilterMode == FilterMode.Simple || FilterMode == FilterMode.SimpleWithMenu) && columns.Where(column => column.Filterable && (!string.IsNullOrEmpty(column.GetFilterProperty()) || column.FilterTemplate != null)).Any())
|
||||
{
|
||||
<tr @onkeydown:stopPropagation>
|
||||
@if (ShowGroupExpandColumn)
|
||||
@@ -161,6 +166,7 @@
|
||||
}
|
||||
@foreach (var column in visibleColumns)
|
||||
{
|
||||
var filterMode = column.FilterMode ?? FilterMode;
|
||||
<th colspan="@column.GetColSpan()" class="@($"rz-unselectable-text {getFrozenColumnClass(column, visibleColumns)} {column.HeaderCssClass}")" scope="col" style="@column.GetStyle(true, true)">
|
||||
@if (AllowFiltering && column.Filterable && column.Columns == null && (!string.IsNullOrEmpty(column.GetFilterProperty()) || column.FilterTemplate != null))
|
||||
{
|
||||
@@ -175,25 +181,25 @@
|
||||
<span class="rz-cell-filter-label" style="height:35px; width:100%;" onclick="event.preventDefault()">
|
||||
@if (PropertyAccess.IsDate(column.FilterPropertyType))
|
||||
{
|
||||
if (FilterMode == FilterMode.Simple)
|
||||
if (filterMode == FilterMode.Simple)
|
||||
{
|
||||
<button class="rz-button rz-button-md rz-button-icon-only rz-variant-flat rz-light" onclick="@($"Radzen.togglePopup(this.parentNode, '{PopupID}{column.GetFilterProperty()}')")">
|
||||
<i class="rzi">date_range</i>
|
||||
<button aria-label="@FilterToggleAriaLabel" class="rz-button rz-button-md rz-button-icon-only rz-variant-flat rz-base rz-shade-default @(column.HasActiveFilter() ? "rz-grid-filter-active" : "")" onclick="@($"Radzen.togglePopup(this.parentNode, '{PopupID}{column.GetFilterProperty()}')")">
|
||||
<i class="notranslate rzi">date_range</i>
|
||||
</button>
|
||||
var filterValue = column.GetFilterValue();
|
||||
var filterOperator = column.GetFilterOperator();
|
||||
@if (filterValue != null && filters.Any(d => d.Property == column.GetFilterProperty()))
|
||||
{
|
||||
<span class="rz-current-filter">@string.Format("{0:" + getFilterDateFormat(column) + "}", filterValue)</span>
|
||||
<i @onclick="@((args) => ClearFilter(column))" class="rzi rz-cell-filter-clear">close</i>
|
||||
<i @onclick="@((args) => ClearFilter(column))" class="notranslate rzi rz-cell-filter-clear">close</i>
|
||||
}
|
||||
else if ((filterOperator == FilterOperator.IsNull || filterOperator == FilterOperator.IsNotNull) && filters.Any(d => d.Property == column.GetFilterProperty()))
|
||||
{
|
||||
<span class="rz-current-filter">@column.GetFilterOperatorText(filterOperator)</span>
|
||||
<i @onclick="@((args) => ClearFilter(column))" class="rzi rz-cell-filter-clear">close</i>
|
||||
<i @onclick="@((args) => ClearFilter(column))" class="notranslate rzi rz-cell-filter-clear">close</i>
|
||||
}
|
||||
<div id="@($"{PopupID}{column.GetFilterProperty()}")" class="rz-overlaypanel"
|
||||
style="display:none;width:550px;" tabindex="0">
|
||||
<div id="@($"{PopupID}{column.GetFilterProperty()}")" class="rz-overlaypanel rz-grid-date-filter"
|
||||
style="display:none;" tabindex="0">
|
||||
<div class="rz-overlaypanel-content">
|
||||
|
||||
<div class="rz-date-filter">
|
||||
@@ -265,18 +271,14 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<RadzenDatePicker TValue="@object" AllowInput=@(AllowFilterDateInput) InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", column.Title + FilterValueArialLabel + column.GetFilterValue() }})"
|
||||
<RadzenDatePicker TValue="@object" AllowInput=@(AllowFilterDateInput) InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", column.Title + FilterValueAriaLabel + column.GetFilterValue() }})"
|
||||
ShowTime="@column.ShowTimeForDateTimeFilter()" ShowTimeOkButton="false" Inline="true" DateFormat="@getFilterDateFormat(column)"
|
||||
Value="@column.GetFilterValue()" Change="@(args => { column.SetFilterValue(args.Value); SaveSettings(); })" />
|
||||
Value="@column.GetFilterValue()" Change="@(args => { column.SetFilterValue(PropertyAccess.IsDateOnly(column.FilterPropertyType) ? PropertyAccess.DateOnlyFromDateTime(args.Value) : args.Value); SaveSettings(); })" />
|
||||
|
||||
</div>
|
||||
<div class="rz-date-filter-buttons">
|
||||
<button class="rz-button rz-clear-filter" @onclick="@((args) => ClearFilter(column, true))">
|
||||
@ClearFilterText
|
||||
</button>
|
||||
<button class="rz-button rz-apply-filter" @onclick="@((args) => ApplyFilter(column, true))">
|
||||
@ApplyFilterText
|
||||
</button>
|
||||
<div class="rz-grid-filter-buttons">
|
||||
<RadzenButton ButtonStyle="ButtonStyle.Base" class="rz-clear-filter" Click="@((args) => ClearFilter(column, true))" Text=@ClearFilterText title="@ClearFilterText" />
|
||||
<RadzenButton ButtonStyle="ButtonStyle.Primary" class="rz-apply-filter" Click="@((args) => ApplyFilter(column, true))" Text=@ApplyFilterText title="@ApplyFilterText" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -285,21 +287,21 @@
|
||||
else
|
||||
{
|
||||
<RadzenDataGridFilterMenu Grid="@this" Column="@column" />
|
||||
<RadzenDatePicker Disabled=@column.CanSetFilterValue() TValue="@object" Style="width:100%" AllowInput=@(AllowFilterDateInput) AllowClear="true" InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", column.Title + FilterValueArialLabel + column.GetFilterValue() }})"
|
||||
<RadzenDatePicker Disabled=@(!column.CanSetFilterValue()) TValue="@object" Style="width:100%" AllowInput=@(AllowFilterDateInput) AllowClear="true" InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", column.Title + FilterValueAriaLabel + column.GetFilterValue() }})"
|
||||
ShowTime="false" ShowTimeOkButton="false" DateFormat="@getFilterDateFormat(column)"
|
||||
Value="@column.GetFilterValue()" Change="@(args => { if(!args.HasValue) { InvokeAsync(() => ClearFilter(column, true)); } else {column.SetFilterValue(args.Value); InvokeAsync(() => ApplyFilter(column, true));} })" />
|
||||
Value="@column.GetFilterValue()" Change="@(args => { if(!args.HasValue) { InvokeAsync(() => ClearFilter(column, true)); } else {column.SetFilterValue(PropertyAccess.IsDateOnly(column.FilterPropertyType) ? PropertyAccess.DateOnlyFromDateTime(args.Value) : args.Value); InvokeAsync(() => ApplyFilter(column, true));} })" />
|
||||
}
|
||||
}
|
||||
else if (PropertyAccess.IsNullableEnum(column.FilterPropertyType) || PropertyAccess.IsEnum(column.FilterPropertyType))
|
||||
{
|
||||
<RadzenDropDown Style="width:100%" AllowClear="true" AllowFiltering="false" TValue="@object"
|
||||
Value=@column.GetFilterValue() Multiple="false" Placeholder="@EnumFilterSelectText" TextProperty="Text" ValueProperty="Value"
|
||||
Data=@((PropertyAccess.IsNullableEnum(column.FilterPropertyType) ? new object[]{ new { Value = -1, Text = EnumNullFilterText}} : Enumerable.Empty<object>()).Concat(EnumExtensions.EnumAsKeyValuePair(Nullable.GetUnderlyingType(column.FilterPropertyType) ?? column.FilterPropertyType)))
|
||||
Data=@((PropertyAccess.IsNullableEnum(column.FilterPropertyType) ? new object[]{ new { Value = Convert.ChangeType(-1, Enum.GetUnderlyingType(Nullable.GetUnderlyingType(column.FilterPropertyType) ?? column.FilterPropertyType)), Text = EnumNullFilterText}} : Enumerable.Empty<object>()).Concat(EnumExtensions.EnumAsKeyValuePair(Nullable.GetUnderlyingType(column.FilterPropertyType) ?? column.FilterPropertyType)))
|
||||
Change="@(args => {column.SetFilterValue(args);column.SetFilterOperator(object.Equals(args, -1) ? FilterOperator.IsNull : FilterOperator.Equals);InvokeAsync(() => ApplyFilter(column, true));})" />
|
||||
}
|
||||
else if (PropertyAccess.IsNumeric(column.FilterPropertyType))
|
||||
{
|
||||
if (FilterMode == FilterMode.SimpleWithMenu)
|
||||
if (filterMode == FilterMode.SimpleWithMenu)
|
||||
{
|
||||
<RadzenDataGridFilterMenu Grid="@this" Column="@column" />
|
||||
}
|
||||
@@ -313,14 +315,14 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
if (FilterMode == FilterMode.SimpleWithMenu)
|
||||
if (filterMode == FilterMode.SimpleWithMenu)
|
||||
{
|
||||
<RadzenDataGridFilterMenu Grid="@this" Column="@column" />
|
||||
}
|
||||
<input aria-label=@(column.Title + FilterValueArialLabel + column.GetFilterValue()) disabled=@column.CanSetFilterValue() id="@(getFilterInputId(column))" @onchange="@((args) => OnFilter(args, column))" @onkeydown="@((args) => OnFilterKeyPress(args, column))" value="@column.GetFilterValue()" type="text" placeholder="@column.GetFilterPlaceholder()" class="rz-textbox" style="width: 100%;" />
|
||||
<input autocomplete="off" aria-label=@(column.Title + FilterValueAriaLabel + column.GetFilterValue()) disabled=@(!column.CanSetFilterValue()) id="@(getFilterInputId(column))" @onchange="@((args) => OnFilter(args, column))" @onkeydown="@((args) => OnFilterKeyPress(args, column))" value="@column.GetFilterValue()" type="text" placeholder="@column.GetFilterPlaceholder()" class="rz-textbox" style="width: 100%;" />
|
||||
@if (column.GetFilterValue() != null && filters.Any(d => d.Property == column.GetFilterProperty()))
|
||||
{
|
||||
<i @onclick="@((args) => ClearFilter(column))" class="rzi rz-cell-filter-clear" style="position:absolute;right:10px;">close</i>
|
||||
<i @onclick="@((args) => ClearFilter(column))" class="notranslate rzi rz-cell-filter-clear" style="position:absolute;inset-inline-end:10px;">close</i>
|
||||
}
|
||||
}
|
||||
</span>
|
||||
@@ -336,17 +338,32 @@
|
||||
<tbody>
|
||||
@if (Data != null)
|
||||
{
|
||||
@if (!ShowEmptyMessage || Count > 0 && (IsVirtualizationAllowed() ? Data.Any() : true) || LoadData.HasDelegate && Data != null && Data.Any())
|
||||
@if (!ShowEmptyMessage || Count > 0 && (IsVirtualizationAllowed() ? Count > 0 : true) || LoadData.HasDelegate && Data.Count() > 0)
|
||||
{
|
||||
if (columns.Count > 0)
|
||||
{
|
||||
@DrawRows(visibleColumns)
|
||||
}
|
||||
else
|
||||
{
|
||||
<tr class=" rz-datatable-emptymessage-row" @onkeydown:stopPropagation>
|
||||
<td class="rz-datatable-emptymessage" colspan="@(visibleColumns.Sum(c => c.GetColSpan()) + (Template != null && ShowExpandColumn ? 1 : 0))">
|
||||
@if (EmptyTemplate != null)
|
||||
{
|
||||
@EmptyTemplate
|
||||
}
|
||||
else
|
||||
{
|
||||
<span style="white-space: normal">@EmptyText</span>
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
<tr class=" rz-datatable-emptymessage-row" @onkeydown:stopPropagation>
|
||||
<td class="rz-datatable-emptymessage" colspan="@(visibleColumns.Sum(c => c.GetColSpan()) + (Template != null && ShowExpandColumn ? 1 : 0))">
|
||||
<td class="rz-datatable-emptymessage" colspan="@(visibleColumns.Sum(c => c.GetColSpan()) + (Template != null && ShowExpandColumn ? 1 : 0) + Groups.Count)">
|
||||
@if (EmptyTemplate != null)
|
||||
{
|
||||
@EmptyTemplate
|
||||
@@ -360,12 +377,12 @@
|
||||
}
|
||||
}
|
||||
</tbody>
|
||||
@if (visibleColumns.Where(c => c.FooterTemplate != null).Any())
|
||||
@if (allColumns.Where(c => c.Visible && c.FooterTemplate != null).Any())
|
||||
{
|
||||
<tfoot class="rz-datatable-tfoot" @onkeydown:stopPropagation>
|
||||
@for (var i = 0; i < deepestChildColumnLevel + 1; i++)
|
||||
{
|
||||
<tr class="">
|
||||
<tr>
|
||||
@if (i == 0) // Only add the th elements for the first row
|
||||
{
|
||||
@if (ShowGroupExpandColumn)
|
||||
@@ -417,7 +434,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<i class="rzi-circle-o-notch"></i>
|
||||
<i class="notranslate rzi-circle-o-notch"></i>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
@@ -459,13 +476,13 @@
|
||||
var cellAttributes = new Dictionary<string, object>(Attributes);
|
||||
|
||||
var rowspan = column.GetRowSpan(true);
|
||||
if(rowspan != 1)
|
||||
if(rowspan > 1)
|
||||
{
|
||||
SetAttribute(cellAttributes, "rowspan", rowspan);
|
||||
}
|
||||
|
||||
var colspan = column.GetColSpan(true);
|
||||
if(colspan != 1)
|
||||
if(colspan > 1)
|
||||
{
|
||||
SetAttribute(cellAttributes, "colspan", colspan);
|
||||
}
|
||||
@@ -476,7 +493,7 @@
|
||||
SetAttribute(cellAttributes, "style", cellStyle);
|
||||
}
|
||||
|
||||
var cellClass = GetCellCssClass(column, Attributes);
|
||||
var cellClass = GetCellCssClass(column, Item, Attributes);
|
||||
if (!string.IsNullOrEmpty(cellClass))
|
||||
{
|
||||
SetAttribute(cellAttributes, "class", cellClass);
|
||||
@@ -510,7 +527,7 @@
|
||||
<text>
|
||||
@if (this.AllowCompositeDataCells ? RowIndex == column.GetLevel() : (column.Parent != null && RowIndex == column.GetLevel() || column.Columns == null))
|
||||
{
|
||||
<td @attributes="@CellAttributes" @oncontextmenu:preventDefault="@this.CellContextMenu.HasDelegate" @onkeydown:stopPropagation>
|
||||
<td @attributes="@CellAttributes" @oncontextmenu:preventDefault="@this.CellContextMenu.HasDelegate" @onkeydown:stopPropagation="true">
|
||||
@if (this.Responsive)
|
||||
{
|
||||
<span class="rz-column-title">
|
||||
@@ -527,7 +544,7 @@
|
||||
@if (this.LoadChildData.HasDelegate && this.ShowExpandColumn && this.allColumns.IndexOf(column) == 0)
|
||||
{
|
||||
<span class="rz-cell-toggle">
|
||||
<a aria-label="@ExpandChildItemAriaLabel" class="@(getExpandIconCssClass(this, Item))" style="@(getExpandIconStyle(this, Item, rowArgs.Item1.Expandable))" @onclick:preventDefault="true" @onclick="_ => this.ExpandItem(Item)" @onclick:stopPropagation>
|
||||
<a id="@(GetId() + "exp")" aria-label="@ExpandChildItemAriaLabel" class="@(getExpandIconCssClass(this, Item))" style="@(getExpandIconStyle(this, Item, rowArgs.Item1.Expandable))" @onclick:preventDefault="true" @onclick="_ => this.ExpandItem(Item)" @onclick:stopPropagation="true">
|
||||
<span class="@(this.ExpandedItemStyle(Item))"></span>
|
||||
</a>
|
||||
<span class="rz-cell-data" @attributes="@spanAttributes">
|
||||
@@ -554,7 +571,7 @@
|
||||
<span class="rz-cell-data" @attributes="@spanAttributes">
|
||||
@if (Item != null)
|
||||
{
|
||||
@if (this.IsRowInEditMode(Item) && column.EditTemplate != null)
|
||||
@if ((column.IsInEditMode(column.Property, Item) || this.IsRowInEditMode(Item)) && column.EditTemplate is not null)
|
||||
{
|
||||
@column.EditTemplate(Item)
|
||||
}
|
||||
@@ -578,7 +595,7 @@
|
||||
@RenderCell(c, Item, this.CellAttributes(Item, c), rowArgs, RowIndex)
|
||||
}
|
||||
}
|
||||
</text>
|
||||
</text>
|
||||
};
|
||||
}
|
||||
|
||||
@@ -594,22 +611,26 @@
|
||||
return columnStyle;
|
||||
}
|
||||
|
||||
string GetCellCssClass(RadzenDataGridColumn<TItem> column, IReadOnlyDictionary<string, object> Attributes)
|
||||
string GetCellCssClass(RadzenDataGridColumn<TItem> column, TItem item, IReadOnlyDictionary<string, object> Attributes)
|
||||
{
|
||||
var CssClass = column.CssClass + " " + getFrozenColumnClass(column, columns.Where(c => c.GetVisible()).ToList()) + " " + getCompositeCellCSSClass(column);
|
||||
|
||||
if (Attributes != null && Attributes.TryGetValue("class", out var @class) && !string.IsNullOrEmpty(Convert.ToString(@class)))
|
||||
List<string> classes = [
|
||||
column.CalculatedCssClass?.Invoke(column, item) ?? string.Empty,
|
||||
column.CssClass,
|
||||
getFrozenColumnClass(column, columns.Where(c => c.GetVisible()).ToList()),
|
||||
getCompositeCellCSSClass(column),
|
||||
];
|
||||
|
||||
if (Attributes?.TryGetValue("class", out var attributeClass) is true)
|
||||
{
|
||||
return $"{CssClass} {@class}".Trim();
|
||||
classes.Add(Convert.ToString(attributeClass));
|
||||
}
|
||||
|
||||
return String.IsNullOrWhiteSpace(CssClass) ? null : CssClass;
|
||||
var result = string.Join(" ", classes.Where(c => !string.IsNullOrWhiteSpace(c)));
|
||||
return !String.IsNullOrWhiteSpace(result) ? result : null;
|
||||
}
|
||||
|
||||
|
||||
async Task OnContextMenu(RadzenDataGridColumn<TItem> Column, TItem Item, MouseEventArgs args)
|
||||
{
|
||||
#if NET5_0_OR_GREATER
|
||||
await OnCellContextMenu(new DataGridCellMouseEventArgs<TItem>
|
||||
{
|
||||
Data = Item,
|
||||
@@ -629,25 +650,6 @@
|
||||
Type = args.Type,
|
||||
Column = Column
|
||||
});
|
||||
#else
|
||||
await OnCellContextMenu(new DataGridCellMouseEventArgs<TItem>
|
||||
{
|
||||
Data = Item,
|
||||
AltKey = args.AltKey,
|
||||
Button = args.Button,
|
||||
Buttons = args.Buttons,
|
||||
ClientX = args.ClientX,
|
||||
ClientY = args.ClientY,
|
||||
CtrlKey = args.CtrlKey,
|
||||
Detail = args.Detail,
|
||||
MetaKey = args.MetaKey,
|
||||
ScreenX = args.ScreenX,
|
||||
ScreenY = args.ScreenY,
|
||||
ShiftKey = args.ShiftKey,
|
||||
Type = args.Type,
|
||||
Column = Column
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
bool clicking;
|
||||
@@ -660,7 +662,6 @@
|
||||
try
|
||||
{
|
||||
clicking = true;
|
||||
#if NET5_0_OR_GREATER
|
||||
await OnCellClick(new DataGridCellMouseEventArgs<TItem>
|
||||
{
|
||||
Data = Item,
|
||||
@@ -680,26 +681,7 @@
|
||||
Type = args.Type,
|
||||
Column = Column
|
||||
});
|
||||
#else
|
||||
await OnCellClick(new DataGridCellMouseEventArgs<TItem>
|
||||
{
|
||||
Data = Item,
|
||||
AltKey = args.AltKey,
|
||||
Button = args.Button,
|
||||
Buttons = args.Buttons,
|
||||
ClientX = args.ClientX,
|
||||
ClientY = args.ClientY,
|
||||
CtrlKey = args.CtrlKey,
|
||||
Detail = args.Detail,
|
||||
MetaKey = args.MetaKey,
|
||||
ScreenX = args.ScreenX,
|
||||
ScreenY = args.ScreenY,
|
||||
ShiftKey = args.ShiftKey,
|
||||
Type = args.Type,
|
||||
Column = Column
|
||||
});
|
||||
#endif
|
||||
#if NET5_0_OR_GREATER
|
||||
|
||||
await OnRowClick(new DataGridRowMouseEventArgs<TItem>
|
||||
{
|
||||
Data = Item,
|
||||
@@ -718,24 +700,7 @@
|
||||
ShiftKey = args.ShiftKey,
|
||||
Type = args.Type
|
||||
});
|
||||
#else
|
||||
await OnRowClick(new DataGridRowMouseEventArgs<TItem>
|
||||
{
|
||||
Data = Item,
|
||||
AltKey = args.AltKey,
|
||||
Button = args.Button,
|
||||
Buttons = args.Buttons,
|
||||
ClientX = args.ClientX,
|
||||
ClientY = args.ClientY,
|
||||
CtrlKey = args.CtrlKey,
|
||||
Detail = args.Detail,
|
||||
MetaKey = args.MetaKey,
|
||||
ScreenX = args.ScreenX,
|
||||
ScreenY = args.ScreenY,
|
||||
ShiftKey = args.ShiftKey,
|
||||
Type = args.Type
|
||||
});
|
||||
#endif
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -745,7 +710,6 @@
|
||||
|
||||
async Task OnDblClick(RadzenDataGridColumn<TItem> Column, TItem Item, MouseEventArgs args)
|
||||
{
|
||||
#if NET5_0_OR_GREATER
|
||||
await OnCellDblClick(new DataGridCellMouseEventArgs<TItem>
|
||||
{
|
||||
Data = Item,
|
||||
@@ -765,26 +729,7 @@
|
||||
Type = args.Type,
|
||||
Column = Column
|
||||
});
|
||||
#else
|
||||
await OnCellDblClick(new DataGridCellMouseEventArgs<TItem>
|
||||
{
|
||||
Data = Item,
|
||||
AltKey = args.AltKey,
|
||||
Button = args.Button,
|
||||
Buttons = args.Buttons,
|
||||
ClientX = args.ClientX,
|
||||
ClientY = args.ClientY,
|
||||
CtrlKey = args.CtrlKey,
|
||||
Detail = args.Detail,
|
||||
MetaKey = args.MetaKey,
|
||||
ScreenX = args.ScreenX,
|
||||
ScreenY = args.ScreenY,
|
||||
ShiftKey = args.ShiftKey,
|
||||
Type = args.Type,
|
||||
Column = Column
|
||||
});
|
||||
#endif
|
||||
#if NET5_0_OR_GREATER
|
||||
|
||||
await OnRowDblClick(new DataGridRowMouseEventArgs<TItem>
|
||||
{
|
||||
Data = Item,
|
||||
@@ -803,24 +748,6 @@
|
||||
ShiftKey = args.ShiftKey,
|
||||
Type = args.Type
|
||||
});
|
||||
#else
|
||||
await OnRowDblClick(new DataGridRowMouseEventArgs<TItem>
|
||||
{
|
||||
Data = Item,
|
||||
AltKey = args.AltKey,
|
||||
Button = args.Button,
|
||||
Buttons = args.Buttons,
|
||||
ClientX = args.ClientX,
|
||||
ClientY = args.ClientY,
|
||||
CtrlKey = args.CtrlKey,
|
||||
Detail = args.Detail,
|
||||
MetaKey = args.MetaKey,
|
||||
ScreenX = args.ScreenX,
|
||||
ScreenY = args.ScreenY,
|
||||
ShiftKey = args.ShiftKey,
|
||||
Type = args.Type
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
static string getExpandIconStyle(RadzenDataGrid<TItem> Grid, TItem Item, bool expandable)
|
||||
|
||||
@@ -29,9 +29,11 @@ namespace Radzen.Blazor
|
||||
/// </RadzenDataGrid>
|
||||
/// </code>
|
||||
/// </example>
|
||||
#if NET6_0_OR_GREATER
|
||||
[CascadingTypeParameter(nameof(TItem))]
|
||||
#endif
|
||||
public partial class RadzenDataGrid<TItem> : PagedDataBoundComponent<TItem>
|
||||
{
|
||||
#if NET5_0_OR_GREATER
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is virtualized.
|
||||
/// </summary>
|
||||
@@ -103,7 +105,7 @@ namespace Radzen.Blazor
|
||||
top = PageSize;
|
||||
}
|
||||
|
||||
var filter = isOData == true ?
|
||||
var filter = isOData == true ?
|
||||
allColumns.ToList().ToODataFilterString<TItem>() : allColumns.ToList().ToFilterString<TItem>();
|
||||
var loadDataArgs = $"{request.StartIndex}|{top}{GetOrderBy()}{filter}";
|
||||
|
||||
@@ -131,20 +133,28 @@ namespace Radzen.Blazor
|
||||
}
|
||||
|
||||
var view = AllowPaging ? PagedView : View;
|
||||
var query = view.AsQueryable().OrderBy(Groups.Any() ? string.Join(',', Groups.Select(g => $"{(typeof(TItem) == typeof(object) ? g.Property : "np(" + g.Property + ")")}")) : "it");
|
||||
_groupedPagedView = query.GroupByMany(Groups.Any() ? Groups.Select(g => $"{(typeof(TItem) == typeof(object) ? g.Property : "np(" + g.Property + ")")}").ToArray() : new string[] { "it" }).ToList();
|
||||
|
||||
var totalItemsCount = await Task.FromResult(_groupedPagedView.Count());
|
||||
var query = Enumerable.Empty<TItem>().AsQueryable();
|
||||
var totalItemsCount = 0;
|
||||
_groupedPagedView = Enumerable.Empty<GroupResult>();
|
||||
|
||||
return new Microsoft.AspNetCore.Components.Web.Virtualization.ItemsProviderResult<GroupResult>(_groupedPagedView.Skip(request.StartIndex).Take(top), totalItemsCount);
|
||||
if (Groups.Any())
|
||||
{
|
||||
query = view.AsQueryable().OrderBy(DynamicLinqCustomTypeProvider.ParsingConfig, Groups.Any() ? string.Join(',', Groups.Select(g => $"{(typeof(TItem) == typeof(object) ? g.Property : "np(" + g.Property + ")")}")) : "it");
|
||||
_groupedPagedView = await Task.FromResult(query.GroupByMany(DynamicLinqCustomTypeProvider.ParsingConfig, Groups.Any() ? Groups.Select(g => $"{(typeof(TItem) == typeof(object) ? g.Property : "np(" + g.Property + ")")}").ToArray() : new string[] { "it" }).ToList());
|
||||
|
||||
totalItemsCount = await Task.FromResult(_groupedPagedView.Count());
|
||||
}
|
||||
|
||||
_view = view;
|
||||
|
||||
return new Microsoft.AspNetCore.Components.Web.Virtualization.ItemsProviderResult<GroupResult>(_groupedPagedView.Any() ? _groupedPagedView.Skip(request.StartIndex).Take(top) : _groupedPagedView, totalItemsCount);
|
||||
}
|
||||
#endif
|
||||
|
||||
RenderFragment DrawRows(IList<RadzenDataGridColumn<TItem>> visibleColumns)
|
||||
{
|
||||
return new RenderFragment(builder =>
|
||||
{
|
||||
#if NET5_0_OR_GREATER
|
||||
if (AllowVirtualization)
|
||||
{
|
||||
if(AllowGrouping && Groups.Any() && !LoadData.HasDelegate)
|
||||
@@ -172,7 +182,7 @@ namespace Radzen.Blazor
|
||||
{
|
||||
builder.OpenComponent(0, typeof(Microsoft.AspNetCore.Components.Web.Virtualization.Virtualize<TItem>));
|
||||
builder.AddAttribute(1, "ItemsProvider", new Microsoft.AspNetCore.Components.Web.Virtualization.ItemsProviderDelegate<TItem>(LoadItems));
|
||||
|
||||
|
||||
builder.AddAttribute(2, "ChildContent", (RenderFragment<TItem>)((context) =>
|
||||
{
|
||||
return (RenderFragment)((b) =>
|
||||
@@ -210,9 +220,6 @@ namespace Radzen.Blazor
|
||||
{
|
||||
DrawGroupOrDataRows(builder, visibleColumns);
|
||||
}
|
||||
#else
|
||||
DrawGroupOrDataRows(builder, visibleColumns);
|
||||
#endif
|
||||
});
|
||||
}
|
||||
|
||||
@@ -256,6 +263,14 @@ namespace Radzen.Blazor
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the callback used to load column filter data for DataGrid FilterMode.CheckBoxList filter mode.
|
||||
/// </summary>
|
||||
/// <value>The load filter data event callback.</value>
|
||||
[Parameter]
|
||||
public EventCallback<DataGridLoadColumnFilterDataEventArgs<TItem>> LoadColumnFilterData { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the load child data callback.
|
||||
/// </summary>
|
||||
@@ -277,6 +292,13 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public string ExpandGroupAriaLabel { get; set; } = "Expand group";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the date simple filter toggle aria label text.
|
||||
/// </summary>
|
||||
/// <value>The date simple filter toggle aria label text.</value>
|
||||
[Parameter]
|
||||
public string FilterToggleAriaLabel { get; set; } = "Toggle";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether DataGrid data cells will follow the header cells structure in composite columns.
|
||||
/// </summary>
|
||||
@@ -296,7 +318,7 @@ namespace Radzen.Blazor
|
||||
public bool Responsive { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Allows to define a custom function for enums DisplayAttribute Description property value translation in datagrid
|
||||
/// Allows to define a custom function for enums DisplayAttribute Description property value translation in datagrid
|
||||
/// Enum filters.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
@@ -317,9 +339,9 @@ namespace Radzen.Blazor
|
||||
if (_groupedPagedView == null)
|
||||
{
|
||||
var orderBy = GetOrderBy();
|
||||
var query = Groups.Count(g => g.SortOrder == null) == Groups.Count || !string.IsNullOrEmpty(orderBy) ? View : View.OrderBy(string.Join(',', Groups.Select(g => $"{(typeof(TItem) == typeof(object) ? g.Property : "np(" + g.Property + ")")} {(g.SortOrder == null ? "" : g.SortOrder == SortOrder.Ascending ? " asc" : " desc")}")));
|
||||
var query = Groups.Count(g => g.SortOrder == null) == Groups.Count || !string.IsNullOrEmpty(orderBy) ? View : View.OrderBy(DynamicLinqCustomTypeProvider.ParsingConfig, string.Join(',', Groups.Select(g => $"{(typeof(TItem) == typeof(object) ? g.Property : "np(" + g.Property + ")")} {(g.SortOrder == null ? "" : g.SortOrder == SortOrder.Ascending ? " asc" : " desc")}")));
|
||||
var v = (AllowPaging && !LoadData.HasDelegate ? query.Skip(skip).Take(PageSize) : query).ToList().AsQueryable();
|
||||
_groupedPagedView = v.GroupByMany(Groups.Select(g => $"{(typeof(TItem) == typeof(object) ? g.Property : "np(" + g.Property + ")")}").ToArray()).ToList();
|
||||
_groupedPagedView = v.GroupByMany(DynamicLinqCustomTypeProvider.ParsingConfig, Groups.Select(g => $"{(typeof(TItem) == typeof(object) ? g.Property : "np(" + g.Property + ")")}").ToArray()).ToList();
|
||||
}
|
||||
return _groupedPagedView;
|
||||
}
|
||||
@@ -327,7 +349,7 @@ namespace Radzen.Blazor
|
||||
|
||||
internal async Task RemoveGroupAsync(GroupDescriptor gd)
|
||||
{
|
||||
Groups.Remove(gd);
|
||||
Groups.Remove(gd);
|
||||
_groupedPagedView = null;
|
||||
|
||||
var column = columns.Where(c => c.GetGroupProperty() == gd.Property).FirstOrDefault();
|
||||
@@ -369,7 +391,7 @@ namespace Radzen.Blazor
|
||||
// https://stackoverflow.com/questions/25308823/targeting-positionsticky-elements-that-are-currently-in-a-stuck-state
|
||||
// https://codepen.io/TomAnthony/pen/qBqgErK
|
||||
// It seemed too complicated, so left + right frozen columns problme has been solved by following css classes:
|
||||
// - rz-frozen-cell-left all of the "left frozen columns" get this class
|
||||
// - rz-frozen-cell-left all of the "left frozen columns" get this class
|
||||
// - rz-frozen-cell-left-end the most right column of the "left frozen columns" get this class to draw the shadow for it
|
||||
// - rz-frozen-cell-left-inner all of the "left inner frozen columns" get this class
|
||||
// - rz-frozen-cell-right all of the "right frozen columns" get this class
|
||||
@@ -461,12 +483,21 @@ namespace Radzen.Blazor
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets key down callback.
|
||||
/// </summary>
|
||||
/// <value>The key down callback.</value>
|
||||
[Parameter]
|
||||
public EventCallback<KeyboardEventArgs> KeyDown { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Handles the <see cref="E:KeyDown" /> event.
|
||||
/// </summary>
|
||||
/// <param name="args">The <see cref="KeyboardEventArgs"/> instance containing the event data.</param>
|
||||
protected virtual async Task OnKeyDown(KeyboardEventArgs args)
|
||||
{
|
||||
await KeyDown.InvokeAsync(args);
|
||||
|
||||
var key = args.Code != null ? args.Code : args.Key;
|
||||
|
||||
if (key == "ArrowDown" || key == "ArrowUp" || key == "ArrowLeft" || key == "ArrowRight")
|
||||
@@ -569,7 +600,7 @@ namespace Radzen.Blazor
|
||||
/// Gives the grid a custom header, allowing the adding of components to create custom tool bars in addtion to column grouping and column picker
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public RenderFragment HeaderTemplate { get; set; }
|
||||
public RenderFragment HeaderTemplate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gives the grid a custom footer, allowing the adding of components to create custom tool bars or custom pagination
|
||||
@@ -659,7 +690,7 @@ namespace Radzen.Blazor
|
||||
columnsList.Add(column);
|
||||
}
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
if (columnsList.Contains(column))
|
||||
{
|
||||
@@ -798,10 +829,11 @@ namespace Radzen.Blazor
|
||||
column.SetFilterValue(filterValue, isFirst);
|
||||
SaveSettings();
|
||||
}));
|
||||
builder.AddAttribute(5, "Disabled", !column.CanSetFilterValue());
|
||||
}
|
||||
else if (FilterMode == FilterMode.SimpleWithMenu)
|
||||
{
|
||||
builder.AddAttribute(4, "Disabled", column.CanSetFilterValue());
|
||||
builder.AddAttribute(4, "Disabled", !column.CanSetFilterValue());
|
||||
}
|
||||
|
||||
builder.CloseComponent();
|
||||
@@ -836,15 +868,21 @@ namespace Radzen.Blazor
|
||||
LogicalFilterOperator = column.GetLogicalFilterOperator()
|
||||
});
|
||||
|
||||
if (FilterMode == FilterMode.CheckBoxList)
|
||||
{
|
||||
allColumns.ToList().ForEach(c =>
|
||||
{
|
||||
c.ClearFilterValues();
|
||||
});
|
||||
}
|
||||
|
||||
SaveSettings();
|
||||
|
||||
if (LoadData.HasDelegate && IsVirtualizationAllowed())
|
||||
{
|
||||
isOData = Data != null && typeof(ODataEnumerable<TItem>).IsAssignableFrom(Data.GetType());
|
||||
Data = null;
|
||||
#if NET5_0_OR_GREATER
|
||||
ResetLoadData();
|
||||
#endif
|
||||
}
|
||||
|
||||
await InvokeAsync(ReloadInternal);
|
||||
@@ -897,9 +935,7 @@ namespace Radzen.Blazor
|
||||
if (LoadData.HasDelegate && IsVirtualizationAllowed())
|
||||
{
|
||||
Data = null;
|
||||
#if NET5_0_OR_GREATER
|
||||
ResetLoadData();
|
||||
#endif
|
||||
}
|
||||
|
||||
await InvokeAsync(ReloadInternal);
|
||||
@@ -951,14 +987,22 @@ namespace Radzen.Blazor
|
||||
|
||||
column.ClearFilters();
|
||||
|
||||
if (FilterMode == FilterMode.CheckBoxList)
|
||||
{
|
||||
allColumns.ToList().ForEach(c =>
|
||||
{
|
||||
c.ClearFilterValues();
|
||||
});
|
||||
}
|
||||
|
||||
skip = 0;
|
||||
CurrentPage = 0;
|
||||
|
||||
SaveSettings();
|
||||
|
||||
await FilterCleared.InvokeAsync(new DataGridColumnFilterEventArgs<TItem>()
|
||||
{
|
||||
Column = column,
|
||||
await FilterCleared.InvokeAsync(new DataGridColumnFilterEventArgs<TItem>()
|
||||
{
|
||||
Column = column,
|
||||
FilterValue = column.GetFilterValue(),
|
||||
SecondFilterValue = column.GetSecondFilterValue(),
|
||||
FilterOperator = column.GetFilterOperator(),
|
||||
@@ -969,9 +1013,7 @@ namespace Radzen.Blazor
|
||||
if (LoadData.HasDelegate && IsVirtualizationAllowed() && shouldReload)
|
||||
{
|
||||
Data = null;
|
||||
#if NET5_0_OR_GREATER
|
||||
ResetLoadData();
|
||||
#endif
|
||||
}
|
||||
|
||||
if (closePopup)
|
||||
@@ -1231,14 +1273,14 @@ namespace Radzen.Blazor
|
||||
/// <value>The null text.</value>
|
||||
[Parameter]
|
||||
public string IsNullText { get; set; } = "Is null";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the is empty text.
|
||||
/// </summary>
|
||||
/// <value>The empty text.</value>
|
||||
[Parameter]
|
||||
public string IsEmptyText { get; set; } = "Is empty";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the is not empty text.
|
||||
/// </summary>
|
||||
@@ -1429,49 +1471,49 @@ namespace Radzen.Blazor
|
||||
/// </summary>
|
||||
/// <value>The remove group button aria label text.</value>
|
||||
[Parameter]
|
||||
public string RemoveGroupArialLabel { get; set; } = "Remove group";
|
||||
public string RemoveGroupAriaLabel { get; set; } = "Remove group";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the select visible columns aria label text.
|
||||
/// </summary>
|
||||
/// <value>The select visible columns aria label text.</value>
|
||||
[Parameter]
|
||||
public string SelectVisibleColumnsArialLabel { get; set; } = "select visible columns";
|
||||
public string SelectVisibleColumnsAriaLabel { get; set; } = "select visible columns";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the column logical filter value aria label text.
|
||||
/// </summary>
|
||||
/// <value>The the column logical filter value aria label text.</value>
|
||||
[Parameter]
|
||||
public string LogicalOperatorArialLabel { get; set; } = " logical filter operator ";
|
||||
public string LogicalOperatorAriaLabel { get; set; } = " logical filter operator ";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the column filter value aria label text.
|
||||
/// </summary>
|
||||
/// <value>The the column filter value aria label text.</value>
|
||||
[Parameter]
|
||||
public string FilterOperatorArialLabel { get; set; } = " filter operator ";
|
||||
public string FilterOperatorAriaLabel { get; set; } = " filter operator ";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the column filter value aria label text.
|
||||
/// </summary>
|
||||
/// <value>The the column filter value aria label text.</value>
|
||||
[Parameter]
|
||||
public string SecondFilterOperatorArialLabel { get; set; } = " second filter operator ";
|
||||
public string SecondFilterOperatorAriaLabel { get; set; } = " second filter operator ";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the column filter value aria label text.
|
||||
/// </summary>
|
||||
/// <value>The the column filter value aria label text.</value>
|
||||
[Parameter]
|
||||
public string FilterValueArialLabel { get; set; } = " filter value ";
|
||||
public string FilterValueAriaLabel { get; set; } = " filter value ";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the column filter value aria label text.
|
||||
/// </summary>
|
||||
/// <value>The the column filter value aria label text.</value>
|
||||
[Parameter]
|
||||
public string SecondFilterValueArialLabel { get; set; } = " second filter value ";
|
||||
public string SecondFilterValueAriaLabel { get; set; } = " second filter value ";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether user can pick all columns in column picker.
|
||||
@@ -1564,6 +1606,21 @@ namespace Radzen.Blazor
|
||||
{
|
||||
var actualColumnIndexFrom = columns.IndexOf(columnToReorder);
|
||||
var actualColumnIndexTo = columns.IndexOf(columnToReorderTo);
|
||||
|
||||
var reorderingArgs = new DataGridColumnReorderingEventArgs<TItem>
|
||||
{
|
||||
Column = columnToReorder,
|
||||
ToColumn = columnToReorderTo
|
||||
};
|
||||
|
||||
await ColumnReordering.InvokeAsync(reorderingArgs);
|
||||
|
||||
if(reorderingArgs.Cancel)
|
||||
{
|
||||
indexOfColumnToReoder = null;
|
||||
return;
|
||||
}
|
||||
|
||||
columns.Remove(columnToReorder);
|
||||
columns.Insert(actualColumnIndexTo, columnToReorder);
|
||||
|
||||
@@ -1617,6 +1674,13 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public EventCallback<DataGridColumnResizedEventArgs<TItem>> ColumnResized { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the column reordering callback.
|
||||
/// </summary>
|
||||
/// <value>The column reordering callback.</value>
|
||||
[Parameter]
|
||||
public EventCallback<DataGridColumnReorderingEventArgs<TItem>> ColumnReordering { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the column reordered callback.
|
||||
/// </summary>
|
||||
@@ -1759,11 +1823,7 @@ namespace Radzen.Blazor
|
||||
|
||||
internal bool IsVirtualizationAllowed()
|
||||
{
|
||||
#if NET5_0_OR_GREATER
|
||||
return AllowVirtualization;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
IList<TItem> _value;
|
||||
@@ -1971,8 +2031,8 @@ namespace Radzen.Blazor
|
||||
|
||||
if (resetColumnState)
|
||||
{
|
||||
allColumns.ToList().ForEach(c =>
|
||||
{
|
||||
allColumns.ToList().ForEach(c =>
|
||||
{
|
||||
c.ClearFilters();
|
||||
c.ResetSortOrder();
|
||||
c.SetOrderIndex(null);
|
||||
@@ -1982,11 +2042,6 @@ namespace Radzen.Blazor
|
||||
selectedColumns = allColumns.Where(c => c.Pickable && c.GetVisible()).ToList();
|
||||
sorts.Clear();
|
||||
}
|
||||
|
||||
if (!LoadData.HasDelegate)
|
||||
{
|
||||
SaveSettings();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1994,9 +2049,7 @@ namespace Radzen.Blazor
|
||||
/// </summary>
|
||||
public async override Task Reload()
|
||||
{
|
||||
#if NET5_0_OR_GREATER
|
||||
ResetLoadData();
|
||||
#endif
|
||||
await ReloadInternal();
|
||||
}
|
||||
|
||||
@@ -2009,7 +2062,7 @@ namespace Radzen.Blazor
|
||||
{
|
||||
Count = 1;
|
||||
}
|
||||
#if NET5_0_OR_GREATER
|
||||
|
||||
if (AllowVirtualization)
|
||||
{
|
||||
if (!LoadData.HasDelegate)
|
||||
@@ -2029,7 +2082,7 @@ namespace Radzen.Blazor
|
||||
Data = null;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!IsVirtualizationAllowed())
|
||||
{
|
||||
await InvokeLoadData(skip, PageSize);
|
||||
@@ -2043,7 +2096,6 @@ namespace Radzen.Blazor
|
||||
}
|
||||
else
|
||||
{
|
||||
#if NET5_0_OR_GREATER
|
||||
if (AllowVirtualization)
|
||||
{
|
||||
if (virtualize != null)
|
||||
@@ -2056,7 +2108,6 @@ namespace Radzen.Blazor
|
||||
await groupVirtualize.RefreshDataAsync();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (LoadData.HasDelegate && View.Count() == 0 && Count > 0)
|
||||
@@ -2143,7 +2194,7 @@ namespace Radzen.Blazor
|
||||
|
||||
internal string ExpandedGroupItemStyle(RadzenDataGridGroupRow<TItem> item, bool? expandedOnLoad)
|
||||
{
|
||||
return collapsedGroupItems.Keys.Contains(item) || expandedOnLoad == false ? "rz-row-toggler rzi-grid-sort rzi-chevron-circle-right" : "rz-row-toggler rzi-grid-sort rzi-chevron-circle-down";
|
||||
return collapsedGroupItems.Keys.Contains(item) || expandedOnLoad == false ? "notranslate rz-row-toggler rzi-grid-sort rzi-chevron-circle-right" : "rz-row-toggler rzi-grid-sort rzi-chevron-circle-down";
|
||||
}
|
||||
|
||||
internal bool IsGroupItemExpanded(RadzenDataGridGroupRow<TItem> item)
|
||||
@@ -2154,7 +2205,7 @@ namespace Radzen.Blazor
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether all groups should be expanded when DataGrid is grouped.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if groups are expanded; otherwise, <c>false</c>.</value>
|
||||
/// <value><c>true</c> if groups are expanded; otherwise, <c>false</c>.</value>
|
||||
[Parameter]
|
||||
public bool? AllGroupsExpanded { get; set; }
|
||||
|
||||
@@ -2215,7 +2266,7 @@ namespace Radzen.Blazor
|
||||
|
||||
internal string ExpandedItemStyle(TItem item)
|
||||
{
|
||||
return expandedItems.Keys.Any(i => ItemEquals(i, item)) ? "rz-row-toggler rzi-chevron-circle-down" : "rz-row-toggler rzi-chevron-circle-right";
|
||||
return expandedItems.Keys.Any(i => ItemEquals(i, item)) ? "notranslate rz-row-toggler rzi-chevron-circle-down" : "rz-row-toggler rzi-chevron-circle-right";
|
||||
}
|
||||
|
||||
internal Dictionary<TItem, bool> selectedItems = new Dictionary<TItem, bool>();
|
||||
@@ -2227,9 +2278,9 @@ namespace Radzen.Blazor
|
||||
return (RowSelect.HasDelegate || ValueChanged.HasDelegate || SelectionMode == DataGridSelectionMode.Multiple) && selectedItems.Keys.Any(i => ItemEquals(i, item)) ? $"rz-state-highlight rz-data-row {isInEditMode} " : $"rz-data-row {isInEditMode} ";
|
||||
}
|
||||
|
||||
internal Tuple<Radzen.RowRenderEventArgs<TItem>, IReadOnlyDictionary<string, object>> RowAttributes(TItem item)
|
||||
internal Tuple<Radzen.RowRenderEventArgs<TItem>, IReadOnlyDictionary<string, object>> RowAttributes(TItem item, int index)
|
||||
{
|
||||
var args = new Radzen.RowRenderEventArgs<TItem>() { Data = item, Expandable = Template != null || LoadChildData.HasDelegate };
|
||||
var args = new Radzen.RowRenderEventArgs<TItem>() { Data = item, Index = index, Expandable = Template != null || LoadChildData.HasDelegate };
|
||||
|
||||
if (RowRender != null)
|
||||
{
|
||||
@@ -2433,6 +2484,19 @@ namespace Radzen.Blazor
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Collapse all rows that are expanded
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async System.Threading.Tasks.Task CollapseAll()
|
||||
{
|
||||
foreach(var item in expandedItems.Keys.ToList())
|
||||
{
|
||||
await CollapseItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Collapse a range of rows.
|
||||
/// </summary>
|
||||
@@ -2442,23 +2506,25 @@ namespace Radzen.Blazor
|
||||
// Only allow the functionality when multiple row expand is allowed
|
||||
if (this.ExpandMode != DataGridExpandMode.Multiple) return;
|
||||
|
||||
foreach (TItem item in items)
|
||||
foreach (TItem item in items.Where(x=> expandedItems.Keys.Any(i => ItemEquals(i, x))))
|
||||
{
|
||||
if (expandedItems.Keys.Any(i => ItemEquals(i, item)))
|
||||
{
|
||||
expandedItems.Remove(item);
|
||||
await RowCollapse.InvokeAsync(item);
|
||||
|
||||
if (childData.ContainsKey(item))
|
||||
{
|
||||
childData.Remove(item);
|
||||
_view = null;
|
||||
}
|
||||
}
|
||||
await CollapseItem(item);
|
||||
}
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
private async Task CollapseItem(TItem item)
|
||||
{
|
||||
expandedItems.Remove(item);
|
||||
await RowCollapse.InvokeAsync(item);
|
||||
|
||||
if (childData.ContainsKey(item))
|
||||
{
|
||||
childData.Remove(item);
|
||||
_view = null;
|
||||
}
|
||||
}
|
||||
|
||||
internal async System.Threading.Tasks.Task ExpandItem(TItem item)
|
||||
{
|
||||
if (ExpandMode == DataGridExpandMode.Single && expandedItems.Keys.Any() && !LoadChildData.HasDelegate)
|
||||
@@ -2493,14 +2559,7 @@ namespace Radzen.Blazor
|
||||
}
|
||||
else
|
||||
{
|
||||
expandedItems.Remove(item);
|
||||
await RowCollapse.InvokeAsync(item);
|
||||
|
||||
if (childData.ContainsKey(item))
|
||||
{
|
||||
childData.Remove(item);
|
||||
_view = null;
|
||||
}
|
||||
await CollapseItem(item);
|
||||
}
|
||||
|
||||
await InvokeAsync(StateHasChanged);
|
||||
@@ -2776,12 +2835,12 @@ namespace Radzen.Blazor
|
||||
{
|
||||
if (editedItems.Keys.Any(i => ItemEquals(i, item)))
|
||||
{
|
||||
var editContext = editContexts[item];
|
||||
var editContext = editContexts.FirstOrDefault(i => ItemEquals(i.Key, item)).Value;
|
||||
|
||||
if (editContext.Validate())
|
||||
if (editContext?.Validate() == true)
|
||||
{
|
||||
editedItems.Remove(item);
|
||||
editContexts.Remove(item);
|
||||
editedItems = editedItems.Where(i => !ItemEquals(i.Key, item)).ToDictionary(i => i.Key, i => i.Value);
|
||||
editContexts = editContexts.Where(i => !ItemEquals(i.Key, item)).ToDictionary(i => i.Key, i => i.Value);
|
||||
|
||||
if (itemsToInsert.Contains(item))
|
||||
{
|
||||
@@ -2817,7 +2876,6 @@ namespace Radzen.Blazor
|
||||
}
|
||||
else
|
||||
{
|
||||
#if NET5_0_OR_GREATER
|
||||
itemsToInsert.Remove(item);
|
||||
if(virtualize != null)
|
||||
{
|
||||
@@ -2828,7 +2886,6 @@ namespace Radzen.Blazor
|
||||
{
|
||||
groupVirtualize.RefreshDataAsync();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -2888,7 +2945,6 @@ namespace Radzen.Blazor
|
||||
}
|
||||
else
|
||||
{
|
||||
#if NET5_0_OR_GREATER
|
||||
if(virtualize != null)
|
||||
{
|
||||
await virtualize.RefreshDataAsync();
|
||||
@@ -2898,7 +2954,6 @@ namespace Radzen.Blazor
|
||||
{
|
||||
await groupVirtualize.RefreshDataAsync();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
await EditRowInternal(item);
|
||||
@@ -3021,8 +3076,8 @@ namespace Radzen.Blazor
|
||||
/// Gets or sets the group descriptors.
|
||||
/// </summary>
|
||||
/// <value>The groups.</value>
|
||||
public ObservableCollection<GroupDescriptor> Groups
|
||||
{
|
||||
public ObservableCollection<GroupDescriptor> Groups
|
||||
{
|
||||
get
|
||||
{
|
||||
if (groups == null)
|
||||
@@ -3049,13 +3104,7 @@ namespace Radzen.Blazor
|
||||
var functionName = $"Radzen['{getColumnUniqueId(indexOfColumnToReoder.Value)}end']";
|
||||
await JSRuntime.InvokeVoidAsync("eval", $"{functionName} && {functionName}()");
|
||||
|
||||
RadzenDataGridColumn<TItem> column;
|
||||
|
||||
column = columns.Where(c => c.GetVisible()).ElementAtOrDefault(indexOfColumnToReoder.Value);
|
||||
|
||||
//may be its a child column
|
||||
if (column == null)
|
||||
column = allColumns.Where(c => c.GetVisible()).ElementAtOrDefault(indexOfColumnToReoder.Value);
|
||||
var column = allColumns.Where(c => c.Visible).ToList().ElementAtOrDefault(indexOfColumnToReoder.Value);
|
||||
|
||||
if (column != null && column.Groupable && !string.IsNullOrEmpty(column.GetGroupProperty()))
|
||||
{
|
||||
@@ -3076,7 +3125,7 @@ namespace Radzen.Blazor
|
||||
}
|
||||
|
||||
indexOfColumnToReoder = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -3156,9 +3205,7 @@ namespace Radzen.Blazor
|
||||
if (LoadData.HasDelegate && IsVirtualizationAllowed())
|
||||
{
|
||||
Data = null;
|
||||
#if NET5_0_OR_GREATER
|
||||
ResetLoadData();
|
||||
#endif
|
||||
}
|
||||
|
||||
InvokeAsync(ReloadInternal);
|
||||
@@ -3186,9 +3233,7 @@ namespace Radzen.Blazor
|
||||
if (LoadData.HasDelegate && IsVirtualizationAllowed())
|
||||
{
|
||||
Data = null;
|
||||
#if NET5_0_OR_GREATER
|
||||
ResetLoadData();
|
||||
#endif
|
||||
}
|
||||
|
||||
InvokeAsync(ReloadInternal);
|
||||
@@ -3219,7 +3264,7 @@ namespace Radzen.Blazor
|
||||
additionalClasses.Add("rz-density-compact");
|
||||
}
|
||||
|
||||
return $"rz-has-paginator rz-datatable rz-datatable-scrollable {String.Join(" ", additionalClasses)}";
|
||||
return $"rz-has-pager rz-datatable rz-datatable-scrollable {String.Join(" ", additionalClasses)}";
|
||||
}
|
||||
|
||||
internal string getHeaderStyle()
|
||||
@@ -3298,7 +3343,7 @@ namespace Radzen.Blazor
|
||||
Visible = c.GetVisible(),
|
||||
OrderIndex = c.GetOrderIndex(),
|
||||
SortOrder = c.GetSortOrder(),
|
||||
SortIndex = c.getSortIndex(),
|
||||
SortIndex = c.GetSortIndex(),
|
||||
FilterValue = c.GetFilterValue(),
|
||||
FilterOperator = c.GetFilterOperator(),
|
||||
SecondFilterValue = c.GetSecondFilterValue(),
|
||||
@@ -3323,8 +3368,8 @@ namespace Radzen.Blazor
|
||||
if (SettingsChanged.HasDelegate)
|
||||
{
|
||||
var shouldUpdateState = false;
|
||||
var hasFilter = settings.Columns != null && settings.Columns.Any(c =>
|
||||
c.FilterValue != null || c.SecondFilterValue != null ||
|
||||
var hasFilter = settings.Columns != null && settings.Columns.Any(c =>
|
||||
c.FilterValue != null || c.SecondFilterValue != null ||
|
||||
c.FilterOperator == FilterOperator.IsNull || c.FilterOperator == FilterOperator.IsNotNull ||
|
||||
c.FilterOperator == FilterOperator.IsEmpty || c.FilterOperator == FilterOperator.IsNotEmpty ||
|
||||
c.SecondFilterOperator == FilterOperator.IsNull || c.SecondFilterOperator == FilterOperator.IsNotNull ||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.JSInterop;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
@@ -37,6 +38,19 @@ namespace Radzen.Blazor
|
||||
[CascadingParameter]
|
||||
public RadzenDataGridColumn<TItem> Parent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies wether CheckBoxList filter list virtualization is enabled. Set to <c>true</c> by default.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool AllowCheckBoxListVirtualization { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the column filter mode.
|
||||
/// </summary>
|
||||
/// <value>The column filter mode.</value>
|
||||
[Parameter]
|
||||
public FilterMode? FilterMode { get; set; }
|
||||
|
||||
internal void RemoveColumn(RadzenDataGridColumn<TItem> column)
|
||||
{
|
||||
if (Grid.childColumns.Contains(column))
|
||||
@@ -76,17 +90,14 @@ namespace Radzen.Blazor
|
||||
|
||||
internal int GetColSpan(bool isDataCell = false)
|
||||
{
|
||||
if (!Grid.AllowCompositeDataCells && isDataCell)
|
||||
if (!Grid.AllowCompositeDataCells && isDataCell || Columns == null)
|
||||
return 1;
|
||||
|
||||
var directChildColumns = Grid.childColumns.Where(c => c.GetVisible() && c.Parent == this);
|
||||
var span = ColumnsCollection.Concat(ColumnsCollection.SelectManyRecursive(c => c.ColumnsCollection)).Sum(c => c.ColumnsCollection.Count())
|
||||
- ColumnsCollection.SelectManyRecursive(c => c.ColumnsCollection).Count(c => c.ColumnsCollection.Any())
|
||||
+ ColumnsCollection.Where(c => c.ColumnsCollection.Count() == 0).Count();
|
||||
|
||||
if (Parent == null)
|
||||
{
|
||||
return Columns == null ? 1 : directChildColumns.Sum(c => c.GetColSpan());
|
||||
}
|
||||
|
||||
return Columns == null ? 1 : directChildColumns.Count();
|
||||
return span != 0 ? span : ColumnsCollection.Count;
|
||||
}
|
||||
|
||||
internal int GetRowSpan(bool isDataCell = false)
|
||||
@@ -97,7 +108,7 @@ namespace Radzen.Blazor
|
||||
if (Columns == null && Parent != null)
|
||||
{
|
||||
var level = this.GetLevel();
|
||||
return level == Grid.deepestChildColumnLevel ? 1 : level + 1;
|
||||
return level == Grid.deepestChildColumnLevel ? 1 : level < Grid.deepestChildColumnLevel ? Grid.deepestChildColumnLevel : level + 1;
|
||||
}
|
||||
|
||||
return Columns == null && Parent == null ? Grid.deepestChildColumnLevel + 1 : 1;
|
||||
@@ -122,6 +133,23 @@ namespace Radzen.Blazor
|
||||
{
|
||||
Grid.AddColumn(this);
|
||||
|
||||
var canSetFilterPropertyType = (FilterMode ?? Grid.FilterMode) == Radzen.FilterMode.CheckBoxList && FilterTemplate == null;
|
||||
|
||||
if (canSetFilterPropertyType)
|
||||
{
|
||||
if (Type == null)
|
||||
{
|
||||
_filterPropertyType = typeof(IEnumerable<object>);
|
||||
}
|
||||
|
||||
if (GetFilterOperator() == FilterOperator.Equals)
|
||||
{
|
||||
SetFilterOperator(FilterOperator.Contains);
|
||||
}
|
||||
|
||||
Grid.FilterPopupRenderMode = PopupRenderMode.OnDemand;
|
||||
}
|
||||
|
||||
var property = GetFilterProperty();
|
||||
|
||||
if (!string.IsNullOrEmpty(property))
|
||||
@@ -129,7 +157,7 @@ namespace Radzen.Blazor
|
||||
_propertyType = PropertyAccess.GetPropertyType(typeof(TItem), property);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(property) && Type == null)
|
||||
if (!string.IsNullOrEmpty(property) && Type == null && !canSetFilterPropertyType)
|
||||
{
|
||||
_filterPropertyType = _propertyType;
|
||||
}
|
||||
@@ -138,18 +166,18 @@ namespace Radzen.Blazor
|
||||
{
|
||||
_filterPropertyType = Type;
|
||||
}
|
||||
else
|
||||
else if(!string.IsNullOrEmpty(Property))
|
||||
{
|
||||
propertyValueGetter = PropertyAccess.Getter<TItem, object>(Property);
|
||||
}
|
||||
|
||||
if (_filterPropertyType == typeof(string))
|
||||
if (_filterPropertyType == typeof(string) && filterOperator != FilterOperator.Custom && filterOperator == null)
|
||||
{
|
||||
FilterOperator = FilterOperator.Contains;
|
||||
SetFilterOperator(FilterOperator.Contains);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int? orderIndex;
|
||||
|
||||
/// <summary>
|
||||
@@ -268,7 +296,7 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public string ColumnPickerTitle
|
||||
{
|
||||
get => _columnPickerTitle ?? Title;
|
||||
get => _columnPickerTitle ?? Title ?? string.Empty;
|
||||
set => _columnPickerTitle = value;
|
||||
}
|
||||
|
||||
@@ -331,7 +359,7 @@ namespace Radzen.Blazor
|
||||
{
|
||||
return FilterPlaceholder ?? string.Empty;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the second filter value.
|
||||
/// </summary>
|
||||
@@ -367,6 +395,13 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public string CssClass { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a function that calculates the CSS class based on the <typeparamref name="TItem"/> value.
|
||||
/// </summary>
|
||||
/// <value>The dynamic CSS class applied to data cells.</value>
|
||||
[Parameter]
|
||||
public Func<RadzenDataGridColumn<TItem>, TItem, string> CalculatedCssClass { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the header CSS class applied to header cell.
|
||||
/// </summary>
|
||||
@@ -465,6 +500,12 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public RenderFragment<TItem> EditTemplate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Allows the column to override whether or not this column's the <see cref="EditTemplate" /> is visible at runtime.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public Func<string, TItem, bool> IsInEditMode { get; set; } = (property, item) => false;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the header template.
|
||||
/// </summary>
|
||||
@@ -521,6 +562,13 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public Type Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the IFormatProvider used for FormatString.
|
||||
/// </summary>
|
||||
/// <value>The IFormatProvider.</value>
|
||||
[Parameter]
|
||||
public IFormatProvider FormatProvider { get; set; }
|
||||
|
||||
Func<TItem, object> propertyValueGetter;
|
||||
|
||||
/// <summary>
|
||||
@@ -532,7 +580,9 @@ namespace Radzen.Blazor
|
||||
{
|
||||
var value = propertyValueGetter != null && !string.IsNullOrEmpty(Property) && !Property.Contains('.') ? propertyValueGetter(item) : !string.IsNullOrEmpty(Property) ? PropertyAccess.GetValue(item, Property) : "";
|
||||
|
||||
if ((PropertyAccess.IsEnum(FilterPropertyType) || PropertyAccess.IsNullableEnum(FilterPropertyType)) && value != null)
|
||||
|
||||
if ((PropertyAccess.IsEnum(FilterPropertyType) || PropertyAccess.IsNullableEnum(FilterPropertyType) ||
|
||||
((FilterMode ?? Grid.FilterMode) == Radzen.FilterMode.CheckBoxList && (value as Enum) != null)) && value != null)
|
||||
{
|
||||
var enumValue = value as Enum;
|
||||
if (enumValue != null)
|
||||
@@ -541,7 +591,7 @@ namespace Radzen.Blazor
|
||||
}
|
||||
}
|
||||
|
||||
return !string.IsNullOrEmpty(FormatString) ? string.Format(Grid?.Culture ?? CultureInfo.CurrentCulture, FormatString, value) : Convert.ToString(value, Grid?.Culture ?? CultureInfo.CurrentCulture);
|
||||
return !string.IsNullOrEmpty(FormatString) ? string.Format(FormatProvider ?? Grid?.Culture ?? CultureInfo.CurrentCulture, FormatString, value) : Convert.ToString(value, FormatProvider ?? Grid?.Culture ?? CultureInfo.CurrentCulture);
|
||||
}
|
||||
|
||||
internal object GetHeader()
|
||||
@@ -573,7 +623,7 @@ namespace Radzen.Blazor
|
||||
|
||||
var width = GetWidthOrGridSetting()?.Trim();
|
||||
|
||||
if (!string.IsNullOrEmpty(width) && !isForCol)
|
||||
if (!string.IsNullOrEmpty(width))
|
||||
{
|
||||
style.Add($"width:{width}");
|
||||
}
|
||||
@@ -608,13 +658,13 @@ namespace Radzen.Blazor
|
||||
{
|
||||
var stackColumns = visibleFrozenColumns.Where((c, i) => visibleFrozenColumns.IndexOf(this) > i);
|
||||
|
||||
return GetStackedStyleForFrozen(stackColumns, "left");
|
||||
return GetStackedStyleForFrozen(stackColumns, "inset-inline-start");
|
||||
}
|
||||
else
|
||||
{
|
||||
var stackColumns = visibleFrozenColumns.Where((c, i) => visibleFrozenColumns.IndexOf(this) < i);
|
||||
|
||||
return GetStackedStyleForFrozen(stackColumns, "right");
|
||||
return GetStackedStyleForFrozen(stackColumns, "inset-inline-end");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -848,12 +898,10 @@ namespace Radzen.Blazor
|
||||
Grid.SaveSettings();
|
||||
if (Grid.IsVirtualizationAllowed())
|
||||
{
|
||||
#if NET5_0_OR_GREATER
|
||||
if (Grid.virtualize != null)
|
||||
{
|
||||
await Grid.virtualize.RefreshDataAsync();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -874,12 +922,10 @@ namespace Radzen.Blazor
|
||||
Grid.SaveSettings();
|
||||
if (Grid.IsVirtualizationAllowed())
|
||||
{
|
||||
#if NET5_0_OR_GREATER
|
||||
if (Grid.virtualize != null)
|
||||
{
|
||||
await Grid.virtualize.RefreshDataAsync();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -900,12 +946,10 @@ namespace Radzen.Blazor
|
||||
Grid.SaveSettings();
|
||||
if (Grid.IsVirtualizationAllowed())
|
||||
{
|
||||
#if NET5_0_OR_GREATER
|
||||
if (Grid.virtualize != null)
|
||||
{
|
||||
await Grid.virtualize.RefreshDataAsync();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -915,10 +959,10 @@ namespace Radzen.Blazor
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (parameters.DidParameterChange(nameof(FilterOperator), FilterOperator))
|
||||
|
||||
if (parameters.DidParameterChange(nameof(FilterOperator), FilterOperator) || _filterOperator != null)
|
||||
{
|
||||
filterOperator = parameters.GetValueOrDefault<FilterOperator>(nameof(FilterOperator));
|
||||
filterOperator = _filterOperator ?? parameters.GetValueOrDefault<FilterOperator>(nameof(FilterOperator));
|
||||
}
|
||||
|
||||
if (parameters.DidParameterChange(nameof(SecondFilterValue), SecondFilterValue))
|
||||
@@ -955,6 +999,14 @@ namespace Radzen.Blazor
|
||||
return filterValue ?? FilterValue;
|
||||
}
|
||||
|
||||
internal void ClearFilterValues()
|
||||
{
|
||||
if (headerCell != null)
|
||||
{
|
||||
headerCell.filterValues = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get column filter operator.
|
||||
/// </summary>
|
||||
@@ -998,13 +1050,21 @@ namespace Radzen.Blazor
|
||||
value = offset;
|
||||
}
|
||||
|
||||
if (PropertyAccess.IsEnum(FilterPropertyType) || (PropertyAccess.IsNullableEnum(FilterPropertyType)))
|
||||
{
|
||||
Type enumType = Enum.GetUnderlyingType(Nullable.GetUnderlyingType(FilterPropertyType) ?? FilterPropertyType);
|
||||
value = value is not null ? Convert.ChangeType(value, enumType) : null;
|
||||
}
|
||||
|
||||
if (isFirst)
|
||||
{
|
||||
filterValue = value;
|
||||
filterValue = CanSetCurrentValue(value) ? value :
|
||||
GetFilterOperator() == FilterOperator.IsEmpty || GetFilterOperator() == FilterOperator.IsNotEmpty ? string.Empty : null;
|
||||
}
|
||||
else
|
||||
{
|
||||
secondFilterValue = value;
|
||||
secondFilterValue = CanSetCurrentValue(value, false) ? value :
|
||||
GetSecondFilterOperator() == FilterOperator.IsEmpty || GetSecondFilterOperator() == FilterOperator.IsNotEmpty ? string.Empty : null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1020,12 +1080,18 @@ namespace Radzen.Blazor
|
||||
await Grid.FirstPage(true);
|
||||
}
|
||||
|
||||
internal bool CanSetFilterValue()
|
||||
internal bool CanSetFilterValue(bool isFirst = true)
|
||||
{
|
||||
return GetFilterOperator() == FilterOperator.IsNull
|
||||
|| GetFilterOperator() == FilterOperator.IsNotNull
|
||||
|| GetFilterOperator() == FilterOperator.IsEmpty
|
||||
|| GetFilterOperator() == FilterOperator.IsNotEmpty;
|
||||
var fo = isFirst ? GetFilterOperator() : GetSecondFilterOperator();
|
||||
return fo != FilterOperator.IsNull
|
||||
&& fo != FilterOperator.IsNotNull
|
||||
&& fo != FilterOperator.IsEmpty
|
||||
&& fo != FilterOperator.IsNotEmpty;
|
||||
}
|
||||
|
||||
internal bool CanSetCurrentValue(object value, bool isFirst = true)
|
||||
{
|
||||
return CanSetFilterValue(isFirst) ? !string.IsNullOrEmpty(value?.ToString()) : false;
|
||||
}
|
||||
|
||||
internal bool HasCustomFilter()
|
||||
@@ -1037,7 +1103,7 @@ namespace Radzen.Blazor
|
||||
{
|
||||
return GetFilterValue() != null
|
||||
|| GetSecondFilterValue() != null
|
||||
|| CanSetFilterValue()
|
||||
|| !CanSetFilterValue()
|
||||
|| HasCustomFilter();
|
||||
}
|
||||
|
||||
@@ -1073,28 +1139,41 @@ namespace Radzen.Blazor
|
||||
/// </summary>
|
||||
public void ClearFilters()
|
||||
{
|
||||
SetFilterValue(null);
|
||||
SetFilterValue(null, false);
|
||||
SetFilterOperator(null);
|
||||
SetSecondFilterOperator(null);
|
||||
|
||||
FilterValue = null;
|
||||
SecondFilterValue = null;
|
||||
FilterOperator = FilterOperator == FilterOperator.Custom
|
||||
var fo = FilterOperator == FilterOperator.Custom
|
||||
? FilterOperator.Custom
|
||||
: typeof(System.Collections.IEnumerable).IsAssignableFrom(FilterPropertyType)
|
||||
? !string.IsNullOrEmpty(FilterProperty) && FilterProperty != Property ? FilterOperator.In : FilterOperator.Contains
|
||||
: default(FilterOperator);
|
||||
SecondFilterOperator = default(FilterOperator);
|
||||
|
||||
SetFilterOperator(fo);
|
||||
SetSecondFilterOperator(null);
|
||||
|
||||
filterValue = null;
|
||||
secondFilterValue = null;
|
||||
|
||||
ClearFilterValues();
|
||||
|
||||
LogicalFilterOperator = default(LogicalFilterOperator);
|
||||
|
||||
}
|
||||
|
||||
FilterOperator? _filterOperator;
|
||||
/// <summary>
|
||||
/// Gets or sets the filter operator.
|
||||
/// </summary>
|
||||
/// <value>The filter operator.</value>
|
||||
[Parameter]
|
||||
public FilterOperator FilterOperator { get; set; }
|
||||
public FilterOperator FilterOperator
|
||||
{
|
||||
get
|
||||
{
|
||||
return _filterOperator ?? FilterOperator.Equals;
|
||||
}
|
||||
set
|
||||
{
|
||||
_filterOperator = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the second filter operator.
|
||||
@@ -1187,10 +1266,10 @@ namespace Radzen.Blazor
|
||||
/// </summary>
|
||||
public virtual IEnumerable<FilterOperator> GetFilterOperators()
|
||||
{
|
||||
if (PropertyAccess.IsEnum(FilterPropertyType))
|
||||
if (PropertyAccess.IsEnum(FilterPropertyType) || FilterPropertyType == typeof(bool))
|
||||
return new FilterOperator[] { FilterOperator.Equals, FilterOperator.NotEquals };
|
||||
|
||||
if (PropertyAccess.IsNullableEnum(FilterPropertyType))
|
||||
if (PropertyAccess.IsNullableEnum(FilterPropertyType) || FilterPropertyType == typeof(bool?))
|
||||
return new FilterOperator[] { FilterOperator.Equals, FilterOperator.NotEquals, FilterOperator.IsNull, FilterOperator.IsNotNull };
|
||||
|
||||
return Enum.GetValues(typeof(FilterOperator)).Cast<FilterOperator>().Where(o =>
|
||||
@@ -1198,7 +1277,7 @@ namespace Radzen.Blazor
|
||||
var isStringOperator = o == FilterOperator.Contains || o == FilterOperator.DoesNotContain
|
||||
|| o == FilterOperator.StartsWith || o == FilterOperator.EndsWith || o == FilterOperator.IsEmpty || o == FilterOperator.IsNotEmpty;
|
||||
|
||||
if ((FilterPropertyType == typeof(string) || !QueryableExtension.IsEnumerable(FilterPropertyType)) &&
|
||||
if ((FilterPropertyType == typeof(string) || !QueryableExtension.IsEnumerable(FilterPropertyType)) &&
|
||||
(o == FilterOperator.In || o == FilterOperator.NotIn)) return false;
|
||||
|
||||
return FilterPropertyType == typeof(string) || QueryableExtension.IsEnumerable(FilterPropertyType) ? isStringOperator
|
||||
@@ -1291,6 +1370,12 @@ namespace Radzen.Blazor
|
||||
/// </summary>
|
||||
public virtual bool ShowTimeForDateTimeFilter()
|
||||
{
|
||||
#if NET6_0_OR_GREATER
|
||||
if (FilterPropertyType == typeof(DateOnly))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1331,7 +1416,10 @@ namespace Radzen.Blazor
|
||||
Grid?.RemoveColumn(this);
|
||||
}
|
||||
|
||||
internal int? getSortIndex()
|
||||
/// <summary>
|
||||
/// Gets the column sort descriptor index indicating order of applied column sort in case of multiple sorting.
|
||||
/// </summary>
|
||||
public int? GetSortIndex()
|
||||
{
|
||||
var descriptor = Grid.sorts.Where(s => s.Property == GetSortProperty()).FirstOrDefault();
|
||||
if (descriptor != null)
|
||||
@@ -1344,8 +1432,8 @@ namespace Radzen.Blazor
|
||||
|
||||
internal string getSortIndexAsString()
|
||||
{
|
||||
var index = getSortIndex();
|
||||
return index != null ? $"{getSortIndex() + 1}" : "";
|
||||
var index = GetSortIndex();
|
||||
return index != null ? $"{GetSortIndex() + 1}" : "";
|
||||
}
|
||||
|
||||
internal RadzenDataGridHeaderCell<TItem> headerCell;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
@using Microsoft.JSInterop
|
||||
@inject IJSRuntime JSRuntime
|
||||
<button title=@Column.GetFilterOperatorText(Column.GetFilterOperator()) class="@FilterIconStyle()" onclick="@($"Radzen.togglePopup(this.parentNode, '{Grid.PopupID}{Column.GetFilterProperty()}')")">
|
||||
<i class="rzi">@Grid.FilterIcon</i>
|
||||
<i class="notranslate rzi">@Grid.FilterIcon</i>
|
||||
@if (Column.GetFilterOperator() == FilterOperator.DoesNotContain)
|
||||
{
|
||||
<s>@Column.GetFilterOperatorSymbol(Column.GetFilterOperator())</s>
|
||||
@@ -128,7 +128,7 @@
|
||||
{
|
||||
var additionalStyle = Column.HasActiveFilter() ? "rz-grid-filter-active" : "";
|
||||
|
||||
return $"rz-filter-button rz-button rz-button-md rz-button-icon-only rz-variant-flat rz-light {additionalStyle}";
|
||||
return $"rz-filter-button rz-button rz-button-md rz-button-icon-only rz-variant-flat rz-base rz-shade-default {additionalStyle}";
|
||||
}
|
||||
|
||||
protected async Task ApplyFilter(FilterOperator value)
|
||||
|
||||
61
Radzen.Blazor/RadzenDataGridGroupFooterCell.razor
Normal file
61
Radzen.Blazor/RadzenDataGridGroupFooterCell.razor
Normal file
@@ -0,0 +1,61 @@
|
||||
@typeparam TItem
|
||||
@if (RowIndex == Column.GetLevel())
|
||||
{
|
||||
<td rowspan="@(Column.GetRowSpan())" colspan="@(Column.GetColSpan())" @attributes="@Attributes" class="@CssClass" scope="col" style="@GetStyle()">
|
||||
<span class="rz-column-footer">
|
||||
@if (Column.GroupFooterTemplate != null)
|
||||
{
|
||||
@Column.GroupFooterTemplate(Group)
|
||||
}
|
||||
</span>
|
||||
</td>
|
||||
}
|
||||
else
|
||||
{
|
||||
@foreach(var column in Grid.childColumns.Where(c => c.GetVisible() && c.Parent == Column))
|
||||
{
|
||||
<RadzenDataGridGroupFooterCell Group="@Group" RowIndex="@RowIndex" Grid="@Grid" Column="@column" Style="@column.GetStyle(true, true)"
|
||||
CssClass="@($"{Column.GroupFooterCssClass} {Grid.getFrozenColumnClass(column, Grid.ColumnsCollection.Where(c => c.GetVisible()).ToList())} {Grid.getCompositeCellCSSClass(column)}")"
|
||||
Attributes="@(Attributes)" />
|
||||
}
|
||||
}
|
||||
@code {
|
||||
[Parameter(CaptureUnmatchedValues = true)]
|
||||
public IReadOnlyDictionary<string, object> Attributes { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public Group Group { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public RadzenDataGridColumn<TItem> Column { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public int RowIndex { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public RadzenDataGrid<TItem> Grid { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string CssClass { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string Style { get; set; }
|
||||
|
||||
private string GetStyle()
|
||||
{
|
||||
var styles = new List<string>() { Column.GetStyle(true, true), Style };
|
||||
|
||||
if (Attributes?.TryGetValue("style", out var styleAttribute) == true)
|
||||
{
|
||||
styles.Add(Convert.ToString(styleAttribute));
|
||||
}
|
||||
|
||||
var finalStyle = string.Join(";",
|
||||
styles
|
||||
.Select(x => x?.Trim().TrimEnd(';'))
|
||||
.Where(x => !string.IsNullOrEmpty(x))
|
||||
);
|
||||
|
||||
return finalStyle;
|
||||
}
|
||||
}
|
||||
@@ -1,41 +1,41 @@
|
||||
@typeparam TItem
|
||||
@using System.Linq.Dynamic.Core
|
||||
<tr>
|
||||
@if (Grid.Template != null && Grid.ShowExpandColumn)
|
||||
{
|
||||
@if (Grid.ShowGroupExpandColumn)
|
||||
{
|
||||
<th class="rz-col-icon rz-unselectable-text" scope="col">
|
||||
<span class="rz-column-title"></span>
|
||||
</th>
|
||||
}
|
||||
}
|
||||
@for(var i = 0; i < GetLevel(); i++)
|
||||
{
|
||||
<td class="rz-col-icon">
|
||||
<span class="rz-column-title"></span>
|
||||
</td>
|
||||
}
|
||||
@foreach (var column in Columns)
|
||||
{
|
||||
<td class="@($" {column.GroupFooterCssClass} {Grid.getFrozenColumnClass(column, Columns)}".Trim())" style="@column.GetStyle(true, true)">
|
||||
<span class="rz-column-footer">
|
||||
@if (column.GroupFooterTemplate != null)
|
||||
@for (var i = 0; i < Grid.deepestChildColumnLevel + 1; i++)
|
||||
{
|
||||
<tr>
|
||||
@if (i == 0) // Only add the th elements for the first row
|
||||
{
|
||||
@if (Grid.Template != null && Grid.ShowExpandColumn)
|
||||
{
|
||||
@if (Grid.ShowGroupExpandColumn)
|
||||
{
|
||||
@column.GroupFooterTemplate(Group)
|
||||
<th class="rz-col-icon rz-unselectable-text" scope="col">
|
||||
<span class="rz-column-title"></span>
|
||||
</th>
|
||||
}
|
||||
</span>
|
||||
</td>
|
||||
}
|
||||
</tr>
|
||||
|
||||
}
|
||||
}
|
||||
@for (var j = 0; j < GetLevel(); j++)
|
||||
{
|
||||
<td class="rz-col-icon">
|
||||
<span class="rz-column-title"></span>
|
||||
</td>
|
||||
}
|
||||
@foreach (var column in Columns)
|
||||
{
|
||||
<RadzenDataGridGroupFooterCell Group="@Group" RowIndex="@i" Grid="@Grid" Column="@column" CssClass="@($"{column.GroupFooterCssClass} {Grid.getFrozenColumnClass(column, Columns)} {Grid.getCompositeCellCSSClass(column)}".Trim())" />
|
||||
}
|
||||
</tr>
|
||||
}
|
||||
@code {
|
||||
[Parameter]
|
||||
public IList<RadzenDataGridColumn<TItem>> Columns { get; set; }
|
||||
|
||||
GroupResult _groupResult;
|
||||
[Parameter]
|
||||
public GroupResult GroupResult
|
||||
{
|
||||
public GroupResult GroupResult
|
||||
{
|
||||
get
|
||||
{
|
||||
return _groupResult;
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
@using System.Globalization
|
||||
@{
|
||||
var rowArgs = Grid?.GroupRowAttributes(this);
|
||||
|
||||
if (Grid != null)
|
||||
{
|
||||
if (rowArgs.Item1.Expanded == true && Grid.collapsedGroupItems.ContainsKey(this))
|
||||
{
|
||||
Grid.collapsedGroupItems.Remove(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
<tr class="rz-group-row" @attributes="@rowArgs.Item2">
|
||||
@if (Grid.ShowGroupExpandColumn)
|
||||
@@ -19,7 +27,7 @@
|
||||
}
|
||||
<td class="rz-col-icon">
|
||||
<span class="rz-column-title"></span>
|
||||
<a aria-label=@Grid.ExpandGroupAriaLabel @onclick:preventDefault="true" @onclick="@(_ => Grid.ExpandGroupItem(this, rowArgs.Item1.Expanded))">
|
||||
<a id="@(Grid.GridId() + Group.GetHashCode())" aria-label=@Grid.ExpandGroupAriaLabel @onclick:preventDefault="true" @onclick="@(_ => Grid.ExpandGroupItem(this, rowArgs.Item1.Expanded))">
|
||||
<span class="@(Grid.ExpandedGroupItemStyle(this, Grid.allGroupsExpanded != null ? Grid.allGroupsExpanded : rowArgs.Item1.Expanded))"></span>
|
||||
</a>
|
||||
</td>
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
@typeparam TItem
|
||||
@using Microsoft.JSInterop
|
||||
@using Radzen.Blazor.Rendering
|
||||
@using System.Globalization
|
||||
@using System.Linq.Dynamic.Core
|
||||
@using System.Collections
|
||||
@using Radzen
|
||||
|
||||
@if (RowIndex == Column.GetLevel())
|
||||
{
|
||||
<th rowspan="@(Column.GetRowSpan())" colspan="@(Column.GetColSpan())" @attributes="@Attributes" class="@CssClass" scope="col" style="@GetStyle()" @onmouseup=@(args => Grid.EndColumnReorder(args, ColumnIndex))>
|
||||
@@ -26,7 +31,7 @@
|
||||
{
|
||||
@if (Column.GetSortOrder() == SortOrder.Ascending)
|
||||
{
|
||||
<span class="rz-sortable-column-icon rzi-grid-sort rzi-sort rzi-sort-asc"></span>
|
||||
<span class="notranslate rz-sortable-column-icon rzi-grid-sort rzi-sort rzi-sort-asc"></span>
|
||||
@if(Grid.ShowMultiColumnSortingIndex)
|
||||
{
|
||||
<RadzenBadge BadgeStyle="BadgeStyle.Info" Shade="Shade.Lighter" IsPill=true Text="@Column.getSortIndexAsString()" />
|
||||
@@ -34,7 +39,7 @@
|
||||
}
|
||||
else if (Column.GetSortOrder() == SortOrder.Descending)
|
||||
{
|
||||
<span class="rz-sortable-column-icon rzi-grid-sort rzi-sort rzi-sort-desc"></span>
|
||||
<span class="notranslate rz-sortable-column-icon rzi-grid-sort rzi-sort rzi-sort-desc"></span>
|
||||
@if(Grid.ShowMultiColumnSortingIndex)
|
||||
{
|
||||
<RadzenBadge BadgeStyle="BadgeStyle.Info" Shade="Shade.Lighter" IsPill=true Text="@Column.getSortIndexAsString()" />
|
||||
@@ -42,7 +47,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="rz-sortable-column-icon rzi-grid-sort rzi-sort"></span>
|
||||
<span class="notranslate rz-sortable-column-icon rzi-grid-sort rzi-sort"></span>
|
||||
}
|
||||
}
|
||||
</span>
|
||||
@@ -53,7 +58,8 @@
|
||||
@onmousedown:preventDefault="true"
|
||||
@onmousedown=@StartColumnResize @onmouseup=@StopColumnResize> </div>
|
||||
}
|
||||
@if (Grid.AllowFiltering && Column.Filterable && Grid.FilterMode == FilterMode.Advanced)
|
||||
@{var filterMode = Column.FilterMode ?? Grid.FilterMode;}
|
||||
@if (Grid.AllowFiltering && Column.Filterable && (filterMode == FilterMode.Advanced || filterMode == FilterMode.CheckBoxList))
|
||||
{
|
||||
<i @ref=@filterButton @onclick:stopPropagation="true" @onmousedown=@ToggleFilter
|
||||
class="@getFilterIconCss(Column)" onclick=@getFilterOpen() @onclick:preventDefault="true">
|
||||
@@ -70,8 +76,10 @@
|
||||
else
|
||||
{
|
||||
<form id="@($"{getColumnPopupID()}-form")" @onsubmit="@(args => ApplyFilter())" class="rz-grid-filter">
|
||||
@if (filterMode == FilterMode.Advanced)
|
||||
{
|
||||
<span class="rz-grid-filter-label">@Grid.FilterText</span>
|
||||
<RadzenDropDown InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Grid.FilterOperatorArialLabel + Column.GetFilterOperatorText(Column.GetSecondFilterOperator()) }})"
|
||||
<RadzenDropDown InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Grid.FilterOperatorAriaLabel + Column.GetFilterOperatorText(Column.GetSecondFilterOperator()) }})"
|
||||
@onclick:preventDefault="true" Data="@(Column.GetFilterOperators().Select(t => new { Value = Column.GetFilterOperatorText(t), Key = t }))" TextProperty="Value" ValueProperty="Key" TValue="FilterOperator" Value="@Column.GetFilterOperator()" Change="@(args => Column.SetFilterOperator((FilterOperator)args))" />
|
||||
@if (Column.FilterValueTemplate != null)
|
||||
{
|
||||
@@ -79,10 +87,10 @@
|
||||
}
|
||||
else if (PropertyAccess.IsNullableEnum(Column.FilterPropertyType) || PropertyAccess.IsEnum(Column.FilterPropertyType))
|
||||
{
|
||||
<RadzenDropDown AllowClear="false" AllowFiltering="false" TValue="@object"
|
||||
<RadzenDropDown Disabled="@(!Column.CanSetFilterValue())" AllowClear="false" AllowFiltering="false" TValue="@object"
|
||||
Value=@Column.GetFilterValue() Multiple="false" Placeholder="@Grid.EnumFilterSelectText" TextProperty="Text" ValueProperty="Value" Data=@EnumExtensions.EnumAsKeyValuePair(Nullable.GetUnderlyingType(Column.FilterPropertyType) ?? Column.FilterPropertyType, Grid.EnumFilterTranslationFunc)
|
||||
Change="@(args => Column.SetFilterValue(args))"
|
||||
InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Column.Title + Grid.FilterValueArialLabel + Column.GetFilterValue() }})" />
|
||||
InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Column.Title + Grid.FilterValueAriaLabel + Column.GetFilterValue() }})" />
|
||||
}
|
||||
else if (PropertyAccess.IsNumeric(Column.FilterPropertyType))
|
||||
{
|
||||
@@ -90,32 +98,32 @@
|
||||
}
|
||||
else if (PropertyAccess.IsDate(Column.FilterPropertyType))
|
||||
{
|
||||
<RadzenDatePicker TValue="@object" ShowTime="@Column.ShowTimeForDateTimeFilter()" ShowTimeOkButton="true" DateFormat="@Grid.getFilterDateFormat(Column)"
|
||||
Value="@Column.GetFilterValue()" Change="@(args => Column.SetFilterValue(args.Value))" AllowInput=@(Grid.AllowFilterDateInput)
|
||||
InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Column.Title + Grid.FilterValueArialLabel + Column.GetFilterValue() }})" />
|
||||
<RadzenDatePicker Disabled="@(!Column.CanSetFilterValue())" TValue="@object" ShowTime="@Column.ShowTimeForDateTimeFilter()" ShowTimeOkButton="true" DateFormat="@Grid.getFilterDateFormat(Column)"
|
||||
Value="@Column.GetFilterValue()" Change="@(args => Column.SetFilterValue(PropertyAccess.IsDateOnly(Column.FilterPropertyType) ? PropertyAccess.DateOnlyFromDateTime(args.Value) : args.Value))" AllowInput=@(Grid.AllowFilterDateInput)
|
||||
InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Column.Title + Grid.FilterValueAriaLabel + Column.GetFilterValue() }})" />
|
||||
|
||||
}
|
||||
else if (Column.FilterPropertyType == typeof(bool) || Column.FilterPropertyType == typeof(bool?))
|
||||
{
|
||||
<RadzenCheckBox InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Column.Title + Grid.FilterValueArialLabel + Column.GetFilterValue() }})" TriState="true" TValue="@object" Value="@Column.GetFilterValue()" Change="@(args => { Column.SetFilterValue(null); Column.SetFilterValue(args); Grid.SaveSettings(); InvokeAsync(() => Grid.Reload()); })" />
|
||||
<RadzenCheckBox Disabled="@(!Column.CanSetFilterValue())" InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Column.Title + Grid.FilterValueAriaLabel + Column.GetFilterValue() }})" TriState="true" TValue="@object" Value="@Column.GetFilterValue()" Change="@(args => { Column.SetFilterValue(null); Column.SetFilterValue(args); Grid.SaveSettings(); InvokeAsync(() => Grid.Reload()); })" />
|
||||
}
|
||||
else
|
||||
{
|
||||
<RadzenTextBox id="@($"{getColumnPopupID()}-sf")" aria-label=@(Column.Title + Grid.FilterValueArialLabel + Column.GetFilterValue()) Value="@($"{Column.GetFilterValue()}")" Change="@(args => Column.SetFilterValue(args))" />
|
||||
<RadzenTextBox Disabled="@(!Column.CanSetFilterValue())" id="@($"{getColumnPopupID()}-sf")" aria-label=@(Column.Title + Grid.FilterValueAriaLabel + Column.GetFilterValue()) Value="@($"{Column.GetFilterValue()}")" Change="@(args => Column.SetFilterValue(args))" />
|
||||
}
|
||||
|
||||
<RadzenDropDown @onclick:preventDefault="true" TextProperty="Text" ValueProperty="Value" Style="width: 90px" InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Column.Title + Grid.LogicalOperatorArialLabel + (Column.LogicalFilterOperator == LogicalFilterOperator.And ? Grid.AndOperatorText : Grid.OrOperatorText) }})"
|
||||
<RadzenDropDown @onclick:preventDefault="true" TextProperty="Text" ValueProperty="Value" Style="width: 90px" InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Column.Title + Grid.LogicalOperatorAriaLabel + (Column.LogicalFilterOperator == LogicalFilterOperator.And ? Grid.AndOperatorText : Grid.OrOperatorText) }})"
|
||||
Data="@(Enum.GetValues(typeof(LogicalFilterOperator)).Cast<LogicalFilterOperator>().Select(t => new { Text = t == LogicalFilterOperator.And ? Grid.AndOperatorText : Grid.OrOperatorText, Value = t }))" TValue="LogicalFilterOperator" Value="@Column.LogicalFilterOperator" Change="@(args => Column.SetLogicalFilterOperator((LogicalFilterOperator)args))" />
|
||||
|
||||
<RadzenDropDown InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Grid.SecondFilterOperatorArialLabel + Column.GetFilterOperatorText(Column.GetSecondFilterOperator()) }})" @onclick:preventDefault="true" Data="@(Column.GetFilterOperators().Select(t => new { Value = Column.GetFilterOperatorText(t), Key = t }))" TextProperty="Value" ValueProperty="Key" TValue="FilterOperator" Value="@Column.GetSecondFilterOperator()" Change="@(args => Column.SetSecondFilterOperator((FilterOperator)args))" />
|
||||
<RadzenDropDown InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Grid.SecondFilterOperatorAriaLabel + Column.GetFilterOperatorText(Column.GetSecondFilterOperator()) }})" @onclick:preventDefault="true" Data="@(Column.GetFilterOperators().Select(t => new { Value = Column.GetFilterOperatorText(t), Key = t }))" TextProperty="Value" ValueProperty="Key" TValue="FilterOperator" Value="@Column.GetSecondFilterOperator()" Change="@(args => Column.SetSecondFilterOperator((FilterOperator)args))" />
|
||||
@if (Column.SecondFilterValueTemplate != null)
|
||||
{
|
||||
@Column.SecondFilterValueTemplate(Column)
|
||||
}
|
||||
else if (PropertyAccess.IsNullableEnum(Column.FilterPropertyType) || PropertyAccess.IsEnum(Column.FilterPropertyType))
|
||||
{
|
||||
<RadzenDropDown AllowClear="false" AllowFiltering="false" TValue="@object" InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Column.Title + Grid.SecondFilterValueArialLabel }})"
|
||||
Value=@Column.GetSecondFilterValue() Multiple="false" Placeholder="@Grid.EnumFilterSelectText" TextProperty="Text" ValueProperty="Value" Data=@EnumExtensions.EnumAsKeyValuePair(Nullable.GetUnderlyingType(Column.FilterPropertyType) ?? Column.FilterPropertyType)
|
||||
<RadzenDropDown Disabled="@(!Column.CanSetFilterValue(false))" AllowClear="false" AllowFiltering="false" TValue="@object" InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Column.Title + Grid.SecondFilterValueAriaLabel }})"
|
||||
Value=@Column.GetSecondFilterValue() Multiple="false" Placeholder="@Grid.EnumFilterSelectText" TextProperty="Text" ValueProperty="Value" Data=@EnumExtensions.EnumAsKeyValuePair(Nullable.GetUnderlyingType(Column.FilterPropertyType) ?? Column.FilterPropertyType, Grid.EnumFilterTranslationFunc)
|
||||
Change="@(args => Column.SetFilterValue(args,false))" />
|
||||
}
|
||||
else if (PropertyAccess.IsNumeric(Column.FilterPropertyType))
|
||||
@@ -124,27 +132,48 @@
|
||||
}
|
||||
else if (PropertyAccess.IsDate(Column.FilterPropertyType))
|
||||
{
|
||||
<RadzenDatePicker TValue="@object" InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Column.Title + Grid.SecondFilterValueArialLabel + Column.GetSecondFilterValue() }})"
|
||||
<RadzenDatePicker Disabled="@(!Column.CanSetFilterValue(false))" TValue="@object" InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Column.Title + Grid.SecondFilterValueAriaLabel + Column.GetSecondFilterValue() }})"
|
||||
ShowTime="@Column.ShowTimeForDateTimeFilter()" ShowTimeOkButton="true" DateFormat="@Grid.getFilterDateFormat(Column)"
|
||||
Value="@Column.GetSecondFilterValue()" Change="@(args => Column.SetFilterValue(args.Value, false))" AllowInput=@(Grid.AllowFilterDateInput) />
|
||||
Value="@Column.GetSecondFilterValue()" Change="@(args => Column.SetFilterValue(PropertyAccess.IsDateOnly(Column.FilterPropertyType) ? PropertyAccess.DateOnlyFromDateTime(args.Value) : args.Value, false))" AllowInput=@(Grid.AllowFilterDateInput) />
|
||||
|
||||
}
|
||||
else if (Column.FilterPropertyType == typeof(bool) || Column.FilterPropertyType == typeof(bool?))
|
||||
{
|
||||
<RadzenCheckBox InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Column.Title + Grid.SecondFilterValueArialLabel + Column.GetSecondFilterValue() }})" TriState="true" TValue="@object" Value="@Column.GetSecondFilterValue()" Change="@(args => { Column.SetFilterValue(args, false); Grid.SaveSettings(); })" />
|
||||
<RadzenCheckBox Disabled="@(!Column.CanSetFilterValue(false))" InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Column.Title + Grid.SecondFilterValueAriaLabel + Column.GetSecondFilterValue() }})" TriState="true" TValue="@object" Value="@Column.GetSecondFilterValue()" Change="@(args => { Column.SetFilterValue(args, false); Grid.SaveSettings(); })" />
|
||||
}
|
||||
else
|
||||
{
|
||||
<RadzenTextBox id="@($"{getColumnPopupID()}-sf2")" aria-label=@(Column.Title + Grid.SecondFilterValueArialLabel + Column.GetSecondFilterValue()) Value="@($"{Column.GetSecondFilterValue()}")" Change="@(args => Column.SetFilterValue(args, false))" />
|
||||
<RadzenTextBox Disabled="@(!Column.CanSetFilterValue(false))" id="@($"{getColumnPopupID()}-sf2")" aria-label=@(Column.Title + Grid.SecondFilterValueAriaLabel + Column.GetSecondFilterValue()) Value="@($"{Column.GetSecondFilterValue()}")" Change="@(args => Column.SetFilterValue(args, false))" />
|
||||
}
|
||||
}
|
||||
</form>
|
||||
else
|
||||
{
|
||||
<RadzenListBox AllowVirtualization="@Column.AllowCheckBoxListVirtualization" AllowClear="true" Multiple="true" Style="height: 300px"
|
||||
TValue="IEnumerable<object>" Value=@Column.GetFilterValue() Change="@ListBoxChange"
|
||||
Data=@filterValues Count=@filterValuesCount LoadData="@LoadFilterValues"
|
||||
AllowFiltering="@(!string.IsNullOrEmpty(Column.GetFilterProperty()) && PropertyAccess.GetPropertyType(typeof(TItem), Column.GetFilterProperty()) == typeof(string))"
|
||||
Disabled="@(!Column.CanSetFilterValue())" FilterCaseSensitivity="FilterCaseSensitivity.CaseInsensitive"
|
||||
InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Column.Title + Grid.FilterValueAriaLabel + Column.GetFilterValue() }})">
|
||||
<Template>
|
||||
@if (context as Enum != null)
|
||||
{
|
||||
@EnumExtensions.GetDisplayDescription(context as Enum)
|
||||
}
|
||||
else
|
||||
{
|
||||
@(!string.IsNullOrEmpty(Column.FormatString) ? string.Format(Column.FormatProvider ?? Grid?.Culture ?? CultureInfo.CurrentCulture, Column.FormatString, context ?? "") : Convert.ToString(context ?? "", Grid?.Culture ?? CultureInfo.CurrentCulture))
|
||||
}
|
||||
</Template>
|
||||
</RadzenListBox>
|
||||
}
|
||||
</form>
|
||||
}
|
||||
</div>
|
||||
@if (Column.FilterTemplate == null)
|
||||
{
|
||||
<div class="rz-grid-filter-buttons">
|
||||
<RadzenButton ButtonStyle="ButtonStyle.Secondary" Text=@Grid.ClearFilterText Click="@ClearFilter" />
|
||||
<RadzenButton form="@($"{getColumnPopupID()}-form")" ButtonType="ButtonType.Submit" ButtonStyle="ButtonStyle.Primary" Text=@Grid.ApplyFilterText />
|
||||
<RadzenButton ButtonStyle="ButtonStyle.Base" class="rz-clear-filter" Click="@ClearFilter" Text=@Grid.ClearFilterText title="@Grid.ClearFilterText" />
|
||||
<RadzenButton ButtonStyle="ButtonStyle.Primary" class="rz-apply-filter" form="@($"{getColumnPopupID()}-form")" ButtonType="ButtonType.Submit" Text=@Grid.ApplyFilterText title="@Grid.ApplyFilterText" />
|
||||
</div>
|
||||
}
|
||||
</Popup>
|
||||
@@ -166,6 +195,113 @@ else
|
||||
Radzen.Blazor.Rendering.Popup popup;
|
||||
ElementReference filterButton;
|
||||
|
||||
int filterValuesCount;
|
||||
internal IEnumerable filterValues;
|
||||
string loadDataArgsString;
|
||||
|
||||
async Task LoadFilterValues(LoadDataArgs loadDataArgs)
|
||||
{
|
||||
var property = Column.Property != Column.FilterProperty && !string.IsNullOrEmpty(Column.FilterProperty) ? Column.Property :
|
||||
Column.GetFilterProperty();
|
||||
|
||||
var propertyType = PropertyAccess.GetPropertyType(typeof(TItem), property);
|
||||
|
||||
if (property.IndexOf(".") != -1)
|
||||
{
|
||||
property = $"np({property})";
|
||||
}
|
||||
|
||||
if (propertyType == typeof(string))
|
||||
{
|
||||
property = $@"({property} == null ? """" : {property})";
|
||||
}
|
||||
|
||||
var loadDataArgsString = $"{loadDataArgs.Skip}|{loadDataArgs.Top}{loadDataArgs.Filter}";
|
||||
|
||||
if (Column.Grid.LoadColumnFilterData.HasDelegate)
|
||||
{
|
||||
var args = new DataGridLoadColumnFilterDataEventArgs<TItem>() { Column = Column, Filter = loadDataArgs.Filter };
|
||||
|
||||
await Column.Grid.LoadColumnFilterData.InvokeAsync(args);
|
||||
|
||||
filterValues = args.Data.AsQueryable().Select(DynamicLinqCustomTypeProvider.ParsingConfig, property).Distinct().Cast(propertyType ?? typeof(object));
|
||||
filterValuesCount = args.Count;
|
||||
}
|
||||
else if(!string.IsNullOrEmpty(property) && (filterValues == null || this.loadDataArgsString != loadDataArgsString) && Column.Grid.Data != null)
|
||||
{
|
||||
this.loadDataArgsString = loadDataArgsString;
|
||||
|
||||
IQueryable query;
|
||||
|
||||
if(!string.IsNullOrEmpty(loadDataArgs.Filter))
|
||||
{
|
||||
query = Radzen.QueryableExtension.Where(Column.Grid.Data.AsQueryable().Where<TItem>(Column.Grid.allColumns.Where(c => c != Column)),
|
||||
property, loadDataArgs.Filter, StringFilterOperator.Contains, FilterCaseSensitivity.CaseInsensitive);
|
||||
}
|
||||
else
|
||||
{
|
||||
query = Column.Grid.Data.AsQueryable().Where<TItem>(Column.Grid.allColumns.Where(c => c != Column));
|
||||
}
|
||||
|
||||
if (Column.Property != Column.FilterProperty && !string.IsNullOrEmpty(Column.FilterProperty))
|
||||
{
|
||||
query = query
|
||||
.SelectMany(DynamicLinqCustomTypeProvider.ParsingConfig, property)
|
||||
.Select(DynamicLinqCustomTypeProvider.ParsingConfig, Column.FilterProperty)
|
||||
.Distinct().OrderBy("it").Cast(typeof(object));
|
||||
}
|
||||
else
|
||||
{
|
||||
query = query.Select(DynamicLinqCustomTypeProvider.ParsingConfig, property).Distinct().OrderBy("it").Cast(propertyType ?? typeof(object));
|
||||
}
|
||||
|
||||
filterValuesCount = query.Count();
|
||||
|
||||
if(loadDataArgs.Skip != null)
|
||||
{
|
||||
query = query.Skip(loadDataArgs.Skip.Value);
|
||||
}
|
||||
|
||||
if(loadDataArgs.Top != null)
|
||||
{
|
||||
query = query.Take(loadDataArgs.Top.Value);
|
||||
}
|
||||
|
||||
filterValues = query.Select("it => it.ToString() == string.Empty ? null : it");
|
||||
|
||||
if (!Column.AllowCheckBoxListVirtualization)
|
||||
{
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ListBoxChange(object args)
|
||||
{
|
||||
var enumerable = args as IEnumerable;
|
||||
|
||||
Type propertyType = null;
|
||||
|
||||
if (Column.Property != Column.FilterProperty && !string.IsNullOrEmpty(Column.FilterProperty))
|
||||
{
|
||||
var collectionType = PropertyAccess.GetPropertyType(typeof(TItem), Column.Property);
|
||||
if (collectionType != null && collectionType.IsGenericType)
|
||||
{
|
||||
var itemType = collectionType.GenericTypeArguments.FirstOrDefault();
|
||||
if(itemType != null)
|
||||
{
|
||||
propertyType = PropertyAccess.GetPropertyType(itemType, Column.FilterProperty);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
propertyType = PropertyAccess.GetPropertyType(typeof(TItem), Column.GetFilterProperty());
|
||||
}
|
||||
|
||||
Column.SetFilterValue(enumerable.Cast<object>().Any() ? propertyType != null ? enumerable.AsQueryable().Cast(propertyType) : enumerable : null);
|
||||
}
|
||||
|
||||
string getFilterOpen()
|
||||
{
|
||||
return Grid.FilterPopupRenderMode == PopupRenderMode.Initial ? $"Radzen.togglePopup(this, '{getColumnPopupID()}', false, null, null, true, true)" : "";
|
||||
@@ -176,6 +312,11 @@ else
|
||||
if (Grid.FilterPopupRenderMode == PopupRenderMode.OnDemand)
|
||||
{
|
||||
await popup.ToggleAsync(filterButton);
|
||||
|
||||
Grid.allColumns
|
||||
.Where(c => c != Column && c.headerCell != null)
|
||||
.Select(c => c.headerCell).ToList()
|
||||
.ForEach(cell => InvokeAsync(cell.CloseFilter));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,7 +380,7 @@ else
|
||||
private string getFilterIconCss(RadzenDataGridColumn<TItem> column)
|
||||
{
|
||||
var additionalStyle = Column.HasActiveFilter() ? "rz-grid-filter-active" : "";
|
||||
return $"rzi rz-grid-filter-icon {additionalStyle}";
|
||||
return $"notranslate rzi rz-grid-filter-icon {additionalStyle}";
|
||||
}
|
||||
|
||||
private Task OnSortKeyPressed(KeyboardEventArgs args)
|
||||
@@ -311,6 +452,7 @@ else
|
||||
if (key == "Escape")
|
||||
{
|
||||
await CloseFilter();
|
||||
await ClearFilter();
|
||||
await Grid.GetJSRuntime().InvokeVoidAsync("Radzen.focusElement", Grid.GridId());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
@implements IRadzenForm
|
||||
<CascadingValue Value=@EditContext>
|
||||
<CascadingValue Value=this>
|
||||
@{var rowArgs = Grid?.RowAttributes(Item); }
|
||||
@{var rowArgs = Grid?.RowAttributes(Item, Index); }
|
||||
@{var firstLevel = Grid.AllowCompositeDataCells ? 0 : Grid.deepestChildColumnLevel; }
|
||||
@for(var i = firstLevel; i < Grid.deepestChildColumnLevel + 1; i++)
|
||||
{
|
||||
@@ -27,7 +27,7 @@
|
||||
<span class="rz-column-title"></span>
|
||||
@if (rowArgs.Item1.Expandable)
|
||||
{
|
||||
<a aria-label="@Grid.ExpandChildItemAriaLabel" @onclick:preventDefault="true" @onclick="@(_ => Grid.ExpandItem(Item))" @onclick:stopPropagation>
|
||||
<a id="@(Grid.GridId() + Item.GetHashCode())" aria-label="@Grid.ExpandChildItemAriaLabel" @onclick:preventDefault="true" @onclick="@(_ => Grid.ExpandItem(Item))" @onclick:stopPropagation>
|
||||
<span class="@(Grid.ExpandedItemStyle(Item))"></span>
|
||||
</a>
|
||||
}
|
||||
|
||||
@@ -10,15 +10,29 @@
|
||||
}
|
||||
@if (Data != null)
|
||||
{
|
||||
@if (!WrapItems)
|
||||
{
|
||||
@DrawDataListRows()
|
||||
}
|
||||
else
|
||||
@if (!ShowEmptyMessage || Count > 0 && (AllowVirtualization ? Count > 0 : true) || LoadData.HasDelegate && Data.Count() > 0)
|
||||
{
|
||||
@if (!WrapItems)
|
||||
{
|
||||
@DrawDataListRows()
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="rz-g">
|
||||
@DrawDataListRows()
|
||||
</div>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@if (EmptyTemplate != null)
|
||||
{
|
||||
@EmptyTemplate
|
||||
}
|
||||
else
|
||||
{
|
||||
<span style="white-space: normal">@EmptyText</span>
|
||||
}
|
||||
}
|
||||
}
|
||||
@if (IsLoading)
|
||||
@@ -31,13 +45,13 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<i class="rzi-circle-o-notch"></i>
|
||||
<i class="notranslate rzi-circle-o-notch"></i>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
@if (AllowPaging && PagerPosition.HasFlag(PagerPosition.Bottom))
|
||||
{
|
||||
<RadzenPager HorizontalAlign="@PagerHorizontalAlign" AlwaysVisible="@PagerAlwaysVisible" @ref="bottomPager" Count="@Count" PageSize="@PageSize" PageNumbersCount="@PageNumbersCount" PageChanged="@OnPageChanged" PageSizeChanged="@OnPageSizeChanged" PageSizeOptions="@PageSizeOptions" ShowPagingSummary="@ShowPagingSummary" PagingSummaryFormat="@PagingSummaryFormat" PageSizeText="@PageSizeText" class="rz-paginator-bottom" Density="@Density" FirstPageTitle="@FirstPageTitle" FirstPageAriaLabel="@FirstPageAriaLabel" PrevPageAriaLabel="@PrevPageAriaLabel" PrevPageTitle="@PrevPageTitle" NextPageAriaLabel="@NextPageAriaLabel" NextPageTitle="@NextPageTitle" LastPageAriaLabel="@LastPageAriaLabel" LastPageTitle="@LastPageTitle" PageAriaLabelFormat="@PageAriaLabelFormat" PageTitleFormat="@PageTitleFormat" PrevPageLabel="@PrevPageLabel" NextPageLabel="@NextPageLabel" />
|
||||
<RadzenPager HorizontalAlign="@PagerHorizontalAlign" AlwaysVisible="@PagerAlwaysVisible" @ref="bottomPager" Count="@Count" PageSize="@PageSize" PageNumbersCount="@PageNumbersCount" PageChanged="@OnPageChanged" PageSizeChanged="@OnPageSizeChanged" PageSizeOptions="@PageSizeOptions" ShowPagingSummary="@ShowPagingSummary" PagingSummaryFormat="@PagingSummaryFormat" PageSizeText="@PageSizeText" class="rz-pager-bottom" Density="@Density" FirstPageTitle="@FirstPageTitle" FirstPageAriaLabel="@FirstPageAriaLabel" PrevPageAriaLabel="@PrevPageAriaLabel" PrevPageTitle="@PrevPageTitle" NextPageAriaLabel="@NextPageAriaLabel" NextPageTitle="@NextPageTitle" LastPageAriaLabel="@LastPageAriaLabel" LastPageTitle="@LastPageTitle" PageAriaLabelFormat="@PageAriaLabelFormat" PageTitleFormat="@PageTitleFormat" PrevPageLabel="@PrevPageLabel" NextPageLabel="@NextPageLabel" />
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -27,6 +27,9 @@ namespace Radzen.Blazor
|
||||
/// </RadzenDataList>
|
||||
/// </code>
|
||||
/// </example>
|
||||
#if NET6_0_OR_GREATER
|
||||
[CascadingTypeParameter(nameof(TItem))]
|
||||
#endif
|
||||
public partial class RadzenDataList<TItem> : PagedDataBoundComponent<TItem>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
@@ -35,13 +38,43 @@ namespace Radzen.Blazor
|
||||
return "rz-datalist-content";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether DataList should show empty message.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool ShowEmptyMessage { get; set; }
|
||||
|
||||
private string _emptyText = "No records to display.";
|
||||
/// <summary>
|
||||
/// Gets or sets the empty text shown when Data is empty collection.
|
||||
/// </summary>
|
||||
/// <value>The empty text.</value>
|
||||
[Parameter]
|
||||
public string EmptyText
|
||||
{
|
||||
get { return _emptyText; }
|
||||
set
|
||||
{
|
||||
if (value != _emptyText)
|
||||
{
|
||||
_emptyText = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the empty template shown when Data is empty collection.
|
||||
/// </summary>
|
||||
/// <value>The empty template.</value>
|
||||
[Parameter]
|
||||
public RenderFragment EmptyTemplate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to wrap items.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if wrap items; otherwise, <c>false</c>.</value>
|
||||
[Parameter]
|
||||
public bool WrapItems { get; set; }
|
||||
#if NET5_0_OR_GREATER
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is virtualized.
|
||||
@@ -85,12 +118,10 @@ namespace Radzen.Blazor
|
||||
|
||||
return new Microsoft.AspNetCore.Components.Web.Virtualization.ItemsProviderResult<TItem>(virtualDataItems, totalItemsCount);
|
||||
}
|
||||
#endif
|
||||
RenderFragment DrawDataListRows()
|
||||
{
|
||||
return new RenderFragment(builder =>
|
||||
{
|
||||
#if NET5_0_OR_GREATER
|
||||
if (AllowVirtualization)
|
||||
{
|
||||
builder.OpenComponent(0, typeof(Microsoft.AspNetCore.Components.Web.Virtualization.Virtualize<TItem>));
|
||||
@@ -112,9 +143,6 @@ namespace Radzen.Blazor
|
||||
{
|
||||
DrawRows(builder);
|
||||
}
|
||||
#else
|
||||
DrawRows(builder);
|
||||
#endif
|
||||
});
|
||||
}
|
||||
|
||||
@@ -124,12 +152,11 @@ namespace Radzen.Blazor
|
||||
public async override Task Reload()
|
||||
{
|
||||
await base.Reload();
|
||||
#if NET5_0_OR_GREATER
|
||||
|
||||
if (virtualize != null)
|
||||
{
|
||||
await virtualize.RefreshDataAsync();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
internal void DrawRows(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder)
|
||||
|
||||
@@ -10,50 +10,52 @@
|
||||
@implements IRadzenFormComponent
|
||||
@if (Visible)
|
||||
{
|
||||
<div @ref="@Element" @attributes="Attributes" class="@GetCssClass()" style="@getStyle()" id="@GetId()">
|
||||
<div @ref="@Element" @attributes="Attributes" class="@($"rz-datepicker{(Disabled ? " rz-state-disabled" : "")}") @GetCssClass()" style="@getStyle()" id="@GetId()">
|
||||
@if (!Inline)
|
||||
{
|
||||
<span class="@($"rz-calendar rz-calendar-w-btn{(Disabled ? " rz-state-disabled" : "")}")" style="width:100%">
|
||||
<input @ref="@input" @attributes="InputAttributes" disabled="@Disabled" readonly="@IsReadonly" value="@FormattedValue" tabindex="@(Disabled ? "-1" : $"{TabIndex}")"
|
||||
@onchange="@ParseDate" autocomplete="off" type="text" name="@Name" @onkeydown="@(args => OnKeyPress(args))" @onkeydown:preventDefault=preventKeyPress @onkeydown:stopPropagation
|
||||
class="rz-inputtext @InputClass @(IsReadonly ? "rz-readonly" : "")" id="@Name" placeholder="@Placeholder" />
|
||||
@if (ShowButton)
|
||||
{
|
||||
<button @onmousedown=@OnToggle class="@($"rz-datepicker-trigger rz-calendar-button rz-button rz-button-icon-only{(Disabled ? " rz-state-disabled" : "")}")" tabindex="-1" type="button">
|
||||
<span aria-hidden="true" class="@ButtonClasses"></span><span class="rz-button-text"></span>
|
||||
</button>
|
||||
}
|
||||
@if (AllowClear && HasValue)
|
||||
{
|
||||
<i class="rz-dropdown-clear-icon rzi rzi-times" @onclick="@Clear" @onclick:stopPropagation="true"></i>
|
||||
}
|
||||
</span>
|
||||
<input @ref="@input" @attributes="InputAttributes" disabled="@Disabled" readonly="@IsReadonly" value="@FormattedValue" tabindex="@(Disabled ? "-1" : $"{TabIndex}")"
|
||||
@onchange="@ParseDate" autocomplete="off" type="text" name="@Name" @onkeydown="@(args => OnKeyPress(args))" @onkeydown:preventDefault=preventKeyPress @onkeydown:stopPropagation
|
||||
class="rz-inputtext @InputClass @(IsReadonly ? "rz-readonly" : "") @(!ShowButton ? "rz-input-trigger" : "")" id="@Name" placeholder="@Placeholder" />
|
||||
@if (ShowButton)
|
||||
{
|
||||
<button aria-label="@ToggleAriaLabel" @onmousedown=@OnToggle class="@($"rz-datepicker-trigger rz-button rz-button-icon-only{(Disabled ? " rz-state-disabled" : "")} {ButtonClass}")" tabindex="-1" type="button">
|
||||
<span aria-hidden="true" class="@ButtonClasses"></span><span class="rz-button-text"></span>
|
||||
</button>
|
||||
}
|
||||
@if (AllowClear && HasValue)
|
||||
{
|
||||
<i class="notranslate rz-dropdown-clear-icon rzi rzi-times" @onclick="@Clear" @onclick:stopPropagation="true"></i>
|
||||
}
|
||||
}
|
||||
|
||||
<Popup id="@PopupID" Lazy=@(PopupRenderMode == PopupRenderMode.OnDemand) @ref=@popup style=@PopupStyle class="@($"{(Inline ? "rz-datepicker-inline " : "")}rz-datepicker")">
|
||||
<div class="rz-datepicker-group" @onkeydown="@OnPopupKeyDown">
|
||||
<Popup id="@PopupID" Lazy=@(PopupRenderMode == PopupRenderMode.OnDemand) @ref=@popup style=@PopupStyle class="@($"{(Inline ? "rz-datepicker-inline-container " : "rz-datepicker-popup-container ")}")">
|
||||
<div class="rz-calendar" @onkeydown="@OnPopupKeyDown">
|
||||
@if (!TimeOnly)
|
||||
{
|
||||
<div class="rz-datepicker-header">
|
||||
<a tabindex="-1" aria-label="@PrevMonthAriaLabel" @onclick:preventDefault="true" class="rz-datepicker-prev" @onclick="@(async () => { if (!Disabled) { try { if(CurrentDate.AddMonths(-1).Year >= YearFrom) {CurrentDate = CurrentDate.AddMonths(-1);}} catch (ArgumentOutOfRangeException) {}} })">
|
||||
<span class="rz-datepicker-prev-icon rzi rzi-chevron-left"></span>
|
||||
<div class="rz-calendar-header">
|
||||
<a id="@(GetId() + "pm")" tabindex="-1" aria-label="@PrevMonthAriaLabel" @onclick:preventDefault="true" class="rz-button rz-button-md rz-variant-text rz-button-icon-only rz-secondary rz-shade-default rz-calendar-prev" @onclick="@(async () => { if (!Disabled) { try { if(CurrentDate.AddMonths(-1).Year >= YearFrom) {CurrentDate = CurrentDate.AddMonths(-1);}} catch (ArgumentOutOfRangeException) {}} })">
|
||||
<span class="notranslate rzi rz-calendar-prev-icon"></span>
|
||||
</a>
|
||||
<a tabindex="-1" aria-label="@NextMonthAriaLabel" @onclick:preventDefault="true" class="rz-datepicker-next" @onclick="@(async () => { if (!Disabled) { try { if(CurrentDate.AddMonths(1).Year <= YearTo) {CurrentDate = CurrentDate.AddMonths(1);}} catch (ArgumentOutOfRangeException) {} } })">
|
||||
<span class="rz-datepicker-next-icon rzi rzi-chevron-right"></span>
|
||||
<a id="@(GetId() + "nm")" tabindex="-1" aria-label="@NextMonthAriaLabel" @onclick:preventDefault="true" class="rz-button rz-button-md rz-variant-text rz-button-icon-only rz-secondary rz-shade-default rz-calendar-next" @onclick="@(async () => { if (!Disabled) { try { if(CurrentDate.AddMonths(1).Year <= YearTo) {CurrentDate = CurrentDate.AddMonths(1);}} catch (ArgumentOutOfRangeException) {} } })">
|
||||
<span class="notranslate rzi rz-calendar-next-icon"></span>
|
||||
</a>
|
||||
<div class="rz-datepicker-title">
|
||||
<RadzenDropDown @ref="monthDropDown" Style="height:auto;width:120px;margin-top:5px;text-align:left;" TabIndex="@TabIndex"
|
||||
TValue="int" Value="@CurrentDate.Month" Disabled="@Disabled" Data="@months" TextProperty="Name" ValueProperty="Value"
|
||||
Change="@((args) => { SetMonth(int.Parse(args.ToString())); })"/>
|
||||
<RadzenDropDown @ref="yearDropDown" Style="height:auto;width:80px;margin-top:5px;text-align:left;" TabIndex="@TabIndex"
|
||||
TValue="int" Value="@CurrentDate.Year" Disabled="@Disabled" Data="@years" TextProperty="Name" ValueProperty="Value"
|
||||
Change="@((args) => { SetYear(int.Parse(args.ToString())); })"/>
|
||||
<div class="rz-calendar-title">
|
||||
<RadzenDropDown @ref="monthDropDown" class="rz-calendar-month-dropdown" TabIndex="@TabIndex"
|
||||
TValue="int" Value="@CurrentDate.Month" Disabled="@Disabled" Data="@months" TextProperty="Name" ValueProperty="Value"
|
||||
Change="@((args) => { SetMonth(int.Parse(args.ToString())); })"/>
|
||||
<RadzenDropDown @ref="yearDropDown" class="rz-calendar-year-dropdown" TabIndex="@TabIndex"
|
||||
TValue="int" Value="@CurrentDate.Year" Disabled="@Disabled" Data="@years" TextProperty="Name" ValueProperty="Value"
|
||||
Change="@((args) => { SetYear(int.Parse(args.ToString())); })">
|
||||
<Template>
|
||||
@Culture.Calendar.GetYear(new DateTime(context.Value,1,1))
|
||||
</Template>
|
||||
</RadzenDropDown>
|
||||
</div>
|
||||
</div>
|
||||
@if(ShowDays)
|
||||
{
|
||||
<div class="rz-datepicker-calendar-container" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" @onkeydown="@(args => OnCalendarKeyPress(args))" @onkeydown:preventDefault=preventKeyPress @onkeydown:stopPropagation>
|
||||
<table class="rz-datepicker-calendar" style="@(Inline ? "" : "width:100%")">
|
||||
<div class="rz-calendar-view-container" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" @onkeydown="@(args => OnCalendarKeyPress(args))" @onkeydown:preventDefault=preventKeyPress @onkeydown:stopPropagation>
|
||||
<table class="rz-calendar-view rz-calendar-month-view" style="@(Inline ? "" : "width:100%")">
|
||||
<thead>
|
||||
<tr>
|
||||
@if (ShowCalendarWeek)
|
||||
@@ -79,7 +81,7 @@
|
||||
<tr>
|
||||
@if (ShowCalendarWeek)
|
||||
{
|
||||
<td class="rz-datepicker-other-month rz-datepicker-week-number">@Culture.Calendar.GetWeekOfYear(new DateTime(CurrentDate.Year, CurrentDate.Month, 1).AddDays(i * 7), Culture.DateTimeFormat.CalendarWeekRule, Culture.DateTimeFormat.FirstDayOfWeek)</td>
|
||||
<td class="rz-calendar-other-month rz-calendar-week-number">@Culture.Calendar.GetWeekOfYear(new DateTime(CurrentDate.Year, CurrentDate.Month, 1).AddDays(i * 7), Culture.DateTimeFormat.CalendarWeekRule, Culture.DateTimeFormat.FirstDayOfWeek)</td>
|
||||
}
|
||||
@for (int j = 0; j < 7; j++)
|
||||
{
|
||||
@@ -91,7 +93,7 @@
|
||||
DateTime date = StartDate.AddDays(dayNumber++);
|
||||
var dateArgs = DateAttributes(date);
|
||||
|
||||
<td @attributes="@(dateArgs.Attributes)" class="@GetDayCssClass(date, dateArgs)" @onmouseup=@Close
|
||||
<td @attributes="@(dateArgs.Attributes)" class="@GetDayCssClass(date, dateArgs)"
|
||||
@onclick="@(async () => { if (!Disabled && !dateArgs.Disabled) { await SetDay(date); } })">
|
||||
<span class=@GetDayCssClass(date, dateArgs, false)>@date.Day</span>
|
||||
</td>
|
||||
@@ -132,18 +134,18 @@
|
||||
@if (HourFormat == "12")
|
||||
{
|
||||
<div class="rz-ampm-picker">
|
||||
<a tabindex="@(Disabled ? "-1" : $"{TabIndex}")"aria-label="@ToggleAmPmAriaLabel" @onclick:preventDefault="true" @onclick="@ToggleAmPm">
|
||||
<span class="rzi rzi-chevron-up"></span>
|
||||
<a id="@(GetId() + "ampmup")" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" aria-label="@ToggleAmPmAriaLabel" @onclick:preventDefault="true" @onclick="@ToggleAmPm">
|
||||
<span class="notranslate rzi rzi-chevron-up"></span>
|
||||
</a>
|
||||
<span>@CurrentDate.ToString("tt")</span>
|
||||
<a tabindex="@(Disabled ? "-1" : $"{TabIndex}")" aria-label="@ToggleAmPmAriaLabel" @onclick:preventDefault="true" @onclick="@ToggleAmPm">
|
||||
<span class="rzi rzi-chevron-down"></span>
|
||||
<a id="@(GetId() + "ampmdown")" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" aria-label="@ToggleAmPmAriaLabel" @onclick:preventDefault="true" @onclick="@ToggleAmPm">
|
||||
<span class="notranslate rzi rzi-chevron-down"></span>
|
||||
</a>
|
||||
</div>
|
||||
}
|
||||
@if (ShowTimeOkButton)
|
||||
{
|
||||
<button type="button" class="rz-button rz-button-md rz-secondary" tabindex="0" @onclick="@OkClick">
|
||||
<button aria-label="@OkAriaLabel" type="button" class="rz-button rz-button-md rz-secondary" tabindex="0" @onclick="@(args => OkClick())">
|
||||
<span class="rz-button-text">Ok</span>
|
||||
</button>
|
||||
}
|
||||
|
||||
@@ -39,6 +39,20 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public string CalendarWeekTitle { get; set; } = "#";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the toggle popup aria label text.
|
||||
/// </summary>
|
||||
/// <value>The toggle popup aria label text.</value>
|
||||
[Parameter]
|
||||
public string ToggleAriaLabel { get; set; } = "Toggle";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the OK button aria label text.
|
||||
/// </summary>
|
||||
/// <value>The OK button aria label text.</value>
|
||||
[Parameter]
|
||||
public string OkAriaLabel { get; set; } = "Ok";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the previous month aria label text.
|
||||
/// </summary>
|
||||
@@ -137,6 +151,7 @@ namespace Radzen.Blazor
|
||||
{
|
||||
if (ShowTimeOkButton)
|
||||
{
|
||||
DateTimeValue = newValue;
|
||||
CurrentDate = newValue;
|
||||
}
|
||||
else
|
||||
@@ -155,9 +170,9 @@ namespace Radzen.Blazor
|
||||
|
||||
if (v < 0)
|
||||
{
|
||||
newHour = 23;
|
||||
newMinute = 59;
|
||||
newSecond = 59;
|
||||
newHour = string.IsNullOrEmpty(HoursStep) ? 23 : 0;
|
||||
newMinute = string.IsNullOrEmpty(MinutesStep) ? 59 : 0;
|
||||
newSecond = string.IsNullOrEmpty(SecondsStep) ? 59 : 0;
|
||||
}
|
||||
|
||||
var newValue = new DateTime(CurrentDate.Year, CurrentDate.Month, CurrentDate.Day, newHour > 23 || newHour < 0 ? 0 : newHour, newMinute, newSecond);
|
||||
@@ -182,9 +197,12 @@ namespace Radzen.Blazor
|
||||
await UpdateValueFromTime(newValue);
|
||||
}
|
||||
|
||||
async Task OkClick()
|
||||
async Task OkClick(bool shouldClose = true)
|
||||
{
|
||||
Close();
|
||||
if (shouldClose)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
if(Min.HasValue && CurrentDate < Min.Value || Max.HasValue && CurrentDate > Max.Value)
|
||||
{
|
||||
@@ -216,12 +234,12 @@ namespace Radzen.Blazor
|
||||
|
||||
if (monthDropDown != null)
|
||||
{
|
||||
await monthDropDown.ClosePopup();
|
||||
await monthDropDown.PopupClose();
|
||||
}
|
||||
|
||||
if (yearDropDown != null)
|
||||
{
|
||||
await yearDropDown.ClosePopup();
|
||||
await yearDropDown.PopupClose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -298,6 +316,12 @@ namespace Radzen.Blazor
|
||||
/// <value>The input CSS class.</value>
|
||||
[Parameter]
|
||||
public string InputClass { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the button CSS class.
|
||||
/// </summary>
|
||||
/// <value>The button CSS class.</value>
|
||||
[Parameter]
|
||||
public string ButtonClass { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Minimum Selectable Date.
|
||||
@@ -679,7 +703,7 @@ namespace Radzen.Blazor
|
||||
|
||||
private string ButtonClasses
|
||||
{
|
||||
get => $"rz-button-icon-left rzi rzi-{(TimeOnly ? "time" : "calendar")}";
|
||||
get => $"notranslate rz-button-icon-left rzi rzi-{(TimeOnly ? "time" : "calendar")}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -890,7 +914,7 @@ namespace Radzen.Blazor
|
||||
|
||||
private string getStyle()
|
||||
{
|
||||
return $"display: inline-block;{(Inline ? "overflow:auto;" : "")}{(Style != null ? Style : "")}";
|
||||
return $"{(Inline ? "overflow:auto;" : "")}{(Style != null ? Style : "")}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -920,11 +944,11 @@ namespace Radzen.Blazor
|
||||
{
|
||||
if (Inline)
|
||||
{
|
||||
return "white-space: nowrap";
|
||||
return "";
|
||||
}
|
||||
else
|
||||
{
|
||||
return $"width: 320px; {contentStyle}";
|
||||
return $"{contentStyle}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -936,6 +960,10 @@ namespace Radzen.Blazor
|
||||
DateTimeOffset? offset = DateTime.SpecifyKind((DateTime)Value, Kind);
|
||||
await ValueChanged.InvokeAsync((TValue)(object)offset);
|
||||
}
|
||||
else if ((typeof(TValue) == typeof(DateTime) || typeof(TValue) == typeof(DateTime?)) && Value != null)
|
||||
{
|
||||
await ValueChanged.InvokeAsync((TValue)(object)DateTime.SpecifyKind((DateTime)Value, Kind));
|
||||
}
|
||||
else
|
||||
{
|
||||
await ValueChanged.InvokeAsync((TValue)Value);
|
||||
@@ -950,7 +978,7 @@ namespace Radzen.Blazor
|
||||
protected override string GetComponentCssClass()
|
||||
{
|
||||
return ClassList.Create()
|
||||
.Add("rz-calendar-inline", Inline)
|
||||
.Add("rz-datepicker-inline", Inline)
|
||||
.Add(FieldIdentifier, EditContext)
|
||||
.ToString();
|
||||
}
|
||||
@@ -960,7 +988,7 @@ namespace Radzen.Blazor
|
||||
if (ShowTimeOkButton)
|
||||
{
|
||||
CurrentDate = new DateTime(newValue.Year, newValue.Month, newValue.Day, CurrentDate.Hour, CurrentDate.Minute, CurrentDate.Second);
|
||||
await OkClick();
|
||||
await OkClick(!ShowTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -972,9 +1000,7 @@ namespace Radzen.Blazor
|
||||
Close();
|
||||
}
|
||||
}
|
||||
#if NET5_0_OR_GREATER
|
||||
await FocusAsync();
|
||||
#endif
|
||||
}
|
||||
|
||||
private void SetMonth(int month)
|
||||
@@ -1116,9 +1142,7 @@ namespace Radzen.Blazor
|
||||
if (PopupRenderMode == PopupRenderMode.OnDemand && !Disabled && !ReadOnly && !Inline)
|
||||
{
|
||||
await popup.ToggleAsync(Element);
|
||||
#if NET5_0_OR_GREATER
|
||||
await FocusAsync();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
DateTime FocusedDate { get; set; } = DateTime.Now;
|
||||
@@ -1127,9 +1151,9 @@ namespace Radzen.Blazor
|
||||
{
|
||||
return ClassList.Create()
|
||||
.Add("rz-state-default", !forCell)
|
||||
.Add("rz-datepicker-other-month", CurrentDate.Month != date.Month)
|
||||
.Add("rz-calendar-other-month", CurrentDate.Month != date.Month)
|
||||
.Add("rz-state-active", !forCell && DateTimeValue.HasValue && DateTimeValue.Value.Date.CompareTo(date.Date) == 0)
|
||||
.Add("rz-datepicker-today", !forCell && DateTime.Now.Date.CompareTo(date.Date) == 0)
|
||||
.Add("rz-calendar-today", !forCell && DateTime.Now.Date.CompareTo(date.Date) == 0)
|
||||
.Add("rz-state-focused", !forCell && FocusedDate.Date.CompareTo(date.Date) == 0)
|
||||
.Add("rz-state-disabled", !forCell && dateArgs.Disabled)
|
||||
.ToString();
|
||||
@@ -1156,30 +1180,27 @@ namespace Radzen.Blazor
|
||||
{
|
||||
preventKeyPress = true;
|
||||
|
||||
await SetDay(FocusedDate);
|
||||
if (!DateAttributes(FocusedDate).Disabled)
|
||||
{
|
||||
await SetDay(FocusedDate);
|
||||
|
||||
await ClosePopup();
|
||||
#if NET5_0_OR_GREATER
|
||||
await FocusAsync();
|
||||
#endif
|
||||
await ClosePopup();
|
||||
await FocusAsync();
|
||||
}
|
||||
}
|
||||
else if (key == "Escape")
|
||||
{
|
||||
preventKeyPress = false;
|
||||
|
||||
await ClosePopup();
|
||||
#if NET5_0_OR_GREATER
|
||||
await FocusAsync();
|
||||
#endif
|
||||
}
|
||||
else if (key == "Tab")
|
||||
{
|
||||
preventKeyPress = false;
|
||||
|
||||
await ClosePopup();
|
||||
#if NET5_0_OR_GREATER
|
||||
await FocusAsync();
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1195,9 +1216,7 @@ namespace Radzen.Blazor
|
||||
preventKeyPress = false;
|
||||
|
||||
await ClosePopup();
|
||||
#if NET5_0_OR_GREATER
|
||||
await FocusAsync();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1230,9 +1249,7 @@ namespace Radzen.Blazor
|
||||
preventKeyPress = false;
|
||||
|
||||
await ClosePopup();
|
||||
#if NET5_0_OR_GREATER
|
||||
await FocusAsync();
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1242,6 +1259,8 @@ namespace Radzen.Blazor
|
||||
|
||||
internal async Task TogglePopup()
|
||||
{
|
||||
if (Inline) return;
|
||||
|
||||
if (PopupRenderMode == PopupRenderMode.Initial)
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.togglePopup", Element, PopupID, false, null, null, true, true);
|
||||
@@ -1254,6 +1273,8 @@ namespace Radzen.Blazor
|
||||
|
||||
async Task ClosePopup()
|
||||
{
|
||||
if (Inline) return;
|
||||
|
||||
if (PopupRenderMode == PopupRenderMode.Initial)
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.closePopup", PopupID);
|
||||
@@ -1265,7 +1286,7 @@ namespace Radzen.Blazor
|
||||
}
|
||||
|
||||
bool preventKeyPress = false;
|
||||
#if NET5_0_OR_GREATER
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async ValueTask FocusAsync()
|
||||
{
|
||||
@@ -1276,6 +1297,5 @@ namespace Radzen.Blazor
|
||||
catch
|
||||
{}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
<div class="rz-dialog-side-title" style="display: inline" id="rz-dialog-side-label">@((MarkupString)sideDialogOptions.Title)</div>
|
||||
@if (sideDialogOptions.ShowClose)
|
||||
{
|
||||
<a aria-label="@CloseSideDialogAriaLabel" @onclick:preventDefault="true" class="rz-dialog-side-titlebar-close" @onclick="@(_ => Service.CloseSide(null))" role="button" tabindex="@sideDialogOptions.CloseTabIndex">
|
||||
<span class="rzi rzi-times"></span>
|
||||
<a id="@(sideDialogOptions.GetHashCode() + "cl")" aria-label="@CloseSideDialogAriaLabel" @onclick:preventDefault="true" class="rz-dialog-side-titlebar-close" @onclick="@(_ => Service.CloseSide(null))" role="button" tabindex="@sideDialogOptions.CloseTabIndex">
|
||||
<span class="notranslate rzi rzi-times"></span>
|
||||
</a>
|
||||
}
|
||||
</div>
|
||||
@@ -145,4 +145,14 @@
|
||||
|
||||
return $"{widthStyle}{heightStyle}{sideDialogOptions.Style}";
|
||||
}
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
await base.OnAfterRenderAsync(firstRender);
|
||||
|
||||
if (isSideDialogOpen)
|
||||
{
|
||||
await JSRuntime.InvokeAsync<string>("Radzen.openSideDialog", sideDialogOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,15 +36,16 @@
|
||||
var y = CenterY;
|
||||
var radius = CurrentRadius;
|
||||
var innerRadius = InnerRadius ?? radius / 2;
|
||||
var items = PositiveItems;
|
||||
return
|
||||
@<g>
|
||||
<g class="@className">
|
||||
@if (PositiveItems.Any())
|
||||
@if (items.Any())
|
||||
{
|
||||
var sum = PositiveItems.Sum(Value);
|
||||
var sum = items.Sum(Value);
|
||||
var startAngle = StartAngle;
|
||||
|
||||
@foreach (var data in PositiveItems)
|
||||
@foreach (var data in items)
|
||||
{
|
||||
var value = Value(data);
|
||||
var sweepAngle = (value / sum) * TotalAngle;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
@using Radzen
|
||||
@using System.Linq
|
||||
@using System.Linq.Dynamic.Core
|
||||
@using Microsoft.AspNetCore.Components.Forms
|
||||
@using Microsoft.JSInterop
|
||||
@using Microsoft.AspNetCore.Components.Rendering
|
||||
@@ -14,7 +13,7 @@
|
||||
<div class="rz-helper-hidden-accessible">
|
||||
<input disabled="@Disabled" aria-haspopup="listbox" readonly="" type="text" tabindex="-1"
|
||||
name="@Name" value="@(internalValue != null ? internalValue : "")" id="@Name"
|
||||
aria-label="@(!Multiple && internalValue != null ? internalValue : "")" @attributes="InputAttributes"/>
|
||||
aria-label="@(!Multiple && internalValue != null ? internalValue : EmptyAriaLabel)" @attributes="InputAttributes"/>
|
||||
</div>
|
||||
|
||||
@if (ValueTemplate != null && selectedItem != null)
|
||||
@@ -55,7 +54,7 @@
|
||||
@GetItemOrValueFromProperty(item, TextProperty)
|
||||
}
|
||||
</span>
|
||||
<button tabindex="0" title="@(RemoveChipTitle + " " + GetItemOrValueFromProperty(item, TextProperty))" type=button class="rz-button rz-button-sm rz-button-icon-only rz-light @(Disabled ?"rz-state-disabled":"")" @onclick:preventDefault @onclick:stopPropagation @onclick="() => OnChipRemove(item)"><RadzenIcon Icon="close" /></button>
|
||||
<button tabindex="0" title="@(RemoveChipTitle + " " + GetItemOrValueFromProperty(item, TextProperty))" type=button class="rz-button rz-button-sm rz-button-icon-only rz-base rz-shade-default @(Disabled ?"rz-state-disabled":"")" @onclick:preventDefault @onclick:stopPropagation @onclick="() => OnChipRemove(item)"><RadzenIcon Icon="close" /></button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
@@ -107,22 +106,30 @@
|
||||
}
|
||||
|
||||
<div class="rz-dropdown-trigger rz-corner-right">
|
||||
<span class="rz-dropdown-trigger-icon rzi rzi-chevron-down"></span>
|
||||
<span class="notranslate rz-dropdown-trigger-icon rzi rzi-chevron-down"></span>
|
||||
</div>
|
||||
|
||||
<div id="@PopupID" class="@(Multiple ? "rz-multiselect-panel " : "rz-dropdown-panel ")"
|
||||
<div id="@PopupID" class="@(Multiple ? "rz-multiselect-panel" : "rz-dropdown-panel")"
|
||||
style="display:none; box-sizing: border-box">
|
||||
@if (AllowFiltering && !Multiple)
|
||||
@if(!Multiple && (AllowFiltering || HeaderTemplate != null))
|
||||
{
|
||||
<div class="rz-dropdown-filter-container">
|
||||
<input aria-label="@SearchAriaLabel" id="@SearchID" @ref="@search" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" placeholder="@FilterPlaceholder" class="rz-dropdown-filter rz-inputtext" autocomplete="off" aria-autocomplete="none" type="text"
|
||||
@onchange="@((ChangeEventArgs args) => OnFilter(args))" @onkeydown="@((args) => OnFilterKeyPress(args))" value="@searchText"
|
||||
@oninput=@(args => { searchText = $"{args.Value}"; SearchTextChanged.InvokeAsync(searchText);}) />
|
||||
<span class="rz-dropdown-filter-icon rzi rzi-search"></span>
|
||||
</div>
|
||||
@if (HeaderTemplate != null)
|
||||
{
|
||||
@HeaderTemplate
|
||||
}
|
||||
else
|
||||
{
|
||||
@RenderFilter()
|
||||
}
|
||||
}
|
||||
@if (Multiple && (AllowSelectAll || AllowFiltering))
|
||||
@if (Multiple && (AllowSelectAll || AllowFiltering || HeaderTemplate != null))
|
||||
{
|
||||
@if (HeaderTemplate != null)
|
||||
{
|
||||
@HeaderTemplate
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="rz-multiselect-header rz-helper-clearfix" @onclick:preventDefault>
|
||||
@if(AllowSelectAll && Data != null && Data.Cast<object>().Any())
|
||||
{
|
||||
@@ -130,8 +137,8 @@
|
||||
<div class="rz-helper-hidden-accessible">
|
||||
<input readonly="readonly" type="checkbox" id="@($"{(Name ?? UniqueID + "sa")}")" aria-label="@SearchAriaLabel" aria-checked="@(IsAllSelected().ToString().ToLowerInvariant())">
|
||||
</div>
|
||||
<div class="@(IsAllSelected() ? "rz-chkbox-box rz-state-active" : "rz-chkbox-box")">
|
||||
<span class="@(IsAllSelected() ? "rz-chkbox-icon rzi rzi-check" : "rz-chkbox-icon")"></span>
|
||||
<div class="@(IsAllSelected() ? "notranslate rz-chkbox-box rz-state-active" : "notranslate rz-chkbox-box")">
|
||||
<span class="@(IsAllSelected() ? "notranslate rz-chkbox-icon rzi rzi-check" : "notranslate rz-chkbox-icon")"></span>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@@ -146,13 +153,14 @@
|
||||
onclick="Radzen.preventDefaultAndStopPropagation(event)" aria-label="@SearchAriaLabel"
|
||||
@ref="@search" @oninput=@(args => { searchText = $"{args.Value}"; SearchTextChanged.InvokeAsync(searchText);})
|
||||
@onchange="@((args) => OnFilter(args))" @onkeydown="@((args) => OnFilterKeyPress(args))" value="@searchText" />
|
||||
<span class="rz-multiselect-filter-icon rzi rzi-search"></span>
|
||||
<span class="notranslate rz-multiselect-filter-icon rzi rzi-search"></span>
|
||||
</div>
|
||||
}
|
||||
<a class="rz-multiselect-close " @onclick="@ClearAll" @onclick:stopPropagation="true">
|
||||
<span class="rzi rzi-times"></span>
|
||||
<a id="@(GetId() + "clear")" class="rz-multiselect-close " @onclick="@ClearAll" @onclick:stopPropagation="true">
|
||||
<span class="notranslate rzi rzi-times"></span>
|
||||
</a>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
<div class="@(Multiple ? "rz-multiselect-items-wrapper" : "rz-dropdown-items-wrapper")" style="@PopupStyle">
|
||||
@if (Data != null && Data.Cast<object>().Any())
|
||||
@@ -172,7 +180,35 @@
|
||||
</div>
|
||||
@if (AllowClear && (!Multiple && HasValue || Multiple && selectedItems.Count > 0))
|
||||
{
|
||||
<i class="rz-dropdown-clear-icon rzi rzi-times" @onclick="@ClearAll" @onclick:stopPropagation="true"></i>
|
||||
<i class="notranslate rz-dropdown-clear-icon rzi rzi-times" @onclick="@ClearAll" @onclick:stopPropagation="true"></i>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
@code {
|
||||
internal RenderFragment RenderFilter()
|
||||
{
|
||||
#if NET7_0_OR_GREATER
|
||||
return __builder => {
|
||||
<text>
|
||||
<div class="rz-dropdown-filter-container">
|
||||
<input aria-label="@SearchAriaLabel" id="@SearchID" @ref="@search" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" placeholder="@FilterPlaceholder" class="rz-dropdown-filter rz-inputtext" autocomplete="off" aria-autocomplete="none" type="text"
|
||||
@onchange="@OnFilter" @onkeydown="@OnFilterKeyPress"
|
||||
@bind:event="oninput" @bind:get="searchText" @bind:set="@(args => { searchText = $"{args}"; SearchTextChanged.InvokeAsync(searchText);})" />
|
||||
<span class="notranslate rz-dropdown-filter-icon rzi rzi-search"></span>
|
||||
</div>
|
||||
</text>
|
||||
};
|
||||
#else
|
||||
return __builder => {
|
||||
<text>
|
||||
<div class="rz-dropdown-filter-container">
|
||||
<input aria-label="@SearchAriaLabel" id="@SearchID" @ref="@search" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" placeholder="@FilterPlaceholder" class="rz-dropdown-filter rz-inputtext" autocomplete="off" aria-autocomplete="none" type="text"
|
||||
@onchange="@OnFilter" @onkeydown="@OnFilterKeyPress" value="@searchText"
|
||||
@oninput="@((ChangeEventArgs args) => { searchText = $"{args.Value}"; SearchTextChanged.InvokeAsync(searchText);})" />
|
||||
<span class="notranslate rz-dropdown-filter-icon rzi rzi-search"></span>
|
||||
</div>
|
||||
</text>
|
||||
};
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ using Microsoft.JSInterop;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
@@ -67,6 +68,32 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public string FilterPlaceholder { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the row render callback. Use it to set row attributes.
|
||||
/// </summary>
|
||||
/// <value>The row render callback.</value>
|
||||
[Parameter]
|
||||
public Action<DropDownItemRenderEventArgs<TValue>> ItemRender { get; set; }
|
||||
|
||||
internal DropDownItemRenderEventArgs<TValue> ItemAttributes(RadzenDropDownItem<TValue> item)
|
||||
{
|
||||
var disabled = !string.IsNullOrEmpty(DisabledProperty) ? GetItemOrValueFromProperty(item.Item, DisabledProperty) : false;
|
||||
|
||||
var args = new DropDownItemRenderEventArgs<TValue>()
|
||||
{
|
||||
DropDown = this,
|
||||
Item = item.Item,
|
||||
Disabled = disabled is bool ? (bool)disabled : false,
|
||||
};
|
||||
|
||||
if (ItemRender != null)
|
||||
{
|
||||
ItemRender(args);
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
private async Task OnFocus(Microsoft.AspNetCore.Components.Web.FocusEventArgs args)
|
||||
{
|
||||
if (OpenOnFocus)
|
||||
@@ -74,6 +101,24 @@ namespace Radzen.Blazor
|
||||
await OpenPopup("Enter", false);
|
||||
}
|
||||
}
|
||||
internal override async Task ClosePopup(string key)
|
||||
{
|
||||
bool of = false;
|
||||
|
||||
if (key == "Enter")
|
||||
{
|
||||
of = OpenOnFocus;
|
||||
OpenOnFocus = false;
|
||||
}
|
||||
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.closePopup", PopupID);
|
||||
|
||||
if (key == "Enter")
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.focusElement", UniqueID);
|
||||
OpenOnFocus = of;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the popup.
|
||||
@@ -89,7 +134,7 @@ namespace Radzen.Blazor
|
||||
await JSRuntime.InvokeVoidAsync(OpenOnFocus ? "Radzen.openPopup" : "Radzen.togglePopup", Element, PopupID, true);
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.focusElement", isFilter ? UniqueID : SearchID);
|
||||
|
||||
if (list != null)
|
||||
if (list != null && selectedIndex != -1)
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.selectListItem", search, list, selectedIndex);
|
||||
}
|
||||
@@ -150,6 +195,17 @@ namespace Radzen.Blazor
|
||||
private bool disabledChanged = false;
|
||||
private bool firstRender = true;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Task SelectAll()
|
||||
{
|
||||
if (ReadOnly)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
return base.SelectAll();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async Task SetParametersAsync(ParameterView parameters)
|
||||
{
|
||||
@@ -274,7 +330,7 @@ namespace Radzen.Blazor
|
||||
}
|
||||
}
|
||||
|
||||
internal async Task ClosePopup()
|
||||
internal async Task PopupClose()
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.closePopup", PopupID);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
@using Radzen
|
||||
@using System.Collections
|
||||
@using System.Collections.Generic
|
||||
@using System.Linq.Dynamic.Core
|
||||
@using Microsoft.AspNetCore.Components.Forms
|
||||
@using Microsoft.JSInterop
|
||||
@typeparam TValue
|
||||
@@ -14,7 +13,7 @@
|
||||
@onkeydown="@((args) => OnKeyPress(args))" @onkeydown:preventDefault="@preventKeydown">
|
||||
<div class="rz-helper-hidden-accessible">
|
||||
<input tabindex="-1" disabled="@Disabled" style="width:100%" aria-haspopup="listbox" readonly="" type="text" id="@Name"
|
||||
name="@Name" aria-label="@(!Multiple && internalValue != null ? PropertyAccess.GetItemOrValueFromProperty(internalValue, TextProperty) : "")" @attributes="InputAttributes"/>
|
||||
name="@Name" aria-label="@(!Multiple && internalValue != null ? PropertyAccess.GetItemOrValueFromProperty(internalValue, TextProperty) : EmptyAriaLabel)" @attributes="InputAttributes" />
|
||||
|
||||
</div>
|
||||
|
||||
@@ -39,23 +38,27 @@
|
||||
else if ((selectedItems.Count > 0 || SelectedValue is IEnumerable && !(SelectedValue is string)) && Multiple)
|
||||
{
|
||||
var itemsToUse = SelectedValue is IEnumerable && !(SelectedValue is string) ? ((IEnumerable)SelectedValue).Cast<object>().ToList() : selectedItems;
|
||||
@if (itemsToUse.Count < MaxSelectedLabels && Template == null && Chips)
|
||||
@if (itemsToUse.Count < MaxSelectedLabels && Chips)
|
||||
{
|
||||
<div class="rz-dropdown-chips-wrapper">
|
||||
@foreach (var item in itemsToUse)
|
||||
{
|
||||
<div class="rz-chip">
|
||||
<span class="rz-chip-text" @onkeydown:stopPropagation>
|
||||
@if (Template != null)
|
||||
@if (ValueTemplate != null)
|
||||
{
|
||||
@ValueTemplate(item)
|
||||
}
|
||||
else if (Template != null)
|
||||
{
|
||||
@Template(item)
|
||||
}
|
||||
else
|
||||
{
|
||||
@PropertyAccess.GetItemOrValueFromProperty(item, TextProperty)
|
||||
@GetItemOrValueFromProperty(item, TextProperty)
|
||||
}
|
||||
</span>
|
||||
<button tabindex="0" title="@(RemoveChipTitle + " " + GetItemOrValueFromProperty(item, TextProperty))" type="button" class="rz-button rz-button-sm rz-button-icon-only rz-light @(Disabled ?"rz-state-disabled":"")" @onclick:preventDefault @onclick:stopPropagation @onclick="() => OnChipRemove(item)"><RadzenIcon Icon="close" /></button>
|
||||
<button tabindex="0" title="@(RemoveChipTitle + " " + GetItemOrValueFromProperty(item, TextProperty))" type="button" class="rz-button rz-button-sm rz-button-icon-only rz-base rz-shade-default @(Disabled ?"rz-state-disabled":"")" @onclick:preventDefault @onclick:stopPropagation @onclick="() => OnChipRemove(item)"><RadzenIcon Icon="close" /></button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
@@ -105,35 +108,40 @@
|
||||
}
|
||||
|
||||
<div class="rz-dropdown-trigger rz-corner-right">
|
||||
<span class="rz-dropdown-trigger-icon rzi rzi-chevron-down"></span>
|
||||
<span class="notranslate rz-dropdown-trigger-icon rzi rzi-chevron-down"></span>
|
||||
</div>
|
||||
|
||||
<div id="@PopupID" class="@(Multiple ? "rz-multiselect-panel" : "rz-dropdown-panel")"
|
||||
style="display:none;min-width:400px;padding:0px;">
|
||||
<div class="rz-lookup-panel" @onkeydown="@CloseOnEscape">
|
||||
@if (AllowFiltering)
|
||||
@if (AllowFiltering || HeaderTemplate != null)
|
||||
{
|
||||
@if (HeaderTemplate != null)
|
||||
{
|
||||
@HeaderTemplate
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="rz-lookup-search">
|
||||
<input aria-label="@SearchAriaLabel" class="rz-lookup-search-input" id="@SearchID" @ref="@search" tabindex="0" placeholder="@SearchTextPlaceholder"
|
||||
@onchange="@((args) => OnFilter(args))" @onkeydown="@((args) => OnFilterKeyPress(args))" value="@searchText" style="@(ShowSearch ? "" : "margin-right:0px;")"
|
||||
@oninput=@(args => { searchText = $"{args.Value}"; SearchTextChanged.InvokeAsync(searchText);}) />
|
||||
@RenderFilter()
|
||||
@if (ShowSearch)
|
||||
{
|
||||
<button tabindex="0" class="rz-button rz-button-md rz-button-icon-only rz-primary" type="button" title="" @onclick="@((args) => OnFilter(new ChangeEventArgs()))">
|
||||
<i class="rz-button-icon-left rzi">search</i>
|
||||
<button tabindex="0" class="rz-button rz-button-md rz-button-icon-only rz-primary" type="button" title="@SearchTextPlaceholder" @onclick="@((args) => OnFilter(new ChangeEventArgs()))">
|
||||
<i class="notranslate rz-button-icon-left rzi">search</i>
|
||||
</button>
|
||||
}
|
||||
@if (ShowAdd)
|
||||
{
|
||||
<button tabindex="0" class="rz-button rz-button-md rz-button-icon-only rz-primary" style="margin-left: 5px" type="button" title="" @onclick="@OnAddClick">
|
||||
<i class="rz-button-icon-left rzi">add</i>
|
||||
<button tabindex="0" class="rz-button rz-button-md rz-button-icon-only rz-primary" style="margin-left: 5px" type="button" title="@AddAriaLabel" @onclick="@OnAddClick">
|
||||
<i class="notranslate rz-button-icon-left rzi">add</i>
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
}
|
||||
@if (Template != null)
|
||||
{
|
||||
<RadzenDataGrid AllowVirtualization="@IsVirtualizationAllowed()" VirtualizationOverscanCount="@GetVirtualizationOverscanCount()" AllowRowSelectOnRowClick="@AllowRowSelectOnRowClick" PagerHorizontalAlign="@PagerHorizontalAlign" PagerAlwaysVisible="@PagerAlwaysVisible" Responsive="@Responsive" AllowColumnResize="@AllowColumnResize" ColumnWidth="@ColumnWidth" @ref="grid" Data="@(LoadData.HasDelegate ? (Data != null ? Data.Cast<object>() : Enumerable.Empty<object>()) : pagedData)" Count="@(LoadData.HasDelegate ? Count : count)" LoadData="@OnLoadData"
|
||||
<RadzenDataGrid EmptyTemplate=@EmptyTemplate FooterTemplate=@FooterTemplate AllowVirtualization="@IsVirtualizationAllowed()" VirtualizationOverscanCount="@GetVirtualizationOverscanCount()" AllowRowSelectOnRowClick="@AllowRowSelectOnRowClick" PagerHorizontalAlign="@PagerHorizontalAlign" PagerAlwaysVisible="@PagerAlwaysVisible" Responsive="@Responsive" AllowColumnResize="@AllowColumnResize" ColumnWidth="@ColumnWidth" @ref="grid" Data="@(LoadData.HasDelegate ? (Data != null ? Data.Cast<object>() : Enumerable.Empty<object>()) : pagedData)" Count="@(LoadData.HasDelegate ? Count : count)" LoadData="@OnLoadData"
|
||||
TItem="object" CellRender="@OnCellRender" RowRender="@OnRowRender" ShowPagingSummary="@ShowPagingSummary" PagingSummaryFormat="@PagingSummaryFormat" PageSize="@PageSize" PageNumbersCount="@PageNumbersCount" AllowPaging="@(!IsVirtualizationAllowed())" AllowSorting="@AllowSorting" RowSelect="@OnRowSelect" Style="@(IsVirtualizationAllowed() ? "height:285px" : "")" Density="@Density" IsLoading="@IsLoading" FirstPageTitle="@FirstPageTitle" FirstPageAriaLabel="@FirstPageAriaLabel" PrevPageAriaLabel="@PrevPageAriaLabel" PrevPageTitle="@PrevPageTitle" NextPageAriaLabel="@NextPageAriaLabel" NextPageTitle="@NextPageTitle" LastPageAriaLabel="@LastPageAriaLabel" LastPageTitle="@LastPageTitle" PageAriaLabelFormat="@PageAriaLabelFormat" PageTitleFormat="@PageTitleFormat">
|
||||
<Columns>
|
||||
<RadzenDataGridColumn TItem="object" Property="@TextProperty" Title="@TextProperty" Type="typeof(string)">
|
||||
@@ -142,16 +150,13 @@
|
||||
</Template>
|
||||
</RadzenDataGridColumn>
|
||||
</Columns>
|
||||
<EmptyTemplate>
|
||||
@EmptyTemplate
|
||||
</EmptyTemplate>
|
||||
</RadzenDataGrid>
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!string.IsNullOrEmpty(TextProperty) || Columns != null)
|
||||
{
|
||||
<RadzenDataGrid AllowVirtualization="@IsVirtualizationAllowed()" VirtualizationOverscanCount="@GetVirtualizationOverscanCount()" AllowRowSelectOnRowClick="@AllowRowSelectOnRowClick" PagerHorizontalAlign="@PagerHorizontalAlign" PagerAlwaysVisible="@PagerAlwaysVisible" Responsive="@Responsive" AllowColumnResize="@AllowColumnResize" ColumnWidth="@ColumnWidth" EmptyText="@EmptyText" @ref="grid" Data="@(LoadData.HasDelegate ? (Data != null ? Data.Cast<object>() : Enumerable.Empty<object>()) : pagedData)" Count="@(LoadData.HasDelegate ? Count : count)" LoadData="@OnLoadData"
|
||||
<RadzenDataGrid EmptyTemplate=@EmptyTemplate FooterTemplate=@FooterTemplate AllowVirtualization="@IsVirtualizationAllowed()" VirtualizationOverscanCount="@GetVirtualizationOverscanCount()" AllowRowSelectOnRowClick="@AllowRowSelectOnRowClick" PagerHorizontalAlign="@PagerHorizontalAlign" PagerAlwaysVisible="@PagerAlwaysVisible" Responsive="@Responsive" AllowColumnResize="@AllowColumnResize" ColumnWidth="@ColumnWidth" EmptyText="@EmptyText" @ref="grid" Data="@(LoadData.HasDelegate ? (Data != null ? Data.Cast<object>() : Enumerable.Empty<object>()) : pagedData)" Count="@(LoadData.HasDelegate ? Count : count)" LoadData="@OnLoadData"
|
||||
TItem="object" CellRender="@OnCellRender" RowRender="@OnRowRender" ShowPagingSummary="@ShowPagingSummary" PagingSummaryFormat="@PagingSummaryFormat" PageSize="@PageSize" PageNumbersCount="@PageNumbersCount" AllowPaging="@(!IsVirtualizationAllowed())" AllowSorting="@AllowSorting" RowSelect="@OnRowSelect" Style="@(IsVirtualizationAllowed() ? "height:285px" : "")" Density="@Density" IsLoading="@IsLoading" FirstPageTitle="@FirstPageTitle" FirstPageAriaLabel="@FirstPageAriaLabel" PrevPageAriaLabel="@PrevPageAriaLabel" PrevPageTitle="@PrevPageTitle" NextPageAriaLabel="@NextPageAriaLabel" NextPageTitle="@NextPageTitle" LastPageAriaLabel="@LastPageAriaLabel" LastPageTitle="@LastPageTitle" PageAriaLabelFormat="@PageAriaLabelFormat" PageTitleFormat="@PageTitleFormat">
|
||||
<Columns>
|
||||
@if (Columns != null)
|
||||
@@ -163,14 +168,11 @@
|
||||
<RadzenDataGridColumn TItem="object" Property="@TextProperty" Title="@TextProperty" Type="typeof(string)" />
|
||||
}
|
||||
</Columns>
|
||||
<EmptyTemplate>
|
||||
@EmptyTemplate
|
||||
</EmptyTemplate>
|
||||
</RadzenDataGrid>
|
||||
}
|
||||
else
|
||||
{
|
||||
<RadzenDataGrid AllowVirtualization="@IsVirtualizationAllowed()" VirtualizationOverscanCount="@GetVirtualizationOverscanCount()" AllowRowSelectOnRowClick="@AllowRowSelectOnRowClick" PagerHorizontalAlign="@PagerHorizontalAlign" PagerAlwaysVisible="@PagerAlwaysVisible" Responsive="@Responsive" AllowColumnResize="@AllowColumnResize" ColumnWidth="@ColumnWidth" EmptyText="@EmptyText" @ref="grid" Data="@(LoadData.HasDelegate ? (Data != null ? Data.Cast<object>() : Enumerable.Empty<object>()) : pagedData)" Count="@(LoadData.HasDelegate ? Count : count)" LoadData="@OnLoadData"
|
||||
<RadzenDataGrid EmptyTemplate=@EmptyTemplate FooterTemplate=@FooterTemplate AllowVirtualization="@IsVirtualizationAllowed()" VirtualizationOverscanCount="@GetVirtualizationOverscanCount()" AllowRowSelectOnRowClick="@AllowRowSelectOnRowClick" PagerHorizontalAlign="@PagerHorizontalAlign" PagerAlwaysVisible="@PagerAlwaysVisible" Responsive="@Responsive" AllowColumnResize="@AllowColumnResize" ColumnWidth="@ColumnWidth" EmptyText="@EmptyText" @ref="grid" Data="@(LoadData.HasDelegate ? (Data != null ? Data.Cast<object>() : Enumerable.Empty<object>()) : pagedData)" Count="@(LoadData.HasDelegate ? Count : count)" LoadData="@OnLoadData"
|
||||
TItem="object" CellRender="@OnCellRender" RowRender="@OnRowRender" ShowPagingSummary="@ShowPagingSummary" PagingSummaryFormat="@PagingSummaryFormat" PageSize="@PageSize" PageNumbersCount="@PageNumbersCount" AllowPaging="@(!IsVirtualizationAllowed())" AllowSorting="@AllowSorting" RowSelect="@OnRowSelect" Style="@(IsVirtualizationAllowed() ? "height:285px" : "")" Density="@Density" IsLoading="@IsLoading" FirstPageTitle="@FirstPageTitle" FirstPageAriaLabel="@FirstPageAriaLabel" PrevPageAriaLabel="@PrevPageAriaLabel" PrevPageTitle="@PrevPageTitle" NextPageAriaLabel="@NextPageAriaLabel" NextPageTitle="@NextPageTitle" LastPageAriaLabel="@LastPageAriaLabel" LastPageTitle="@LastPageTitle" PageAriaLabelFormat="@PageAriaLabelFormat" PageTitleFormat="@PageTitleFormat">
|
||||
<Columns>
|
||||
<RadzenDataGridColumn TItem="object" Property="it" Title="Item" Type="typeof(string)">
|
||||
@@ -179,9 +181,6 @@
|
||||
</Template>
|
||||
</RadzenDataGridColumn>
|
||||
</Columns>
|
||||
<EmptyTemplate>
|
||||
@EmptyTemplate
|
||||
</EmptyTemplate>
|
||||
</RadzenDataGrid>
|
||||
}
|
||||
}
|
||||
@@ -190,7 +189,29 @@
|
||||
|
||||
@if (AllowClear && (!Multiple && HasValue || Multiple && (selectedItems.Count > 0 || SelectedValue is IEnumerable)))
|
||||
{
|
||||
<i class="rz-dropdown-clear-icon rzi rzi-times" @onclick="@Clear" @onclick:stopPropagation="true"></i>
|
||||
<i class="notranslate rz-dropdown-clear-icon rzi rzi-times" @onclick="@Clear" @onclick:stopPropagation="true"></i>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
@code {
|
||||
internal RenderFragment RenderFilter()
|
||||
{
|
||||
#if NET7_0_OR_GREATER
|
||||
return __builder => {
|
||||
<text>
|
||||
<input aria-label="@SearchAriaLabel" class="rz-lookup-search-input" id="@SearchID" @ref="@search" tabindex="0" placeholder="@SearchTextPlaceholder"
|
||||
@onchange="@OnFilter" @onkeydown="@OnFilterKeyPress" style="@(ShowSearch ? "" : "margin-right:0px;")"
|
||||
@bind:event="oninput" @bind:get="searchText" @bind:set=@(args => { searchText = $"{args}"; SearchTextChanged.InvokeAsync(searchText);}) />
|
||||
</text>
|
||||
};
|
||||
#else
|
||||
return __builder => {
|
||||
<text>
|
||||
<input aria-label="@SearchAriaLabel" class="rz-lookup-search-input" id="@SearchID" @ref="@search" tabindex="0" placeholder="@SearchTextPlaceholder"
|
||||
@onchange="@OnFilter" @onkeydown="@OnFilterKeyPress" value="@searchText" style="@(ShowSearch ? "" : "margin-right:0px;")"
|
||||
@oninput=@((ChangeEventArgs args) => { searchText = $"{args.Value}"; SearchTextChanged.InvokeAsync(searchText);}) />
|
||||
</text>
|
||||
};
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,9 +42,16 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public Action<DataGridCellRenderEventArgs<object>> CellRender { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the footer template.
|
||||
/// </summary>
|
||||
/// <value>The footer template.</value>
|
||||
[Parameter]
|
||||
public RenderFragment FooterTemplate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the selected items will be displayed as chips. Set to <c>false</c> by default.
|
||||
/// Requires <see cref="DropDownBase{T}.Multiple" /> to be set to <c>true</c>.
|
||||
/// Requires <see cref="DropDownBase{T}.Multiple" /> to be set to <c>true</c>.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> to display the selected items as chips; otherwise, <c>false</c>.</value>
|
||||
[Parameter]
|
||||
@@ -102,12 +109,12 @@ namespace Radzen.Blazor
|
||||
{
|
||||
if (Disabled)
|
||||
return;
|
||||
#if NET5_0_OR_GREATER
|
||||
|
||||
if (IsVirtualizationAllowed())
|
||||
{
|
||||
await grid.RefreshDataAsync();
|
||||
}
|
||||
#endif
|
||||
|
||||
await JSRuntime.InvokeVoidAsync(OpenOnFocus ? "Radzen.openPopup" : "Radzen.togglePopup", Element, PopupID, true);
|
||||
|
||||
if (FocusFilterOnPopup)
|
||||
@@ -263,19 +270,19 @@ namespace Radzen.Blazor
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string NextPageAriaLabel { get; set; } = "Go to next page.";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the pager's numeric page number buttons' title attributes.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string PageTitleFormat { get; set; } = "Page {0}";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the pager's numeric page number buttons' aria-label attributes.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string PageAriaLabelFormat { get; set; } = "Go to page {0}.";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the empty text.
|
||||
/// </summary>
|
||||
@@ -290,6 +297,12 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public string SearchTextPlaceholder { get; set; } = "Search...";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the add button aria-label attribute.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string AddAriaLabel { get; set; } = "Add";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the selected value.
|
||||
/// </summary>
|
||||
@@ -315,22 +328,6 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public int MaxSelectedLabels { get; set; } = 4;
|
||||
|
||||
#if !NET5_0_OR_GREATER
|
||||
/// <summary>
|
||||
/// Gets or sets the page size.
|
||||
/// </summary>
|
||||
/// <value>The page size.</value>
|
||||
[Parameter]
|
||||
public int PageSize { get; set; } = 5;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the total items count.
|
||||
/// </summary>
|
||||
/// <value>The total items count.</value>
|
||||
[Parameter]
|
||||
public int Count { get; set; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the selected items text.
|
||||
/// </summary>
|
||||
@@ -355,19 +352,32 @@ namespace Radzen.Blazor
|
||||
/// </summary>
|
||||
/// <param name="firstRender">if set to <c>true</c> [first render].</param>
|
||||
/// <returns>Task.</returns>
|
||||
protected override Task OnAfterRenderAsync(bool firstRender)
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
{
|
||||
if(Visible && LoadData.HasDelegate && Data == null)
|
||||
{
|
||||
LoadData.InvokeAsync(new Radzen.LoadDataArgs() { Skip = 0, Top = PageSize, Filter = searchText });
|
||||
await LoadData.InvokeAsync(new Radzen.LoadDataArgs() { Skip = 0, Top = PageSize, Filter = searchText });
|
||||
}
|
||||
|
||||
StateHasChanged();
|
||||
|
||||
if (!Multiple && grid != null && SelectedItem != null)
|
||||
{
|
||||
var items = (LoadData.HasDelegate ? Data != null ? Data : Enumerable.Empty<object>() : (pagedData != null ? pagedData : Enumerable.Empty<object>())).OfType<object>().ToList();
|
||||
if (items.Any())
|
||||
{
|
||||
selectedIndex = items.IndexOf(SelectedItem);
|
||||
if (selectedIndex >= 0)
|
||||
{
|
||||
await JSRuntime.InvokeAsync<int[]>("Radzen.focusTableRow", grid.GridId(), "ArrowDown", selectedIndex - 1, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return base.OnAfterRenderAsync(firstRender);
|
||||
await base.OnAfterRenderAsync(firstRender);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -420,6 +430,8 @@ namespace Radzen.Blazor
|
||||
|
||||
private bool IsColumnFilterPropertyTypeString(RadzenDataGridColumn<object> column)
|
||||
{
|
||||
if (column.Type == typeof(string)) return true;
|
||||
|
||||
var property = column.GetFilterProperty();
|
||||
var itemType = Data != null ? Data.AsQueryable().ElementType : typeof(object);
|
||||
var type = PropertyAccess.GetPropertyType(itemType, property);
|
||||
@@ -458,16 +470,16 @@ namespace Radzen.Blazor
|
||||
|
||||
foreach (string word in words)
|
||||
{
|
||||
query = query.Where(string.Join(" || ", grid.ColumnsCollection.Where(c => c.Filterable && IsColumnFilterPropertyTypeString(c))
|
||||
query = query.Where(DynamicLinqCustomTypeProvider.ParsingConfig, string.Join(" || ", grid.ColumnsCollection.Where(c => c.Filterable && IsColumnFilterPropertyTypeString(c))
|
||||
.Select(c => GetPropertyFilterExpression(c.GetFilterProperty(), filterCaseSensitivityOperator))),
|
||||
FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ? word.ToLower() : word);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
query = query.Where(string.Join(" || ", grid.ColumnsCollection.Where(c => c.Filterable && IsColumnFilterPropertyTypeString(c))
|
||||
query = query.Where(DynamicLinqCustomTypeProvider.ParsingConfig, string.Join(" || ", grid.ColumnsCollection.Where(c => c.Filterable && IsColumnFilterPropertyTypeString(c))
|
||||
.Select(c => GetPropertyFilterExpression(c.GetFilterProperty(), filterCaseSensitivityOperator))),
|
||||
FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ? searchText.ToLower() : searchText);
|
||||
FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ? searchText.ToLower() : searchText);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -478,13 +490,13 @@ namespace Radzen.Blazor
|
||||
|
||||
foreach (string word in words)
|
||||
{
|
||||
query = query.Where($"{GetPropertyFilterExpression(TextProperty, filterCaseSensitivityOperator)}",
|
||||
query = query.Where(DynamicLinqCustomTypeProvider.ParsingConfig, $"{GetPropertyFilterExpression(TextProperty, filterCaseSensitivityOperator)}",
|
||||
FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ? word.ToLower() : word);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
query = query.Where($"{GetPropertyFilterExpression(TextProperty, filterCaseSensitivityOperator)}",
|
||||
query = query.Where(DynamicLinqCustomTypeProvider.ParsingConfig, $"{GetPropertyFilterExpression(TextProperty, filterCaseSensitivityOperator)}",
|
||||
FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ? searchText.ToLower() : searchText);
|
||||
}
|
||||
}
|
||||
@@ -492,7 +504,7 @@ namespace Radzen.Blazor
|
||||
|
||||
if (!string.IsNullOrEmpty(args.OrderBy))
|
||||
{
|
||||
query = query.OrderBy(args.OrderBy);
|
||||
query = query.OrderBy(DynamicLinqCustomTypeProvider.ParsingConfig, args.OrderBy);
|
||||
}
|
||||
|
||||
count = await Task.FromResult(query.Count());
|
||||
@@ -543,21 +555,32 @@ namespace Radzen.Blazor
|
||||
{
|
||||
if (!Multiple)
|
||||
{
|
||||
bool raiseChange = false;
|
||||
|
||||
if (!string.IsNullOrEmpty(ValueProperty))
|
||||
{
|
||||
var item = Query.Where($@"{ValueProperty} == @0", value).FirstOrDefault();
|
||||
if (item != null)
|
||||
var item = Query.Where(DynamicLinqCustomTypeProvider.ParsingConfig, $@"{ValueProperty} == @0", value).FirstOrDefault();
|
||||
if (item != null && SelectedItem != item)
|
||||
{
|
||||
SelectedItem = item;
|
||||
raiseChange = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectedItem = internalValue;
|
||||
if (SelectedItem != internalValue)
|
||||
{
|
||||
SelectedItem = internalValue;
|
||||
raiseChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (raiseChange)
|
||||
{
|
||||
SelectedItemChanged.InvokeAsync(SelectedItem);
|
||||
selectedItems.Clear();
|
||||
selectedItems.Add(SelectedItem);
|
||||
}
|
||||
SelectedItemChanged?.Invoke(SelectedItem);
|
||||
selectedItems.Clear();
|
||||
selectedItems.Add(SelectedItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -569,8 +592,8 @@ namespace Radzen.Blazor
|
||||
{
|
||||
foreach (object v in valueList)
|
||||
{
|
||||
var item = Query.Where($@"{ValueProperty} == @0", v).FirstOrDefault();
|
||||
if (item != null && !selectedItems.AsQueryable().Where($@"object.Equals(it.{ValueProperty},@0)", v).Any())
|
||||
var item = Query.Where(DynamicLinqCustomTypeProvider.ParsingConfig, $@"{ValueProperty} == @0", v).FirstOrDefault();
|
||||
if (item != null && !selectedItems.AsQueryable().Where(DynamicLinqCustomTypeProvider.ParsingConfig, $@"object.Equals(it.{ValueProperty},@0)", v).Any())
|
||||
{
|
||||
selectedItems.Add(item);
|
||||
}
|
||||
@@ -594,6 +617,10 @@ namespace Radzen.Blazor
|
||||
{
|
||||
selectedItem = null;
|
||||
selectedItems.Clear();
|
||||
if (grid != null)
|
||||
{
|
||||
grid.selectedItems.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -667,7 +694,7 @@ namespace Radzen.Blazor
|
||||
{
|
||||
await grid.PrevPage();
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
await grid.NextPage();
|
||||
}
|
||||
@@ -692,10 +719,7 @@ namespace Radzen.Blazor
|
||||
}
|
||||
}
|
||||
|
||||
if (!Multiple)
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.closePopup", PopupID);
|
||||
}
|
||||
await CloseAndFocus();
|
||||
}
|
||||
}
|
||||
else if (args.AltKey && key == "ArrowDown")
|
||||
@@ -760,16 +784,15 @@ namespace Radzen.Blazor
|
||||
|
||||
async Task CloseOnEscape(KeyboardEventArgs args)
|
||||
{
|
||||
var key = args.Code != null ? args.Code : args.Key;
|
||||
if (key == "Escape")
|
||||
var key = args.Code != null ? args.Code : args.Key;
|
||||
if (key == "Escape")
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.closePopup", PopupID);
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.closePopup", PopupID);
|
||||
}
|
||||
}
|
||||
|
||||
async Task RefreshAfterFilter()
|
||||
{
|
||||
#if NET5_0_OR_GREATER
|
||||
if (IsVirtualizationAllowed() && grid != null)
|
||||
{
|
||||
if(string.IsNullOrEmpty(searchText))
|
||||
@@ -802,7 +825,7 @@ namespace Radzen.Blazor
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
StateHasChanged();
|
||||
|
||||
if (!IsVirtualizationAllowed())
|
||||
@@ -866,18 +889,27 @@ namespace Radzen.Blazor
|
||||
|
||||
async Task OnRowSelect(object item)
|
||||
{
|
||||
if (!Disabled && !Multiple)
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.closePopup", PopupID);
|
||||
}
|
||||
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.focusElement", UniqueID);
|
||||
await CloseAndFocus();
|
||||
|
||||
if (AllowRowSelectOnRowClick)
|
||||
{
|
||||
await SelectItem(item);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async Task CloseAndFocus()
|
||||
{
|
||||
if (!Disabled && !Multiple)
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.closePopup", PopupID);
|
||||
}
|
||||
|
||||
var of = OpenOnFocus;
|
||||
OpenOnFocus = false;
|
||||
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.focusElement", UniqueID);
|
||||
|
||||
OpenOnFocus = of;
|
||||
}
|
||||
|
||||
private async Task OnChipRemove(object item)
|
||||
@@ -945,7 +977,11 @@ namespace Radzen.Blazor
|
||||
/// </summary>
|
||||
public new async Task Reset() {
|
||||
base.Reset();
|
||||
await grid.SelectRow(null);
|
||||
|
||||
if (!Multiple)
|
||||
{
|
||||
await grid.SelectRow(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,21 @@
|
||||
@using Radzen
|
||||
@using System.Linq.Dynamic.Core
|
||||
@using Microsoft.AspNetCore.Components.Forms
|
||||
@using Microsoft.JSInterop
|
||||
@typeparam TValue
|
||||
|
||||
@{var itemArgs = DropDown?.ItemAttributes(this); }
|
||||
@if (itemArgs.Visible)
|
||||
{
|
||||
Disabled = itemArgs.Disabled;
|
||||
@if (DropDown.Multiple)
|
||||
{
|
||||
<li class="@GetComponentCssClass("rz-multiselect")"
|
||||
aria-label="@DropDown.GetItemOrValueFromProperty(Item, DropDown.TextProperty)"
|
||||
@onmousedown:preventDefault @onmousedown="args=>SelectItem(args,false)"
|
||||
@onclick:preventDefault @onclick="args=>SelectItem(args,true)">
|
||||
@onmousedown:preventDefault @onmousedown="args=>SelectItem(args,false)"
|
||||
@onclick:preventDefault @onclick="args=>SelectItem(args,true)"
|
||||
@attributes="@(itemArgs.Attributes.Any() ? itemArgs.Attributes : Attributes)">
|
||||
<div class="rz-chkbox ">
|
||||
<div class="@(DropDown.IsSelected(Item) ? "rz-chkbox-box rz-state-active" : "rz-chkbox-box") @(Disabled ? " rz-state-disabled " : "")">
|
||||
<span class="@(DropDown.IsSelected(Item) ? "rz-chkbox-icon rzi rzi-check" : "rz-chkbox-icon")"></span>
|
||||
<div class="@(DropDown.IsSelected(Item) ? "notranslate rz-chkbox-box rz-state-active" : "notranslate rz-chkbox-box") @(Disabled ? " rz-state-disabled " : "")">
|
||||
<span class="@(DropDown.IsSelected(Item) ? "notranslate rz-chkbox-icon rzi rzi-check" : "notranslate rz-chkbox-icon")"></span>
|
||||
</div>
|
||||
</div>
|
||||
<span class="rz-multiselect-item-content">
|
||||
@@ -31,7 +34,8 @@ else
|
||||
{
|
||||
<li role="option" class="@GetComponentCssClass("rz-dropdown")" aria-label="@DropDown.GetItemOrValueFromProperty(Item, DropDown.TextProperty)"
|
||||
@onmousedown:preventDefault @onmousedown="args=>SelectItem(args,false)"
|
||||
@onclick:preventDefault @onclick="args=>SelectItem(args,true)">
|
||||
@onclick:preventDefault @onclick="args=>SelectItem(args,true)"
|
||||
@attributes="@(itemArgs.Attributes.Any() ? itemArgs.Attributes : Attributes)">
|
||||
<span>
|
||||
@if (DropDown.Template != null)
|
||||
{
|
||||
@@ -44,7 +48,11 @@ else
|
||||
</span>
|
||||
</li>
|
||||
}
|
||||
}
|
||||
@code {
|
||||
[Parameter(CaptureUnmatchedValues = true)]
|
||||
public IReadOnlyDictionary<string, object> Attributes { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public RadzenDropDown<TValue> DropDown { get; set; }
|
||||
|
||||
|
||||
19
Radzen.Blazor/RadzenDropZone.razor
Normal file
19
Radzen.Blazor/RadzenDropZone.razor
Normal file
@@ -0,0 +1,19 @@
|
||||
@inherits RadzenComponentWithChildren
|
||||
@typeparam TItem
|
||||
@if(Visible)
|
||||
{
|
||||
<div @ref="@Element" style="@Style" @attributes="Attributes" class="@GetCssClass()" id="@GetId()" @ondrop="OnDrop" @ondragover="OnDragOver" @ondragleave="OnDragLeave">
|
||||
@ChildContent
|
||||
@foreach (var item in Items)
|
||||
{
|
||||
var result = ItemAttributes(item);
|
||||
|
||||
<CascadingValue Value=@item>
|
||||
<CascadingValue Value=this>
|
||||
<RadzenDropZoneItem TItem="TItem" Visible="@result.Item1.Visible" Attributes="@result.Item2" />
|
||||
</CascadingValue>
|
||||
</CascadingValue>
|
||||
}
|
||||
@Footer
|
||||
</div>
|
||||
}
|
||||
117
Radzen.Blazor/RadzenDropZone.razor.cs
Normal file
117
Radzen.Blazor/RadzenDropZone.razor.cs
Normal file
@@ -0,0 +1,117 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using Microsoft.JSInterop;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// RadzenDropZone component.
|
||||
/// </summary>
|
||||
public partial class RadzenDropZone<TItem> : RadzenComponentWithChildren
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the zone value used to compare items in container Selector function.
|
||||
/// </summary>
|
||||
/// <value>The zone value used to compare items in container Selector function.</value>
|
||||
[Parameter]
|
||||
public object Value { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Footer Templated
|
||||
/// The Footer Template is rendered below the items in the <see cref="RadzenDropZone{TItem}" />
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public RenderFragment Footer { get; set; }
|
||||
|
||||
[CascadingParameter]
|
||||
RadzenDropZoneContainer<TItem> Container { get; set; }
|
||||
|
||||
IEnumerable<TItem> Items
|
||||
{
|
||||
get
|
||||
{
|
||||
return Container.ItemSelector != null ? Container.Data.Where(i => Container.ItemSelector(i, this)) : Enumerable.Empty<TItem>();
|
||||
}
|
||||
}
|
||||
|
||||
internal bool CanDrop()
|
||||
{
|
||||
if (Container.Payload != null)
|
||||
{
|
||||
Container.Payload.ToZone = this;
|
||||
Container.Payload.FromZone = Container.Payload.FromZone;
|
||||
Container.Payload.Item = Container.Payload.Item;
|
||||
}
|
||||
|
||||
var canDrop = Container.CanDrop != null && Container.Payload != null ? Container.CanDrop(Container.Payload) : true;
|
||||
|
||||
return canDrop;
|
||||
}
|
||||
|
||||
internal void OnDragOver(DragEventArgs args)
|
||||
{
|
||||
var canDrop = CanDrop();
|
||||
args.DataTransfer.DropEffect = canDrop ? "move" : "none";
|
||||
cssClass = canDrop ? "rz-can-drop" : "rz-no-drop";
|
||||
}
|
||||
|
||||
void OnDragLeave(DragEventArgs args)
|
||||
{
|
||||
cssClass = "";
|
||||
}
|
||||
|
||||
async Task OnDrop(DragEventArgs args)
|
||||
{
|
||||
cssClass = "";
|
||||
await OnDropInternal();
|
||||
}
|
||||
|
||||
internal async Task OnDropInternal()
|
||||
{
|
||||
if (CanDrop())
|
||||
{
|
||||
await Container.Drop.InvokeAsync(Container.Payload);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
await base.OnAfterRenderAsync(firstRender);
|
||||
|
||||
if (Visible)
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.prepareDrag", Element);
|
||||
}
|
||||
}
|
||||
|
||||
string cssClass;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override string GetComponentCssClass()
|
||||
{
|
||||
return $"rz-dropzone {cssClass}".Trim();
|
||||
}
|
||||
|
||||
Tuple<RadzenDropZoneItemRenderEventArgs<TItem>, IReadOnlyDictionary<string, object>> ItemAttributes(TItem item)
|
||||
{
|
||||
var args = new RadzenDropZoneItemRenderEventArgs<TItem>()
|
||||
{
|
||||
Zone = this,
|
||||
Item = item
|
||||
};
|
||||
|
||||
if (Container.ItemRender != null)
|
||||
{
|
||||
Container.ItemRender(args);
|
||||
}
|
||||
|
||||
return new Tuple<RadzenDropZoneItemRenderEventArgs<TItem>, IReadOnlyDictionary<string, object>>(args, new ReadOnlyDictionary<string, object>(args.Attributes));
|
||||
}
|
||||
}
|
||||
}
|
||||
10
Radzen.Blazor/RadzenDropZoneContainer.razor
Normal file
10
Radzen.Blazor/RadzenDropZoneContainer.razor
Normal file
@@ -0,0 +1,10 @@
|
||||
@typeparam TItem
|
||||
@inherits RadzenComponentWithChildren
|
||||
@if(Visible)
|
||||
{
|
||||
<div @ref="@Element" style="@Style" @attributes="Attributes" class="@GetCssClass()" id="@GetId()">
|
||||
<CascadingValue Value="this">
|
||||
@ChildContent
|
||||
</CascadingValue>
|
||||
</div>
|
||||
}
|
||||
65
Radzen.Blazor/RadzenDropZoneContainer.razor.cs
Normal file
65
Radzen.Blazor/RadzenDropZoneContainer.razor.cs
Normal file
@@ -0,0 +1,65 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// RadzenDropZoneContainer component.
|
||||
/// </summary>
|
||||
#if NET6_0_OR_GREATER
|
||||
[CascadingTypeParameter(nameof(TItem))]
|
||||
#endif
|
||||
public partial class RadzenDropZoneContainer<TItem> : RadzenComponentWithChildren
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the data.
|
||||
/// </summary>
|
||||
/// <value>The data.</value>
|
||||
[Parameter]
|
||||
public IEnumerable<TItem> Data { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the selector function for zone items.
|
||||
/// </summary>
|
||||
/// <value>The selector function for zone items.</value>
|
||||
[Parameter]
|
||||
public Func<TItem, RadzenDropZone<TItem>, bool> ItemSelector { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the function that checks if the item can be dropped in specific zone or item.
|
||||
/// </summary>
|
||||
/// <value>The function that checks if the item can be dropped in specific zone.</value>
|
||||
[Parameter]
|
||||
public Func<RadzenDropZoneItemEventArgs<TItem>, bool> CanDrop { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the row render callback. Use it to set row attributes.
|
||||
/// </summary>
|
||||
/// <value>The row render callback.</value>
|
||||
[Parameter]
|
||||
public Action<RadzenDropZoneItemRenderEventArgs<TItem>> ItemRender { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the template for zone items.
|
||||
/// </summary>
|
||||
/// <value>The template for zone items.</value>
|
||||
[Parameter]
|
||||
public RenderFragment<TItem> Template { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The event callback raised on item drop.
|
||||
/// </summary>
|
||||
/// <value>The event callback raised on item drop.</value>
|
||||
[Parameter]
|
||||
public EventCallback<RadzenDropZoneItemEventArgs<TItem>> Drop { get; set; }
|
||||
|
||||
internal RadzenDropZoneItemEventArgs<TItem> Payload { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override string GetComponentCssClass()
|
||||
{
|
||||
return "rz-dropzone-container";
|
||||
}
|
||||
}
|
||||
}
|
||||
17
Radzen.Blazor/RadzenDropZoneItem.razor
Normal file
17
Radzen.Blazor/RadzenDropZoneItem.razor
Normal file
@@ -0,0 +1,17 @@
|
||||
@inherits RadzenComponent
|
||||
@typeparam TItem
|
||||
@if(Visible)
|
||||
{
|
||||
<div @ref="@Element" style="@Style" @attributes="Attributes" class="@GetCssClass()" id="@GetId()"
|
||||
draggable="@(Attributes.ContainsKey("draggable") ? Attributes["draggable"] : "true")"
|
||||
@ondragstart="@OnDragStart" @ondragover="OnDragOver" @ondragleave="OnDragLeave" @ondragend="OnDragEnd" @ondrop="OnDrop">
|
||||
@if (Container.Template != null)
|
||||
{
|
||||
@Container.Template(Item)
|
||||
}
|
||||
else
|
||||
{
|
||||
@Item
|
||||
}
|
||||
</div>
|
||||
}
|
||||
68
Radzen.Blazor/RadzenDropZoneItem.razor.cs
Normal file
68
Radzen.Blazor/RadzenDropZoneItem.razor.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// RadzenDropZoneItem component.
|
||||
/// </summary>
|
||||
public partial class RadzenDropZoneItem<TItem> : RadzenComponent
|
||||
{
|
||||
[CascadingParameter]
|
||||
TItem Item { get; set; }
|
||||
|
||||
[CascadingParameter]
|
||||
RadzenDropZone<TItem> Zone { get; set; }
|
||||
|
||||
[CascadingParameter]
|
||||
RadzenDropZoneContainer<TItem> Container { get; set; }
|
||||
|
||||
void OnDragStart()
|
||||
{
|
||||
dragCssClass = "rz-dragging";
|
||||
Container.Payload = new RadzenDropZoneItemEventArgs<TItem>()
|
||||
{
|
||||
FromZone = Zone,
|
||||
Item = Item
|
||||
};
|
||||
}
|
||||
|
||||
void OnDragOver(DragEventArgs args)
|
||||
{
|
||||
Container.Payload.ToItem = Item;
|
||||
|
||||
var canDrop = Zone.CanDrop();
|
||||
args.DataTransfer.DropEffect = canDrop ? "move" : "none";
|
||||
cssClass = canDrop ? "rz-can-drop" : "rz-no-drop";
|
||||
|
||||
Zone.OnDragOver(args);
|
||||
}
|
||||
|
||||
void OnDragLeave(DragEventArgs args)
|
||||
{
|
||||
cssClass = "";
|
||||
}
|
||||
|
||||
void OnDragEnd(DragEventArgs args)
|
||||
{
|
||||
dragCssClass = "";
|
||||
}
|
||||
|
||||
async Task OnDrop(DragEventArgs args)
|
||||
{
|
||||
cssClass = "";
|
||||
Container.Payload.ToItem = Item;
|
||||
await Zone.OnDropInternal();
|
||||
}
|
||||
|
||||
string cssClass;
|
||||
string dragCssClass;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override string GetComponentCssClass()
|
||||
{
|
||||
return $"rz-dropzone-item {cssClass} {dragCssClass}".Trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,21 +9,21 @@
|
||||
|
||||
@if (AllowCollapse)
|
||||
{
|
||||
<a title="@TitleAttribute()" aria-label="@AriaLabelAttribute()" @onclick:preventDefault="true"
|
||||
<a id="@(GetId() + "expc")" title="@TitleAttribute()" aria-label="@AriaLabelAttribute()" @onclick:preventDefault="true"
|
||||
aria-controls="rz-fieldset-0-content" aria-expanded="@(collapsed ? "false" : "true")" @onclick=@Toggle
|
||||
tabindex="0" @onkeypress="@(args => OnKeyPress(args, Toggle(new EventArgs())))" @onkeypress:preventDefault=preventKeyPress @onkeypress:stopPropagation>
|
||||
@if (collapsed)
|
||||
{
|
||||
<span class="rz-fieldset-toggler rzi rzi-w rzi-plus"></span>
|
||||
<span class="notranslate rz-fieldset-toggler rzi rzi-w rzi-plus"></span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="rz-fieldset-toggler rzi rzi-w rzi-minus"></span>
|
||||
<span class="notranslate rz-fieldset-toggler rzi rzi-w rzi-minus"></span>
|
||||
}
|
||||
|
||||
@if (!string.IsNullOrEmpty(Icon))
|
||||
{
|
||||
<i class="rzi" style="@(!string.IsNullOrEmpty(IconColor) ? $"color:{IconColor}" : null)">@((MarkupString)Icon)</i><span>@Text</span>
|
||||
<i class="notranslate rzi" style="@(!string.IsNullOrEmpty(IconColor) ? $"color:{IconColor}" : null)">@((MarkupString)Icon)</i><span>@Text</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -36,7 +36,7 @@
|
||||
{
|
||||
@if (!string.IsNullOrEmpty(Icon))
|
||||
{
|
||||
<i class="rzi" style="@(!string.IsNullOrEmpty(IconColor) ? $"color:{IconColor}" : null)">@((MarkupString)Icon)</i><span>@Text</span>
|
||||
<i class="notranslate rzi" style="@(!string.IsNullOrEmpty(IconColor) ? $"color:{IconColor}" : null)">@((MarkupString)Icon)</i><span>@Text</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
<div>
|
||||
@if (IsImage)
|
||||
{
|
||||
<img style="@ImageStyle" src="@Value" @onclick="@OnImageClick" alt="@ImageAlternateText" />
|
||||
<img style="@ImageStyle" src="@ImageValue" @onclick="@OnImageClick" alt="@ImageAlternateText" />
|
||||
}
|
||||
</div>
|
||||
<div>
|
||||
|
||||
@@ -65,7 +65,7 @@ namespace Radzen.Blazor
|
||||
/// Gets the button class list.
|
||||
/// </summary>
|
||||
/// <value>The button class list.</value>
|
||||
ClassList ButtonClassList => ClassList.Create("rz-button rz-button-icon-only rz-light")
|
||||
ClassList ButtonClassList => ClassList.Create("rz-button rz-button-icon-only rz-base rz-shade-default")
|
||||
.AddDisabled(Disabled);
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -100,6 +100,23 @@ namespace Radzen.Blazor
|
||||
}
|
||||
}
|
||||
|
||||
private string ImageValue
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Value == null)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
else if (Value is byte[] bytes)
|
||||
{
|
||||
return System.Text.Encoding.Default.GetString(bytes);
|
||||
}
|
||||
|
||||
return Value.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
async Task OnChange()
|
||||
{
|
||||
string uploadValue;
|
||||
@@ -136,6 +153,11 @@ namespace Radzen.Blazor
|
||||
[JSInvokable("RadzenUpload.OnChange")]
|
||||
public async System.Threading.Tasks.Task OnChange(IEnumerable<PreviewFileInfo> files)
|
||||
{
|
||||
if(files == null || !files.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var file = files.FirstOrDefault();
|
||||
|
||||
FileSize = file.Size;
|
||||
|
||||
@@ -60,6 +60,13 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public string ApiKey { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Google Map Id.
|
||||
/// </summary>
|
||||
/// <value>The Google Map Id.</value>
|
||||
[Parameter]
|
||||
public string MapId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Google map options: https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions.
|
||||
/// </summary>
|
||||
@@ -199,7 +206,7 @@ namespace Radzen.Blazor
|
||||
|
||||
if (firstRender)
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.createMap", Element, Reference, UniqueID, ApiKey, Zoom, Center,
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.createMap", Element, Reference, UniqueID, ApiKey, MapId, Zoom, Center,
|
||||
data.Select(m => new { Title = m.Title, Label = m.Label, Position = m.Position }), Options, FitBoundsToMarkersOnUpdate);
|
||||
}
|
||||
else
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,9 +0,0 @@
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// RadzenGrid.
|
||||
/// </summary>
|
||||
public partial class RadzenGrid<TItem>
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
@typeparam TItem
|
||||
<td style="@Style" @attributes="@Attributes" class="@GetCssClass()" @onclick="@OnClick" @ondblclick="@OnDblClick" >
|
||||
<CascadingValue Value=this>
|
||||
@ChildContent
|
||||
</CascadingValue>
|
||||
</td>
|
||||
@code {
|
||||
[Parameter(CaptureUnmatchedValues = true)]
|
||||
public IReadOnlyDictionary<string, object> Attributes { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string CssClass { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string Style { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public TItem Item { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public RadzenGrid<TItem> Grid { get; set; }
|
||||
|
||||
async Task OnClick()
|
||||
{
|
||||
if (Grid != null)
|
||||
{
|
||||
await Grid.OnRowClick(Item);
|
||||
}
|
||||
}
|
||||
|
||||
async Task OnDblClick()
|
||||
{
|
||||
if (Grid != null)
|
||||
{
|
||||
await Grid.OnRowDblClick(Item);
|
||||
}
|
||||
}
|
||||
|
||||
string GetCssClass()
|
||||
{
|
||||
if (Attributes != null && Attributes.TryGetValue("class", out var @class) && !string.IsNullOrEmpty(Convert.ToString(@class)))
|
||||
{
|
||||
return $"{CssClass} {@class}".Trim();
|
||||
}
|
||||
|
||||
return CssClass;
|
||||
}
|
||||
}
|
||||
@@ -1,341 +0,0 @@
|
||||
@using Radzen
|
||||
@using Radzen.Blazor
|
||||
@implements IDisposable
|
||||
@typeparam TItem
|
||||
@code {
|
||||
public override async Task SetParametersAsync(ParameterView parameters)
|
||||
{
|
||||
if (parameters.DidParameterChange(nameof(Visible), Visible) || parameters.DidParameterChange(nameof(Title), Title))
|
||||
{
|
||||
if (Grid != null)
|
||||
{
|
||||
await Grid.ChangeState();
|
||||
}
|
||||
}
|
||||
|
||||
await base.SetParametersAsync(parameters);
|
||||
}
|
||||
|
||||
string _title;
|
||||
[Parameter]
|
||||
public string Title
|
||||
{
|
||||
get
|
||||
{
|
||||
return _title;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_title != value)
|
||||
{
|
||||
_title = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Parameter]
|
||||
public string Property { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string SortProperty { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string FilterProperty { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public object FilterValue { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public object SecondFilterValue { get; set; }
|
||||
|
||||
string _filterOperator;
|
||||
|
||||
[Parameter]
|
||||
public string FilterOperator
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(_filterOperator))
|
||||
{
|
||||
_filterOperator = Type == "string" && string.IsNullOrEmpty(Format) ? "contains" : "eq";
|
||||
}
|
||||
|
||||
return _filterOperator;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_filterOperator != value)
|
||||
{
|
||||
_filterOperator = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string _secondFilterOperator;
|
||||
[Parameter]
|
||||
public string SecondFilterOperator
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(_secondFilterOperator))
|
||||
{
|
||||
_secondFilterOperator = Type == "string" && string.IsNullOrEmpty(Format) ? "contains" : "eq";
|
||||
}
|
||||
|
||||
return _secondFilterOperator;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_secondFilterOperator != value)
|
||||
{
|
||||
_secondFilterOperator = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Parameter]
|
||||
public LogicalFilterOperator LogicalFilterOperator { get; set; } = LogicalFilterOperator.And;
|
||||
|
||||
Dictionary<string, string> _filterOperators;
|
||||
public Dictionary<string, string> FilterOperators
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_filterOperators == null)
|
||||
{
|
||||
_filterOperators = new Dictionary<string, string>();
|
||||
|
||||
if (Type == "string" && string.IsNullOrEmpty(Format))
|
||||
{
|
||||
_filterOperators.Add("startswith", this.Grid != null ? this.Grid.StartsWithText : "Starts with");
|
||||
_filterOperators.Add("contains", this.Grid != null ? this.Grid.ContainsText : "Contains");
|
||||
_filterOperators.Add("endswith", this.Grid != null ? this.Grid.EndsWithText : "Ends with");
|
||||
}
|
||||
|
||||
_filterOperators.Add("eq", this.Grid != null ? this.Grid.EqualsText : "Equals");
|
||||
_filterOperators.Add("ne", this.Grid != null ? this.Grid.NotEqualsText : "Not equals");
|
||||
|
||||
if (Type != "string" || (Type == "string" && !string.IsNullOrEmpty(Format)))
|
||||
{
|
||||
_filterOperators.Add("lt", this.Grid != null ? this.Grid.LessThanText : "Less than");
|
||||
_filterOperators.Add("le", this.Grid != null ? this.Grid.LessThanOrEqualsText : "Less than or equals");
|
||||
_filterOperators.Add("gt", this.Grid != null ? this.Grid.GreaterThanText : "Greater than");
|
||||
_filterOperators.Add("ge", this.Grid != null ? this.Grid.GreaterThanOrEqualsText : "Greater than or equals");
|
||||
}
|
||||
}
|
||||
|
||||
return _filterOperators;
|
||||
}
|
||||
}
|
||||
|
||||
[Parameter]
|
||||
public string Width { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string Type { get; set; } = "string";
|
||||
|
||||
[Parameter]
|
||||
public string Format { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string FormatString { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string CssClass { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string HeaderCssClass { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string FooterCssClass { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public bool Filterable { get; set; } = true;
|
||||
|
||||
[Parameter]
|
||||
public bool Sortable { get; set; } = true;
|
||||
|
||||
[Parameter]
|
||||
public bool Bubble { get; set; } = true;
|
||||
|
||||
[Parameter]
|
||||
public bool Visible { get; set; } = true;
|
||||
|
||||
[Parameter]
|
||||
public TextAlign TextAlign { get; set; } = TextAlign.Left;
|
||||
|
||||
[Parameter]
|
||||
public RenderFragment<TItem> Template { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public RenderFragment<TItem> EditTemplate { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public RenderFragment HeaderTemplate { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public RenderFragment FooterTemplate { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public RenderFragment<RadzenGridColumn<TItem>> FilterTemplate { get; set; }
|
||||
|
||||
RadzenGrid<TItem> _grid;
|
||||
|
||||
[CascadingParameter]
|
||||
public RadzenGrid<TItem> Grid
|
||||
{
|
||||
get
|
||||
{
|
||||
return _grid;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_grid != value)
|
||||
{
|
||||
_grid = value;
|
||||
_grid.AddColumn(this);
|
||||
|
||||
var property = GetFilterProperty();
|
||||
|
||||
if (!string.IsNullOrEmpty(property))
|
||||
{
|
||||
_filterPropertyType = PropertyAccess.GetPropertyType(typeof(TItem), property);
|
||||
if (_filterPropertyType != null)
|
||||
{
|
||||
if (PropertyAccess.IsNumeric(_filterPropertyType))
|
||||
{
|
||||
Type = "number";
|
||||
}
|
||||
else if (_filterPropertyType == typeof(bool) || _filterPropertyType == typeof(bool?))
|
||||
{
|
||||
Type = "boolean";
|
||||
}
|
||||
else if (_filterPropertyType == typeof(DateTime) || _filterPropertyType == typeof(DateTime?))
|
||||
{
|
||||
Type = "string";
|
||||
Format = "date-time";
|
||||
}
|
||||
else if (_filterPropertyType == typeof(DateTimeOffset) || _filterPropertyType == typeof(DateTimeOffset?))
|
||||
{
|
||||
Type = "string";
|
||||
Format = "date-time-offset";
|
||||
}
|
||||
else if (_filterPropertyType == typeof(Guid) || _filterPropertyType == typeof(Guid?))
|
||||
{
|
||||
Type = "string";
|
||||
Format = "uuid";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Type _filterPropertyType;
|
||||
|
||||
internal Type FilterPropertyType
|
||||
{
|
||||
get
|
||||
{
|
||||
return _filterPropertyType;
|
||||
}
|
||||
}
|
||||
|
||||
public string GetStyle(bool forCell = false)
|
||||
{
|
||||
var style = new List<string>();
|
||||
|
||||
var width = GetWidth();
|
||||
|
||||
if (width != null)
|
||||
{
|
||||
style.Add($"width:{width}");
|
||||
}
|
||||
else if (Grid != null && Grid.ColumnWidth != null)
|
||||
{
|
||||
style.Add($"width:{Grid.ColumnWidth}");
|
||||
}
|
||||
|
||||
if (forCell && TextAlign != TextAlign.Left)
|
||||
{
|
||||
style.Add($"text-align:{Enum.GetName(typeof(TextAlign), TextAlign).ToLower()};");
|
||||
}
|
||||
|
||||
return string.Join(";", style);
|
||||
}
|
||||
|
||||
public string GetSortProperty()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(SortProperty))
|
||||
{
|
||||
return SortProperty;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Property;
|
||||
}
|
||||
}
|
||||
|
||||
internal SortOrder? SortOrder { get; set; }
|
||||
|
||||
public string GetFilterProperty()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(FilterProperty))
|
||||
{
|
||||
return FilterProperty;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Property;
|
||||
}
|
||||
}
|
||||
|
||||
internal void SetFilterValue(object value, bool isFirst = true)
|
||||
{
|
||||
if (Format == "date-time-offset" && value != null && value is DateTime?)
|
||||
{
|
||||
DateTimeOffset? offset = DateTime.SpecifyKind((DateTime)value, DateTimeKind.Utc);
|
||||
value = offset;
|
||||
}
|
||||
|
||||
if (isFirst)
|
||||
{
|
||||
FilterValue = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
SecondFilterValue = value;
|
||||
}
|
||||
}
|
||||
|
||||
internal void SetFilterOperator(string value)
|
||||
{
|
||||
FilterOperator = value;
|
||||
}
|
||||
|
||||
internal void SetSecondFilterOperator(string value)
|
||||
{
|
||||
SecondFilterOperator = value;
|
||||
}
|
||||
|
||||
internal void SetLogicalFilterOperator(LogicalFilterOperator value)
|
||||
{
|
||||
LogicalFilterOperator = value;
|
||||
}
|
||||
|
||||
string runtimeWidth;
|
||||
internal void SetWidth(string value)
|
||||
{
|
||||
runtimeWidth = value;
|
||||
}
|
||||
|
||||
internal string GetWidth()
|
||||
{
|
||||
return !string.IsNullOrEmpty(runtimeWidth) ? runtimeWidth : Width;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Grid?.RemoveColumn(this);
|
||||
}
|
||||
}
|
||||
@@ -120,7 +120,6 @@ namespace Radzen.Blazor
|
||||
ElementReference ContentEditable { get; set; }
|
||||
RadzenTextArea TextArea { get; set; }
|
||||
|
||||
#if NET5_0_OR_GREATER
|
||||
/// <summary>
|
||||
/// Focuses the editor.
|
||||
/// </summary>
|
||||
@@ -136,7 +135,6 @@ namespace Radzen.Blazor
|
||||
return TextArea.Element.FocusAsync();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
internal RadzenHtmlEditorCommandState State { get; set; } = new RadzenHtmlEditorCommandState();
|
||||
|
||||
@@ -192,9 +190,17 @@ namespace Radzen.Blazor
|
||||
public async Task ExecuteCommandAsync(string name, string value = null)
|
||||
{
|
||||
State = await JSRuntime.InvokeAsync<RadzenHtmlEditorCommandState>("Radzen.execCommand", ContentEditable, name, value);
|
||||
|
||||
await OnExecuteAsync(name);
|
||||
Html = State.Html;
|
||||
await OnChange();
|
||||
|
||||
if (Html != State.Html)
|
||||
{
|
||||
Html = State.Html;
|
||||
|
||||
htmlChanged = true;
|
||||
|
||||
await OnChange();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -213,7 +219,11 @@ namespace Radzen.Blazor
|
||||
|
||||
private async Task SourceChanged(string html)
|
||||
{
|
||||
Html = html;
|
||||
if (Html != html)
|
||||
{
|
||||
Html = html;
|
||||
htmlChanged = true;
|
||||
}
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.innerHTML", ContentEditable, Html);
|
||||
await OnChange();
|
||||
StateHasChanged();
|
||||
@@ -221,8 +231,21 @@ namespace Radzen.Blazor
|
||||
|
||||
async Task OnChange()
|
||||
{
|
||||
await ValueChanged.InvokeAsync(Html);
|
||||
await Change.InvokeAsync(Html);
|
||||
if (htmlChanged)
|
||||
{
|
||||
htmlChanged = false;
|
||||
|
||||
_value = Html;
|
||||
|
||||
await ValueChanged.InvokeAsync(Html);
|
||||
|
||||
if (FieldIdentifier.FieldName != null)
|
||||
{
|
||||
EditContext?.NotifyFieldChanged(FieldIdentifier);
|
||||
}
|
||||
|
||||
await Change.InvokeAsync(Html);
|
||||
}
|
||||
}
|
||||
|
||||
internal async Task OnExecuteAsync(string name)
|
||||
@@ -260,6 +283,8 @@ namespace Radzen.Blazor
|
||||
await OnChange();
|
||||
}
|
||||
|
||||
bool htmlChanged = false;
|
||||
|
||||
bool visibleChanged = false;
|
||||
bool firstRender = true;
|
||||
|
||||
@@ -330,7 +355,11 @@ namespace Radzen.Blazor
|
||||
[JSInvokable]
|
||||
public void OnChange(string html)
|
||||
{
|
||||
Html = html;
|
||||
if (Html != html)
|
||||
{
|
||||
Html = html;
|
||||
htmlChanged = true;
|
||||
}
|
||||
Input.InvokeAsync(html);
|
||||
}
|
||||
|
||||
@@ -376,7 +405,7 @@ namespace Radzen.Blazor
|
||||
/// <inheritdoc />
|
||||
protected override string GetComponentCssClass()
|
||||
{
|
||||
return "rz-html-editor";
|
||||
return GetClassList("rz-html-editor").ToString();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -389,5 +418,41 @@ namespace Radzen.Blazor
|
||||
JSRuntime.InvokeVoidAsync("Radzen.destroyEditor", ContentEditable);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the callback which when a file is uploaded.
|
||||
/// </summary>
|
||||
/// <value>The complete callback.</value>
|
||||
[Parameter]
|
||||
public EventCallback<UploadCompleteEventArgs> UploadComplete { get; set; }
|
||||
|
||||
|
||||
internal async Task RaiseUploadComplete(UploadCompleteEventArgs args)
|
||||
{
|
||||
await UploadComplete.InvokeAsync(args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked by interop when the upload is complete.
|
||||
/// </summary>
|
||||
[JSInvokable("OnUploadComplete")]
|
||||
public async Task OnUploadComplete(string response)
|
||||
{
|
||||
System.Text.Json.JsonDocument doc = null;
|
||||
|
||||
if (!string.IsNullOrEmpty(response))
|
||||
{
|
||||
try
|
||||
{
|
||||
doc = System.Text.Json.JsonDocument.Parse(response);
|
||||
}
|
||||
catch (System.Text.Json.JsonException)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
await UploadComplete.InvokeAsync(new UploadCompleteEventArgs() { RawResponse = response, JsonResponse = doc });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,39 +15,57 @@
|
||||
|
||||
Attributes = await Editor.GetSelectionAttributes<ImageAttributes>("img", new[] {"src", "alt", "width", "height"});
|
||||
|
||||
var result = await DialogService.OpenAsync(Title, ds =>
|
||||
@<div class="rz-html-editor-dialog">
|
||||
<div class="rz-html-editor-dialog-item">
|
||||
<label>@SelectText</label>
|
||||
<RadzenUpload ChooseText=@UploadChooseText @ref=@FileUpload Url=@Editor.UploadUrl Auto="false" Accept="image/*"
|
||||
style="width: 100%" Complete="OnUploadComplete" Error="OnUploadError">
|
||||
@foreach (var header in uploadHeaders)
|
||||
{
|
||||
<RadzenUploadHeader Name=@header.Key Value=@header.Value />
|
||||
}
|
||||
var result = await DialogService.OpenAsync(Title, ds => @<div class="rz-html-editor-dialog">
|
||||
<RadzenTemplateForm TItem="ImageAttributes" Data="@Attributes" Submit="OnSubmit">
|
||||
<div class="rz-html-editor-dialog-item">
|
||||
<label>@SelectText</label>
|
||||
@if (Editor.UploadUrl != null)
|
||||
{
|
||||
<RadzenUpload ChooseText=@UploadChooseText @ref=@FileUpload Url=@Editor.UploadUrl Auto="false" Accept="image/*"
|
||||
style="width: 100%" Complete="OnUploadComplete" Error="OnUploadError">
|
||||
@foreach (var header in uploadHeaders)
|
||||
{
|
||||
<RadzenUploadHeader Name=@header.Key Value=@header.Value />
|
||||
}
|
||||
</RadzenUpload>
|
||||
</div>
|
||||
<div class="rz-html-editor-dialog-item">
|
||||
<label>@WidthText</label>
|
||||
<RadzenTextBox @bind-Value=@Attributes.Width style="width: 100%" />
|
||||
</div>
|
||||
<div class="rz-html-editor-dialog-item">
|
||||
<label>@HeightText</label>
|
||||
<RadzenTextBox @bind-Value=@Attributes.Height style="width: 100%" />
|
||||
</div>
|
||||
<div class="rz-html-editor-dialog-item">
|
||||
<label>@UrlText</label>
|
||||
<RadzenTextBox @bind-Value=@Attributes.Src style="width: 100%" />
|
||||
</div>
|
||||
<div class="rz-html-editor-dialog-item">
|
||||
<label>@AltText</label>
|
||||
<RadzenTextBox @bind-Value=@Attributes.Alt style="width: 100%" />
|
||||
</div>
|
||||
<div class="rz-html-editor-dialog-buttons">
|
||||
<RadzenButton Text=@OkText Click="OnSubmit" />
|
||||
<RadzenButton Text=@CancelText Click="()=> ds.Close(false)" ButtonStyle="ButtonStyle.Secondary" />
|
||||
</div>
|
||||
} else {
|
||||
<RadzenFileInput Accept="image/*" ChooseText=@UploadChooseText @bind-Value=@Attributes.Src style="width: 100%" />
|
||||
}
|
||||
</div>
|
||||
@if (ShowWidth)
|
||||
{
|
||||
<div class="rz-html-editor-dialog-item">
|
||||
<label>@WidthText</label>
|
||||
<RadzenTextBox @bind-Value=@Attributes.Width style="width: 100%" />
|
||||
</div>
|
||||
}
|
||||
@if (ShowHeight)
|
||||
{
|
||||
<div class="rz-html-editor-dialog-item">
|
||||
<label>@HeightText</label>
|
||||
<RadzenTextBox @bind-Value=@Attributes.Height style="width: 100%" />
|
||||
</div>
|
||||
}
|
||||
@if (ShowSrc)
|
||||
{
|
||||
<div class="rz-html-editor-dialog-item">
|
||||
<label>@UrlText</label>
|
||||
<RadzenTextBox @bind-Value=@Attributes.Src style="width: 100%" />
|
||||
</div>
|
||||
}
|
||||
@if (ShowAlt)
|
||||
{
|
||||
<div class="rz-html-editor-dialog-item">
|
||||
<label>@AltText</label>
|
||||
<RadzenTextBox @bind-Value=@Attributes.Alt style="width: 100%" />
|
||||
</div>
|
||||
}
|
||||
<div class="rz-html-editor-dialog-buttons">
|
||||
<RadzenButton Text=@OkText ButtonType="ButtonType.Submit" />
|
||||
<RadzenButton Text=@CancelText Click="()=> ds.Close(false)" ButtonStyle="ButtonStyle.Secondary" />
|
||||
</div>
|
||||
</RadzenTemplateForm>
|
||||
</div>
|
||||
);
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,12 +81,36 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public string HeightText { get; set; } = "Image Height";
|
||||
|
||||
/// <summary>
|
||||
/// Specifies whether to show the image width section. Set it to false to hide it. Default value is true.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool ShowWidth { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies whether to show the image height section. Set it to false to hide it. Default value is true.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool ShowHeight { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies whether to show the web address section. Set it to false to hide it. Default value is true.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool ShowSrc { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies whether to show the alternative text section. Set it to false to hide it. Default value is true.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool ShowAlt { get; set; } = true;
|
||||
|
||||
ImageAttributes Attributes { get; set; }
|
||||
RadzenUpload FileUpload { get; set; }
|
||||
|
||||
async Task OnSubmit()
|
||||
{
|
||||
if (FileUpload.HasValue)
|
||||
if (FileUpload?.HasValue == true)
|
||||
{
|
||||
await FileUpload.Upload();
|
||||
}
|
||||
@@ -107,6 +131,8 @@ namespace Radzen.Blazor
|
||||
{
|
||||
DialogService.Close(true);
|
||||
}
|
||||
|
||||
await Editor.RaiseUploadComplete(args);
|
||||
}
|
||||
|
||||
async Task OnUploadError(UploadErrorEventArgs args)
|
||||
|
||||
@@ -20,28 +20,29 @@
|
||||
blank = true;
|
||||
}
|
||||
|
||||
var result = await DialogService.OpenAsync(Title, ds =>
|
||||
@<div class="rz-html-editor-dialog">
|
||||
<div class="rz-html-editor-dialog-item">
|
||||
<label>@UrlText</label>
|
||||
<RadzenTextBox @bind-Value=@attributes.Href style="width: 100%" />
|
||||
</div>
|
||||
@if (string.IsNullOrWhiteSpace(attributes.InnerHtml) || attributes.InnerHtml == "<br>")
|
||||
{
|
||||
<div class="rz-html-editor-dialog-item">
|
||||
<label>@LinkText</label>
|
||||
<RadzenTextBox @bind-Value=@attributes.InnerText style="width: 100%" />
|
||||
</div>
|
||||
}
|
||||
<div class="rz-html-editor-dialog-item">
|
||||
<RadzenCheckBox @bind-Value=@blank />
|
||||
<label>@OpenInNewWindowText</label>
|
||||
</div>
|
||||
<div class="rz-html-editor-dialog-buttons">
|
||||
<RadzenButton Text=@OkText Click="()=> ds.Close(true)" />
|
||||
<RadzenButton Text=@CancelText Click="()=> ds.Close(false)" ButtonStyle="ButtonStyle.Secondary" />
|
||||
</div>
|
||||
</div>);
|
||||
var result = await DialogService.OpenAsync(Title, ds => @<div class="rz-html-editor-dialog">
|
||||
<RadzenTemplateForm TItem="LinkAttributes" Data="@attributes" Submit="() => ds.Close(true)">
|
||||
<div class="rz-html-editor-dialog-item">
|
||||
<label>@UrlText</label>
|
||||
<RadzenTextBox @bind-Value=@attributes.Href style="width: 100%" />
|
||||
</div>
|
||||
@if (string.IsNullOrWhiteSpace(attributes.InnerHtml) || attributes.InnerHtml == "<br>")
|
||||
{
|
||||
<div class="rz-html-editor-dialog-item">
|
||||
<label>@LinkText</label>
|
||||
<RadzenTextBox @bind-Value=@attributes.InnerText style="width: 100%" />
|
||||
</div>
|
||||
}
|
||||
<div class="rz-html-editor-dialog-item">
|
||||
<RadzenCheckBox @bind-Value=@blank />
|
||||
<label>@OpenInNewWindowText</label>
|
||||
</div>
|
||||
<div class="rz-html-editor-dialog-buttons">
|
||||
<RadzenButton Text=@OkText ButtonType="ButtonType.Submit" />
|
||||
<RadzenButton Text=@CancelText Click="()=> ds.Close(false)" ButtonStyle="ButtonStyle.Secondary" />
|
||||
</div>
|
||||
</RadzenTemplateForm>
|
||||
</div>);
|
||||
|
||||
await Editor.RestoreSelectionAsync();
|
||||
|
||||
@@ -58,6 +59,5 @@
|
||||
|
||||
await Editor.ExecuteCommandAsync("insertHTML", html.ToString());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
@using Radzen.Blazor.Rendering
|
||||
@inherits RadzenHtmlEditorButtonBase
|
||||
|
||||
<EditorButton Title=@Title Shortcut=@Shortcut Click=@OnClick Icon="format_underline" Selected=@Editor.State.Underline />
|
||||
<EditorButton Title=@Title Shortcut=@Shortcut Click=@OnClick Icon="format_underlined" Selected=@Editor.State.Underline />
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user