Compare commits

...

498 Commits

Author SHA1 Message Date
Vladimir Enchev
990337e4f4 Version updated 2022-11-09 10:05:20 +02:00
Vladimir Enchev
c35cce7b34 Fixed onmouseenter incompatibility with .NET 7.0
Fix #689
2022-11-09 09:02:48 +02:00
Vladimir Enchev
cb36e60af7 sdk path changed 2022-11-08 19:19:24 +02:00
Vladimir Enchev
65baef92b1 .NET 7 support added 2022-11-08 19:16:34 +02:00
Vladimir Enchev
c624db6833 Merge branch 'master' of https://github.com/radzenhq/radzen-blazor 2022-11-08 17:14:24 +02:00
Vladimir Enchev
8aed964f47 DatePicker current day "rz-datepicker-currentday" CSS class added
Fix #688
2022-11-08 17:13:44 +02:00
Daniel Nutu
3874cb93e1 fix quotation marks for alert component (#686)
Co-authored-by: DanielNutu <daniel.nutu@kyndryl.com>
2022-11-08 16:57:02 +02:00
Vladimir Enchev
f966d7ab99 Fixed DataGrid ignores sort order when data takes long to load
Fix #687
2022-11-08 16:56:20 +02:00
Vladimir Enchev
2079705626 DatePicker AM/PM buttons style fixed 2022-11-08 09:51:55 +02:00
Atanas Korchev
e0a56d350b Improve support for cases when all RadzenChart series values are negative. Fixes #685. 2022-11-08 09:24:35 +02:00
David Tosi
181aa4f43b Added click event support to the popup Notification Message. (#682)
Co-authored-by: David Tosi <davidtosi@inphonite.com>
2022-11-08 09:24:25 +02:00
Vladimir Enchev
302ba9be44 version updated 2022-11-07 09:56:33 +02:00
Vladimir Enchev
77422c8dda DropDown examples separated 2022-11-04 16:20:31 +02:00
Vladimir Enchev
eead43e0d9 Use getter instead reflection in DropDownBase 2022-11-04 15:09:13 +02:00
Vladimir Enchev
87927d04aa DataGrid settings not saved properly on simple DateTime filter 2022-11-04 14:44:59 +02:00
Vladimir Enchev
aa1b4b2785 Fixed SelectBar items will not show tooltip 2022-11-04 14:31:39 +02:00
Vladimir Enchev
a7f1d7181d DropDownBase will keep selected items by value if ValueProperty is set 2022-11-04 14:11:55 +02:00
Vladimir Enchev
c4a50efa43 version updated 2022-11-03 17:32:35 +02:00
Vladimir Enchev
b30f7d95e2 Dialog Draggable=true fixed 2022-11-03 17:32:13 +02:00
mafei1982
845b8aac1b Fix issue #680 (#681)
* fix issue #673 When trying to filter on a property from parent interface (Current Titem type is also an interface), the FilterPropertyType is null

* rename the private method

* Fix the refactor issue

* Fix issue #680
2022-11-03 13:52:19 +02:00
Vladimir Enchev
d449469a99 DialogService Alert dialog added 2022-11-03 11:28:56 +02:00
Vladimir Enchev
776ae01c7b Close all popups on dialog open 2022-11-03 09:38:58 +02:00
Vladimir Enchev
a9951fc624 DataGrid Save/Load settings with enum filtering fixed
Fix #677
2022-11-02 17:16:26 +02:00
Vladimir Enchev
d8dfcd9cf7 version updated 2022-11-02 09:01:09 +02:00
mafei1982
fac6744ead Fix the missing call to get the type of the property for the interface (#676)
* fix issue #673 When trying to filter on a property from parent interface (Current Titem type is also an interface), the FilterPropertyType is null

* rename the private method

* Fix the refactor issue
2022-11-02 08:39:26 +02:00
Vladimir Enchev
0a539d1328 DataGrid self-ref hierarchy filtering fixed 2022-11-01 20:03:25 +02:00
Vladimir Enchev
3e137d1c0e Tree item expanded state cannot be changed when bound to model
https://forum.radzen.com/t/ontreenodecollapse-backfires-to-ontreenodeexpand-immediately/12122
2022-11-01 16:19:40 +02:00
Vladimir Enchev
8391556f8f code refactored 2022-11-01 11:18:39 +02:00
mafei1982
365374e73e fix issue #673 When trying to filter on a property from parent interf… (#674)
* fix issue #673 When trying to filter on a property from parent interface (Current Titem type is also an interface), the FilterPropertyType is null

* rename the private method
2022-11-01 11:09:56 +02:00
Vladimir Enchev
19a118c096 themes updated 2022-10-31 16:32:15 +02:00
Vladimir Enchev
62a5505c9d disclaimer restored 2022-10-31 16:22:54 +02:00
Vladimir Enchev
60dcb66805 MaterialDark and Fluent themes updated 2022-10-31 16:20:23 +02:00
Vladimir Enchev
51e6306c19 Version updated 2022-10-31 12:01:23 +02:00
yordanov
683453f63a Update alert close button shades 2022-10-31 11:56:26 +02:00
yordanov
366e042c60 Add base-styles-map to dark theme 2022-10-31 11:56:26 +02:00
yordanov
e599d96b7f Update Alert message margins in different sizes 2022-10-31 11:56:26 +02:00
Vladimir Enchev
6f3fde82ef Close button size improved 2022-10-31 11:56:26 +02:00
yordanov
8ba561b55b Add --rz-alert-icon-size 2022-10-31 11:56:26 +02:00
Vladimir Enchev
79ac8e8cd8 Alert ShowIcon property added 2022-10-31 11:56:26 +02:00
yordanov
cb809156f2 Update Alert icons 2022-10-31 11:56:26 +02:00
Vladimir Enchev
d8aa4dde98 getIcon() fixed 2022-10-31 11:56:26 +02:00
yordanov
938fd759c1 Update Alert icons and close button colors 2022-10-31 11:56:26 +02:00
yordanov
2740f54331 Add base, light and dark styles to Alert 2022-10-31 11:56:26 +02:00
Vladimir Enchev
6f929e48b8 example name fixed and docs link removed 2022-10-31 11:56:26 +02:00
yordanov
308db7888a Add Alert Styling demo 2022-10-31 11:56:26 +02:00
yordanov
657a5c5416 Add AlertSize and update scss 2022-10-31 11:56:26 +02:00
Vladimir Enchev
d12f3921f9 code fixed 2022-10-31 11:56:26 +02:00
Vladimir Enchev
601957ba2a Alert Icon property added. Different Icon and close button depending on AlertStyle 2022-10-31 11:56:26 +02:00
yordanov
e12ffb1a75 Add more examples to Alert demo 2022-10-31 11:56:26 +02:00
yordanov
25543b363b Add initial Alert styling 2022-10-31 11:56:26 +02:00
yordanov
3e8ab559b2 Update Alert links in demos navigation 2022-10-31 11:56:26 +02:00
Vladimir Enchev
9059f3f60b Alert component added 2022-10-31 11:56:26 +02:00
Atanas Korchev
aa4ce25bda RadzenLogin does not fire the Login event. Fixes #670. 2022-10-28 20:59:13 +03:00
Atanas Korchev
5ecd9e0782 Setting Stroke of RadzenGridLines has no visual effect. Fixes #669. 2022-10-28 10:20:32 +03:00
Vladimir Enchev
ba84cc7ea6 DropDown/AutoComplete PopupStyle property added instead PopupHeight 2022-10-28 09:20:04 +03:00
Vladimir Enchev
7edae77736 DropDown/AutoComplete PopupHeight property added 2022-10-27 18:22:42 +03:00
Vladimir Enchev
b5f414623e version updated 2022-10-27 09:41:52 +03:00
yordanov
58c92c94f6 Fix 'remember me' margin in Login 2022-10-27 09:37:01 +03:00
yordanov
3f0509b0b9 Remove absolute position of rz-messages-error and width of components in rz-form 2022-10-27 09:23:14 +03:00
yordanov
33858d2679 Fix chart axis font-size 2022-10-26 16:01:40 +03:00
Vladimir Enchev
5d3b4fab0b re-subscribe to FilterValueChange on property change 2022-10-26 15:46:17 +03:00
Vladimir Enchev
6f998cffe9 Member access of interface properties fixed
Fix #665
2022-10-26 15:33:19 +03:00
yordanov
1f520b904f Add margin to remember me switch 2022-10-26 13:18:19 +03:00
yordanov
94c49deaf7 Fix Switch hover outline in material theme 2022-10-26 12:20:49 +03:00
yordanov
4360896634 Add vertical-align: middle to RadzenLabel 2022-10-26 12:16:58 +03:00
yordanov
8513edc118 Add vertical-align: middle to Switch 2022-10-26 12:16:27 +03:00
Atanas Korchev
6dc08ede91 Implement AllowRememberMe functionality in RadzenLogin. 2022-10-26 10:47:28 +03:00
Vladimir Enchev
8f05520c2f Fixed DropDownBase SelectItem() will not work properly in case of IEnummerable with nullable element type 2022-10-25 18:42:30 +03:00
yordanov
0c3878a8fc Improve dialog responsiveness and refactor styles 2022-10-25 09:58:08 +03:00
Vladimir Enchev
e0d9fa6e95 Fixed DataGrid Groups not loaded properly from settings
Fix #664
2022-10-25 09:00:48 +03:00
yordanov
ef5f613b0b Update material dialog content padding and title 2022-10-24 17:41:36 +03:00
Vladimir Enchev
8617557084 Version updated 2022-10-24 17:38:32 +03:00
Vladimir Enchev
55c0fe05cc Fixed virtualized DataGrid exception with LoadData 2022-10-24 17:38:14 +03:00
yordanov
bdaaa9643e Remove duplicate styles of rz-helper-hidden-accessible 2022-10-24 14:09:29 +03:00
yordanov
883ab83c91 Fix box-sizing and trimmed dropdown label with bootstrap 4.6. Resolves #662 2022-10-24 13:18:44 +03:00
Vladimir Enchev
6df9a499ef Version updated 2022-10-24 11:07:10 +03:00
yordanov
2bbb6919b6 Fix initial width of dropdown. Related to #662 2022-10-24 10:44:18 +03:00
Vladimir Enchev
44e0102073 Get first element type only for in-memory data 2022-10-24 09:55:00 +03:00
Vladimir Enchev
a772a2dd51 Fixed DropDownBase support for non generic IEnumerable
Fix #657
2022-10-24 09:26:11 +03:00
Vladimir Enchev
8cd812cf33 DataGrid PageSizeChanged event added 2022-10-24 09:14:10 +03:00
msdevcode
dbf30f4869 Tabindex depending on Disabled-property (#656) 2022-10-24 07:37:04 +03:00
Atanas Korchev
3b5ec52a06 Add ability to customize the scheduler week view header text. 2022-10-23 19:00:24 +03:00
Vladimir Enchev
740e39fb46 Social OnAfterRender changed to OnAfterRenderAsync 2022-10-21 16:34:10 +03:00
Vladimir Enchev
44fff4fc0a Version updated 2022-10-21 16:18:11 +03:00
Vladimir Enchev
acc3a0c9d4 DataFilter FilterProperty FilterOperator change fixed 2022-10-21 16:17:35 +03:00
yordanov
e9f7f9d027 Update width of pickers in datafilter 2022-10-21 15:38:14 +03:00
Vladimir Enchev
3ff9bcf853 Version updated 2022-10-21 10:18:46 +03:00
Vladimir Enchev
18dd011a84 Fixed DataGrid numeric filter will not save settings
Fix #654
2022-10-21 10:10:28 +03:00
Vladimir Enchev
5ccfd4e838 Fixed DataGrid raising twice RowClick/CellClick/RowSelect on double click 2022-10-21 10:00:13 +03:00
Vladimir Enchev
b0baad56e7 DropDown binding and rendering optimized 2022-10-20 19:10:39 +03:00
Vladimir Enchev
0732938d1d Version updated 2022-10-20 10:02:12 +03:00
yordanov
1df2d8da9b Use correct label padding scss variable in dropdown 2022-10-20 09:57:11 +03:00
Vladimir Enchev
dfdc7567f5 DropDownDataGrid chips rendering improved 2022-10-20 09:54:30 +03:00
Vladimir Enchev
3453b7f84c DataFilter FilterTemplate fixed 2022-10-19 13:47:04 +03:00
yordanov
59137196c6 Change dropdown display to inline-flex 2022-10-19 10:49:57 +03:00
Vladimir Enchev
8d686da3fb DataGrid in-line demo improved
Fix #652
2022-10-19 09:31:03 +03:00
Vladimir Enchev
10aa459ebd Fixed Tree will not hide expand/collapse icon when HasChildren changed runtime 2022-10-18 19:34:27 +03:00
msdevcode
a3737624fe Radzen.Blazor.Tests-Project fix (#649) 2022-10-17 21:31:57 +03:00
Vladimir Enchev
70dd7d8744 DataFilter documentation link removed 2022-10-17 15:44:21 +03:00
Vladimir Enchev
8d52a98504 Version updated 2022-10-17 14:47:48 +03:00
yordanov
994166c88f Fix gutter width in dark theme 2022-10-17 13:11:44 +03:00
yordanov
2a9252b53b Add borders to composite cells 2022-10-17 13:04:57 +03:00
Vladimir Enchev
e8ff2a36be Merge branch 'master' of https://github.com/radzenhq/radzen-blazor 2022-10-17 11:50:24 +03:00
Vladimir Enchev
9ac700b758 rz-grid-table-composite added in case of composite columns 2022-10-17 11:42:06 +03:00
yordanov
1bf994384d Fix spacing between css classes 2022-10-17 11:36:17 +03:00
yordanov
0258389b61 Update number of components 2022-10-17 11:06:11 +03:00
yordanov
8491807987 Update package tags 2022-10-17 10:54:03 +03:00
Vladimir Enchev
e95d07fee1 Fixed virtualized DataGrid bound with LoadData not scrolled to top on sort 2022-10-17 09:49:01 +03:00
Vladimir Enchev
7b0d07e116 DataGrid second filter value not saved properly in Settings 2022-10-17 09:18:19 +03:00
msdevcode
5228ed8543 RadzenSelectBar - RadzenSelectBarItem add disabled-property (#647) 2022-10-17 09:15:06 +03:00
Vladimir Enchev
8f5550576f Fixed DataGrid save settings in case of column FIlterTemplate 2022-10-14 10:09:19 +03:00
Vladimir Enchev
c51e4b5411 Fixed DataGrid paging with Settings when bound with LoadData and
Fix #644
2022-10-14 09:55:42 +03:00
yordanov
ef3918f50c Fix PanelMenu expand/collapse with ripple 2022-10-13 16:57:29 +03:00
Vladimir Enchev
2b29e5371d Version updated 2022-10-13 08:49:58 +03:00
Vladimir Enchev
249815607e Fixed DataGrid groups not saved properly in Settings
Fix #642
2022-10-13 08:48:58 +03:00
Vladimir Enchev
b9f9138ae4 DropDown with groups demo filtering fixed
Fix #641
2022-10-12 08:57:41 +03:00
Vladimir Enchev
00296bacf2 DataGrid grouping API demo improved 2022-10-11 12:05:13 +03:00
Vladimir Enchev
18e6771fcc Delay added to TooltipOptions 2022-10-11 10:21:59 +03:00
yordanov
0c8131ebb3 Fix icon alignment in fieldset legend 2022-10-10 15:27:39 +03:00
Vladimir Enchev
831f0209ae Map demo update with InfoWindow 2022-10-10 15:18:36 +03:00
Vladimir Enchev
488fc2719f Fixed collection was modified exception in DropDownDataGrid
Fix #639
2022-10-06 16:35:49 +03:00
yordanov
ba98d6dfef Show up down arrows in Numeric with text-align 2022-10-06 09:45:10 +03:00
Vladimir Enchev
45d9b69191 version updated 2022-10-06 09:41:19 +03:00
yordanov
5205c94c73 Update Dialog demos 2022-10-06 09:35:25 +03:00
Vladimir Enchev
953bc6370a Tree Collapse event added 2022-10-06 09:14:41 +03:00
Ernesto Roque
7ffd7b10f5 adding Chips support to DropDownDataGrid (#637) 2022-10-06 08:50:59 +03:00
Vladimir Enchev
2a054bce6e Numeric CSS classes fixed 2022-10-05 18:32:42 +03:00
yordanov
de1ed66aaa Fix numeric input right padding 2022-10-05 17:44:51 +03:00
yordanov
caeeee9109 Update validation styles in Login component 2022-10-05 17:31:24 +03:00
Vladimir Enchev
3c9368b05f DataGrid save/load Settings for PageSize change fixed
Fix #633
2022-10-04 09:58:39 +03:00
yordanov
e31567727a Update project icon 2022-10-04 09:39:46 +03:00
nanocortex
7b761c50d7 Add Separator parameter to Dropdown (#631) 2022-10-03 20:19:00 +03:00
Vladimir Enchev
11306a3ce5 Version updated 2022-10-03 17:18:18 +03:00
yordanov
9d23d4df1f Update DataGrid inline editing demo 2022-10-03 16:34:28 +03:00
yordanov
45c35d1d37 DataGrid Density styles and demo 2022-10-03 15:48:29 +03:00
Vladimir Enchev
7b1c7cbcb2 DataGrid Density property added 2022-10-03 15:05:28 +03:00
Vladimir Enchev
01b4431627 DataGrid simple filter row frozen cells class fixed 2022-10-03 14:39:41 +03:00
yordanov
70b478a4b7 Add ExtraSmall button size 2022-10-03 12:10:07 +03:00
Christian Gräfe
6e7d227504 Added Text-Align to RadzenNumeric (#627) 2022-10-03 10:33:35 +03:00
Charles-André Beaudry
962afaf613 [Docs] Fix miscellaneous annoyances in the docs (#622)
* Adjust indentation

* Remove html leftovers?
2022-10-03 10:32:37 +03:00
Vladimir Enchev
ad0ba5d3bf CheckBoxList AllowSelectAll and SelectAllText properties added
Fix #628
2022-10-03 10:31:35 +03:00
Vladimir Enchev
6c729deb77 Tooltip will execute TooltipService.Close when closing on outside click or duration 2022-09-30 11:15:59 +03:00
Vladimir Enchev
0e887d8b28 ContextMenu will execute ContextMenuService.Close event when clicking outside 2022-09-30 11:08:41 +03:00
Vladimir Enchev
8fdaf68707 Fixed DataGrid filtering by bool column will not save settings 2022-09-30 10:13:10 +03:00
Atanas Korchev
0bbbf70e81 Update premium themes. 2022-09-29 17:55:29 +03:00
yordanov
1342c306a3 Add updated tag to Menu demos 2022-09-29 17:38:26 +03:00
yordanov
8890ae4520 Fix tabs padding in material theme 2022-09-29 17:26:56 +03:00
yordanov
72d6fa5454 Set bootstrap grid-gutter-width value to 2rem 2022-09-29 16:07:35 +03:00
Vladimir Enchev
1f700a80bc Version updated 2022-09-29 15:05:17 +03:00
yordanov
d9a25c88e7 Make dropdown label right padding as smaller as possible 2022-09-29 13:51:55 +03:00
yordanov
e060b80b67 Update css selectors for DataGrid selection 2022-09-29 13:26:00 +03:00
yordanov
45687e665d Scope grid alternating rows to tbody only. Fixes #625 2022-09-29 13:10:38 +03:00
yordanov
5a3dffbc98 Update Menu demo page 2022-09-29 12:07:11 +03:00
yordanov
9e932f025f Reduce top item x-padding in material menu 2022-09-29 12:06:47 +03:00
yordanov
5ea729d0d0 Update Menu styling. Fixes #623 2022-09-29 11:12:43 +03:00
yordanov
67b6c52031 Fix sidebar z-index 2022-09-29 11:12:43 +03:00
yordanov
8b9c26c12b Fix grid data row class in table-reflow 2022-09-29 11:12:43 +03:00
Vladimir Enchev
bede7d3fc9 DataGrid settings saved on clear column filter 2022-09-29 11:06:46 +03:00
Vladimir Enchev
cf2d4b890a preventPopupDefault removed 2022-09-29 09:14:37 +03:00
Vladimir Enchev
3aa05efe9c Fixed cannot edit DatePicker time parts 2022-09-28 22:40:08 +03:00
Vladimir Enchev
ac00b513a8 DataGrid columns reset on Settings clear 2022-09-28 21:19:18 +03:00
Vladimir Enchev
7fb4f6de65 DataGrid column filter saved in settings cleared on filter 2022-09-28 21:07:48 +03:00
yordanov
26251a2158 Grid alternating rows inverted 2022-09-28 16:51:22 +03:00
Vladimir Enchev
4a0b1f8f10 DataGrid exception fixed on select/deselect all columns from column picker 2022-09-28 16:40:55 +03:00
Vladimir Enchev
d6cce4a11b Fixed Tree AllowCheckParents behavior
Fix #593
2022-09-28 16:32:05 +03:00
Vladimir Enchev
2ad79ea3d1 DataGrid self-ref items indent with multiple parent items on same level fixed
Fix #617
2022-09-28 12:30:47 +03:00
Vladimir Enchev
82ce761b88 DataGrid AllowPickAllColumns property added 2022-09-28 09:18:37 +03:00
Vladimir Enchev
d1241a6997 DropDown/ListBox AllowSelectAll property added 2022-09-28 09:07:32 +03:00
Vladimir Enchev
eb28720cd2 code fixed 2022-09-27 18:42:53 +03:00
Vladimir Enchev
436a36a704 Version updated 2022-09-27 18:30:54 +03:00
yordanov
c2298b2ae0 Fix selectable grid row hover styles 2022-09-27 17:30:01 +03:00
Vladimir Enchev
9bc1431291 rz-data-row class added to DataGrid data rows 2022-09-27 17:13:18 +03:00
yordanov
695a57153a Update standard base theme pager buttons and shadows 2022-09-27 16:00:35 +03:00
yordanov
b19ce01e2e Fix Pager selected button padding 2022-09-27 16:00:35 +03:00
Vladimir Enchev
d0c74b73dc DataGrid simple filter mode with nullable enums improved
Fix #620
2022-09-27 15:47:07 +03:00
yordanov
673fce5054 Fix background of menu top items with material theme 2022-09-27 15:26:22 +03:00
yordanov
9195f7ed31 Fix alignment of menu top items and reorder scss variables 2022-09-27 15:25:23 +03:00
yordanov
baf97b205f Fix steps widget content overflow 2022-09-27 13:23:34 +03:00
Vladimir Enchev
13da03396f Fixed touch keyboard closes popup in Windows 2022-09-27 09:05:00 +03:00
Vladimir Enchev
52846e3bf2 avoid null ref. exception on string filter 2022-09-26 21:47:24 +03:00
Vladimir Enchev
164c43e2e5 DataFilterProperty GetFilterOperators() made virtual and example added 2022-09-26 21:42:31 +03:00
Vladimir Enchev
3af93df990 Version updated 2022-09-26 16:40:44 +03:00
Vladimir Enchev
6026d27b18 LoadSettings code improved 2022-09-26 16:20:05 +03:00
Vladimir Enchev
ba8786c4fe DataGrid load settings fixed 2022-09-26 16:18:19 +03:00
Atanas Korchev
5650349868 Premium themes (#619)
* Show premium themes in the online demo.

* Set the id of the theme dropdown.

* Update colors in theme picker

* Style theme picker with Pro badges

* Update pro themes.

Co-authored-by: yordanov <vasil@yordanov.info>
2022-09-26 14:15:10 +03:00
yordanov
8bd3c32a65 Update logos 2022-09-26 12:05:56 +03:00
Vladimir Enchev
07623acf41 Save/load settings demo reworked to use ProtectedLocalStorage 2022-09-26 11:22:57 +03:00
Vladimir Enchev
446629b9f8 DataGridSettingsService deleted 2022-09-26 11:09:35 +03:00
Vladimir Enchev
21dca42e33 Save/Load settings demo reworked 2022-09-26 11:01:15 +03:00
Vladimir Enchev
7c5c9fc8be demo text updated 2022-09-26 09:59:48 +03:00
Vladimir Enchev
b2262ad4b8 Version updated 2022-09-26 09:54:22 +03:00
Vladimir Enchev
4f7aba1e4b PageSize added to DataGridSettings 2022-09-26 09:48:01 +03:00
Vladimir Enchev
2bfbc68df8 Save/Load DataGrid runtime settings added (#618) 2022-09-26 09:44:43 +03:00
yordanov
682ae2ed59 Update logos on demos homepage 2022-09-26 09:40:59 +03:00
yordanov
a13705c1fe Fix link text decoration in Panel, SplitButton and Steps with -base themes 2022-09-23 17:25:00 +03:00
yordanov
e4f4ba46f5 Add rz- prefix to all login CSS classes 2022-09-23 16:40:08 +03:00
yordanov
1f4b343a2e Update Login component CSS classes and styles 2022-09-23 16:36:10 +03:00
yordanov
f4e01f42c5 Add pointer cursor to rz-link 2022-09-23 16:36:10 +03:00
Vladimir Enchev
7416ea1a54 DropDownBase HasValue will check if value has items in case of multiple selection 2022-09-23 14:02:49 +03:00
yordanov
b9593b7b4c Add font-smoothing to demos 2022-09-23 10:12:28 +03:00
yordanov
43d7725522 Fix cards position 2022-09-23 10:12:28 +03:00
aaayd
d8d3a392b2 Implement Navigation on Filtered Sidebar (#612)
Implements navigation on the sidebar when filtered with navigation items which do not include children.
This will also implement the Icon for the navigation item.
2022-09-23 09:26:54 +03:00
starkuss
5a36e72616 enable possibility to add custom css class to dialog (#616) 2022-09-23 09:25:37 +03:00
Atanas Korchev
e9bfe72914 Update docs to use base themes instead of full. 2022-09-22 18:58:07 +03:00
Vladimir Enchev
db23f28388 Version updated 2022-09-22 17:09:32 +03:00
yordanov
46bd9a5324 Update demos to use Bootstrap 5 layout css classes 2022-09-22 16:48:22 +03:00
yordanov
d225b6d454 Scope base themes to style radzen components only 2022-09-22 16:48:22 +03:00
yordanov
17fb991744 Add theme's font-family to RadzenText component 2022-09-22 16:48:22 +03:00
yordanov
1035d413de Add --rz-text-font-family and --rz-body-background-color css variables 2022-09-22 16:48:22 +03:00
yordanov
9bbccb72e4 Fix fieldset legend float in Bootstrap 5 2022-09-22 16:48:22 +03:00
yordanov
4b525256fb Fix link text-decoration in components 2022-09-22 16:48:22 +03:00
Vladimir Enchev
960059e307 DataFilter should filter on operator change 2022-09-22 10:58:52 +03:00
Atanas Korchev
0941627527 Use full bootstrap and -base.css for the themes. 2022-09-22 10:18:13 +03:00
Vladimir Enchev
efea8c451b DataGrid self-reference filtering improved 2022-09-22 09:43:36 +03:00
Vladimir Enchev
d9811f4ff1 datafilter link fixed 2022-09-21 18:32:45 +03:00
Vladimir Enchev
11e6713f20 README.md path fixed 2022-09-21 17:43:48 +03:00
Vladimir Enchev
0d37538778 Version updated 2022-09-21 17:40:42 +03:00
yordanov
c88f8bb277 Update grid hieararchy demo tags 2022-09-21 17:29:40 +03:00
yordanov
cd8a8ba310 Update styles for alternating rows 2022-09-21 17:16:30 +03:00
yordanov
9cb81c5fb8 Update new/updated demo tags 2022-09-21 16:31:24 +03:00
Vladimir Enchev
e2d3dc1258 DataGrid AllowAlternatingRows property added 2022-09-21 16:26:51 +03:00
Vladimir Enchev
3c51397be8 SplitButton will close popup on default action 2022-09-21 16:09:21 +03:00
Vladimir Enchev
84d51bf653 RenderMode renamed to PopupRenderMode 2022-09-21 15:35:33 +03:00
Vladimir Enchev
70c541b06f DataGrid self-reference hierarchy support added (#613)
* DataGrid self-reference hierarchy added

* Self ref demo inherited from DbContextPage

* Update grid self reference demo

* rz-cell-toggle added

* rzi-grid-sort removed from expand icon

* Style rz-cell-toggle in DataGrid

Co-authored-by: yordanov <vasil@yordanov.info>
2022-09-21 15:27:56 +03:00
yordanov
79a7095739 Rename Text page 2022-09-21 12:28:40 +03:00
yordanov
cf7fbf0b83 Update Tabs demo 2022-09-21 12:28:35 +03:00
yordanov
f1bf807b67 Update Card demo 2022-09-21 12:26:12 +03:00
Vladimir Enchev
f02581d20a DatePicker PopupRenderMode property added (#611)
* Experiment with on demand popup rendering.

* Delay the open until the popup content has rendered.

* DatePicker PopupRenderMode property added

* DatePicker RenderMode.Initial improved

* ColorPicker PopupRenderMode added

Co-authored-by: Atanas Korchev <akorchev@gmail.com>
2022-09-21 11:14:51 +03:00
Vladimir Enchev
03450fc4f7 Fixed DropDown SelectAll InvalidCastException when bind-Value is IList
Fix #610
2022-09-21 08:44:52 +03:00
Atanas Korchev
5e0eaa529f Update theme instructions. 2022-09-20 19:35:23 +03:00
Vladimir Enchev
56184370a7 DataFilter nested filters fixed 2022-09-20 18:23:15 +03:00
yordanov
6fdc672dc4 Fix height of slots and events in Scheduler 2022-09-20 16:41:00 +03:00
yordanov
ec82a24910 Style labels in bootstrap forms 2022-09-20 16:27:16 +03:00
Atanas Korchev
06157a9e5c Add rz-form class to RadzenTemplateForm. 2022-09-20 16:18:02 +03:00
Vladimir Enchev
a53022bac0 DataFilter component added (#608)
* RadzenDataFilter added

* Add SplitButton Variants, ButtonStyles and Shades

* Add Flat variant to Button and Button gap

* Add SelectBar Size

* Add initial DataFilter styles

* rz-datafilter-group-item class added

* reset filter on property change

* missing rz-datafilter-group-item added

* rz-datafilter-group-item fixed

* inner filter add fixed

* code reworked

* Make datagrid's filter buttons flat

* Update filter node paths

Co-authored-by: yordanov <vasil@yordanov.info>
2022-09-20 14:59:15 +03:00
Vladimir Enchev
896c775fef DataGridCellSelect improved 2022-09-20 13:45:57 +03:00
Vladimir Enchev
f907d689e5 DataGridCellSelect demo improved 2022-09-20 13:28:44 +03:00
Vladimir Enchev
90a9850034 Cell selection color changed to rz-secondary-lighter 2022-09-20 12:19:13 +03:00
Vladimir Enchev
4418d348c5 DataGrid CellClick/CellDoubleClick events and example for cell selection added. 2022-09-20 11:36:36 +03:00
Vladimir Enchev
7ce93da521 DbContext demos reworked with DbContextFactory 2022-09-19 17:21:28 +03:00
Vladimir Enchev
aeb08616b5 DataGrid groups change event disposed 2022-09-19 11:07:04 +03:00
Vladimir Enchev
a10df3a133 reference disposed 2022-09-19 11:00:02 +03:00
Vladimir Enchev
c4039f5663 Force GC on example dispose 2022-09-19 10:50:51 +03:00
Vladimir Enchev
30df4a257a DataGrid column picker not updated when setting column Visible property with code 2022-09-16 19:00:29 +03:00
yordanov
6f0df065ad Update badge size in sidebar 2022-09-16 18:24:01 +03:00
yordanov
8cfc5567d1 Fix Badge bootstrap overrides 2022-09-16 18:24:01 +03:00
Vladimir Enchev
32defc6833 GoogleMap component should not reset zoom and center on marker update. Options property added. 2022-09-16 17:45:43 +03:00
yordanov
4485cf33df Fix border-radius of outlined buttons 2022-09-16 17:39:55 +03:00
Vladimir Enchev
d7638ea764 DataGrid multi sort column index indicator now is Badge 2022-09-16 15:36:15 +03:00
yordanov
d334a472ce Update grid header cell layout based on text-align 2022-09-16 15:15:38 +03:00
Vladimir Enchev
19672dba39 DataGrid column text-align fixed
Fix #606
2022-09-16 10:00:32 +03:00
Vladimir Enchev
24358eeb51 Readme added 2022-09-16 09:27:05 +03:00
Vladimir Enchev
c1a823cd42 Description updated 2022-09-16 09:18:52 +03:00
Vladimir Enchev
849c4982a8 Version updated 2022-09-15 16:07:40 +03:00
yordanov
032d6a1ae1 Update new and updated demo badges 2022-09-14 15:19:03 +03:00
yordanov
b012c48e62 Hide link to docs 2022-09-14 15:19:03 +03:00
yordanov
76aa0f70aa Use css color variables in conditional template 2022-09-14 15:19:03 +03:00
yordanov
1c3c525d2b Make rz-cell-data overflow visible if content is button or checkbox 2022-09-14 15:19:03 +03:00
yordanov
9042b16df4 Add fill color to rz-donut-title 2022-09-14 15:19:03 +03:00
yordanov
1f9198964b Fix z-index of fetching data panel in dashboard demo 2022-09-14 15:19:03 +03:00
yordanov
698513ea84 Update Badge child content demo 2022-09-14 15:19:03 +03:00
yordanov
0cb68d9b5d Fix rz-grid-filter padding 2022-09-14 15:19:03 +03:00
yordanov
221a0942ab Fix standard theme secondary color 2022-09-14 15:19:03 +03:00
yordanov
c83fcc4602 Add Dark styles, Shade styles, Outline and Text variants to Button and Badge 2022-09-14 15:19:03 +03:00
yordanov
b51abc68a8 Update DataList demo styles 2022-09-14 15:19:03 +03:00
yordanov
9040c32f52 Add Pager responsive styles 2022-09-14 15:19:03 +03:00
yordanov
dc81c7244a Update demos layouts and headings 2022-09-14 15:19:03 +03:00
yordanov
62debd3df4 Add functional text css variables 2022-09-14 15:19:03 +03:00
yordanov
a048cf0f23 Update support page 2022-09-14 15:19:03 +03:00
yordanov
50ed79c0b3 Fix content scroll in Steps and add padding to Steps prev next buttons 2022-09-14 15:19:03 +03:00
yordanov
b6963c7cab Remove text uppercase in lg button 2022-09-14 15:19:03 +03:00
yordanov
9f5af15987 Fix demo layouts 2022-09-14 15:19:03 +03:00
yordanov
5119048f33 Update heading styles 2022-09-14 15:19:03 +03:00
yordanov
090f45092c Remove checkbox and radio margin 2022-09-14 15:19:03 +03:00
yordanov
925e36e33b Fix demo layouts and typography 2022-09-14 15:19:03 +03:00
yordanov
720b64ff90 Update layout in dropdown demo 2022-09-14 15:19:03 +03:00
yordanov
4cd9f11f0b Fix padding of dropdown with chips 2022-09-14 15:19:03 +03:00
yordanov
1b54504165 Update console message styles 2022-09-14 15:19:03 +03:00
yordanov
080e514527 Remove unused css classes 2022-09-14 15:19:03 +03:00
yordanov
392ed8b517 Style Chips in DropDown 2022-09-14 15:19:03 +03:00
yordanov
546701894d CLose RadzenText in Upload demo 2022-09-14 15:19:03 +03:00
yordanov
b90139aee4 Fix title text overflow in demos header 2022-09-14 15:19:03 +03:00
yordanov
5d39b554e0 Fix background in ripple demo 2022-09-14 15:19:03 +03:00
yordanov
51b9ab3661 Update headings in steps demo 2022-09-14 15:19:03 +03:00
yordanov
b58672b8ec Update images in get started article 2022-09-14 15:19:03 +03:00
yordanov
4148b57819 Fix steps disabled state 2022-09-14 15:19:03 +03:00
yordanov
8a9f0ddd24 Add Material theme 2022-09-14 15:19:03 +03:00
yordanov
4ccc377f1c Update demos layouts and headings 2022-09-14 15:19:03 +03:00
yordanov
dc56d18595 Remove button-sizes from standard theme 2022-09-14 15:19:03 +03:00
yordanov
ff78f68443 Add button min-width in standard theme 2022-09-14 15:19:03 +03:00
yordanov
5b52b070d9 Fix h6 font-size 2022-09-14 15:19:03 +03:00
yordanov
8f28becd6c Fix validator callout and paddings 2022-09-14 15:19:03 +03:00
yordanov
14212a744a Fix calendar input padding-right 2022-09-14 15:19:03 +03:00
yordanov
cb0af54ab4 Update card box-shadow 2022-09-14 15:19:03 +03:00
yordanov
b6b737a0cd Add UI Fundamentals demos 2022-09-14 15:19:03 +03:00
yordanov
092ec1a8f0 Fix usege of --border-radius-* 2022-09-14 15:19:03 +03:00
yordanov
9476d8bbcd Add scss mixins and fill-in missing utility maps 2022-09-14 15:19:03 +03:00
yordanov
72e4a6ccc7 Fix naming and generation of border css variables 2022-09-14 15:19:03 +03:00
yordanov
73d2c83d8e Refactor generation of css variables and utility classes 2022-09-14 15:19:03 +03:00
yordanov
540b315213 Fix background colors in dark theme 2022-09-14 15:19:03 +03:00
yordanov
9594014358 Add link text-decoration variables and update border css classes 2022-09-14 15:19:03 +03:00
yordanov
d3e781607d Update font-weights of default headings 2022-09-14 15:19:03 +03:00
yordanov
e9d6874ff5 Add text-decoration, hover and focus styles to rz-link 2022-09-14 15:19:03 +03:00
yordanov
729b43cd54 Fix grid filter and date filter dropdown layouts 2022-09-14 15:19:03 +03:00
yordanov
5278060aaa Add background-color to rz-calendar-inline 2022-09-14 15:19:03 +03:00
yordanov
d25a1e8463 Add fill to rz-series-data-label and update chart tooltip padding 2022-09-14 15:19:03 +03:00
yordanov
24e260dc0d Update texts in Dashbboard example 2022-09-14 15:19:03 +03:00
yordanov
ea6a010c5e Fix variable font-sizes in typography headings 2022-09-14 15:19:03 +03:00
yordanov
07715fd541 Add CSS vars to RadzenText 2022-09-14 15:19:03 +03:00
yordanov
6b9e0e60c5 Add CSS classes for colors 2022-09-14 15:19:03 +03:00
yordanov
1040b041a4 Update scss variables in themes 2022-09-14 15:19:03 +03:00
yordanov
914dcced2b Close strong tag in title 2022-09-14 15:19:03 +03:00
yordanov
520d2bf0a8 Replace demo headings and paragraphs with RadzenText component 2022-09-14 15:19:03 +03:00
yordanov
886a09553f Update SCSS variables - names and values 2022-09-14 15:19:03 +03:00
yordanov
9436fa50b8 Set background color to files upload clear button in dark theme 2022-09-14 15:19:03 +03:00
yordanov
feae293d17 Add fieldset legend margin scss variable 2022-09-14 15:19:03 +03:00
yordanov
8eba025e02 Add rating ban icon color variable 2022-09-14 15:19:03 +03:00
yordanov
060f5dfd6c Add overflow hidden to listbox wrapper 2022-09-14 15:19:03 +03:00
yordanov
e3e3bb2731 Fix dropdown item border radius 2022-09-14 15:19:03 +03:00
yordanov
1082dd5aa4 Fix grid filter row background and padding 2022-09-14 15:19:03 +03:00
yordanov
aaba37325b Update dropdown min-width 2022-09-14 15:19:03 +03:00
yordanov
fe225efde5 Remove btn- css classes 2022-09-14 15:19:03 +03:00
yordanov
1726a45738 Fix colors of remove upload files button 2022-09-14 15:19:03 +03:00
yordanov
09f3ebec80 Remove sort icon color from standard theme 2022-09-14 15:19:03 +03:00
yordanov
f8a4534496 Add initial shadow values 2022-09-14 15:19:03 +03:00
yordanov
299833b974 Add button min-width 2022-09-14 15:19:03 +03:00
yordanov
317a1cd8ca Fix navigation link cursor 2022-09-14 15:19:03 +03:00
yordanov
81d7ecde04 Fix numeric button border radius 2022-09-14 15:19:03 +03:00
yordanov
1377769eff Fix LogicalFilterOperator dropdown width 2022-09-14 15:19:03 +03:00
yordanov
1cbde75953 Fix resize, sort, reorder and composite-cell behavior of grid header cells 2022-09-14 15:19:03 +03:00
yordanov
72d16e22be Add background and color to remove file button 2022-09-14 15:19:03 +03:00
yordanov
8fa6721a26 Add color variables for notification icons 2022-09-14 15:19:03 +03:00
yordanov
aeb2355d75 Remove cursor when hue and alpha pickers are active 2022-09-14 15:19:03 +03:00
yordanov
81a3adb483 Add background color to color picker button 2022-09-14 15:19:03 +03:00
yordanov
8298a22023 Fix content alignment in breadcrumb links 2022-09-14 15:19:03 +03:00
yordanov
c3612ec9a6 Update dropdown scss variables - new trigger-icon and item-border-radius 2022-09-14 15:19:03 +03:00
yordanov
c05f158663 Add box-shadow to slider handle and reorder variables 2022-09-14 15:19:03 +03:00
yordanov
671851f345 Reorder switch scss variables 2022-09-14 15:19:03 +03:00
yordanov
1611429d83 Fix transitions and border width between states of radio button 2022-09-14 15:19:03 +03:00
yordanov
a8593078ad Use vertical-offest instead of margin for second level menus 2022-09-14 15:19:03 +03:00
yordanov
6165c25976 Add CSS variables to set margin and border-radius to second level items in panel menu 2022-09-14 15:19:03 +03:00
yordanov
47598a9d7a Add line-height CSS variable to steps number 2022-09-14 15:19:03 +03:00
yordanov
09c727e91a Add color variables for icon in menu item 2022-09-14 15:19:03 +03:00
yordanov
0619557f05 Add border-radius to menu top item 2022-09-14 15:19:03 +03:00
yordanov
aa5a9c6c2d Fix navigation item active indicator margin 2022-09-14 15:19:03 +03:00
yordanov
e3ad81926e Add menu-item-border-radius var 2022-09-14 15:19:03 +03:00
yordanov
37abd6d5b8 Rename sidebar-toggle CSS class to rz-sidebar-toggle 2022-09-14 15:19:03 +03:00
yordanov
5a7499c80e Reorder sidebar-toggle scss variables 2022-09-14 15:19:03 +03:00
yordanov
ce3bb23b8c Add accordion header margin and border-top 2022-09-14 15:19:03 +03:00
yordanov
845d5b2351 Update demos layout 2022-09-14 15:19:03 +03:00
yordanov
08ee361c9c Add special color classes to utilities 2022-09-14 15:19:03 +03:00
yordanov
c6e6a4bd7d Fix FileInput delete button onclick 2022-09-14 15:19:03 +03:00
yordanov
85b571594c Refactor Button, Card and PanelMenu styles 2022-09-14 15:19:03 +03:00
Atanas Korchev
5088c94db5 Some documentation and default property values. 2022-09-14 15:19:03 +03:00
Atanas Korchev
2dc9e9e04c Allow tag name overriding. 2022-09-14 15:19:03 +03:00
Atanas Korchev
2752c641ed Add RadzenText. 2022-09-14 15:19:03 +03:00
yordanov
4c0b6bff9d Update grid columns' width 2022-09-14 15:19:03 +03:00
yordanov
5acebc3e44 Update title in dashboard example 2022-09-14 15:19:03 +03:00
yordanov
1e8c065fdb Update Typography page 2022-09-14 15:19:03 +03:00
yordanov
b35775b3e0 Update demos layout 2022-09-14 15:19:03 +03:00
yordanov
0693853c0a Fix button height 2022-09-14 15:19:03 +03:00
yordanov
6994d12eb6 Update demos layout to fixed width 2022-09-14 15:19:03 +03:00
yordanov
dc0dda35fc Fix event list button top position unit 2022-09-14 15:19:03 +03:00
yordanov
085fc2a764 Style scheduler event list button 2022-09-14 15:19:03 +03:00
yordanov
7ecae9e3a2 Style grid group header item 2022-09-14 15:19:03 +03:00
yordanov
61d687882f Add Large button size 2022-09-14 15:19:03 +03:00
yordanov
354eed23b9 Update humanistic theme vars 2022-09-14 15:19:03 +03:00
yordanov
99996613bc Update main color variables in dark theme 2022-09-14 15:19:03 +03:00
yordanov
c6e7b1d68a Fix shadow variable 2022-09-14 15:19:03 +03:00
yordanov
69e9823640 Add Typography demo 2022-09-14 15:19:03 +03:00
yordanov
6e74d02e95 Fix colorpicker hover state in editor 2022-09-14 15:19:03 +03:00
yordanov
397d3073c6 Add default typography styles 2022-09-14 15:19:03 +03:00
yordanov
ecba921352 Update github icon color 2022-09-14 15:19:03 +03:00
yordanov
bea36fdcb5 Update main theme color scss variables 2022-09-14 15:19:03 +03:00
yordanov
0379e0ee6d Fix slot header and slot title font-sizes 2022-09-14 15:19:03 +03:00
yordanov
787a48a795 Update chart color schemes with css vars 2022-09-14 15:19:03 +03:00
yordanov
ce257fcc95 Add scss variables for colors in notification 2022-09-14 15:19:03 +03:00
yordanov
becc50d2b8 Remove inline styles in time picker OK button 2022-09-14 15:19:03 +03:00
yordanov
673be6056c Fix toggle icon order in accordion 2022-09-14 15:19:03 +03:00
yordanov
5c7b19527d Update progressbar style scss vars 2022-09-14 15:19:03 +03:00
yordanov
4304099d3a Add more shadow variables 2022-09-14 15:19:03 +03:00
yordanov
5911968469 Fix numeric button alignment and spacing in pager 2022-09-14 15:19:03 +03:00
yordanov
6afde15a1d Reorder css rules 2022-09-14 15:19:03 +03:00
yordanov
ab578f499c Refactor pager scss variables 2022-09-14 15:19:03 +03:00
yordanov
e78c3bc6aa Refactor grid scss variables 2022-09-14 15:19:03 +03:00
yordanov
6394a8ee76 Refactor datalist scss variables 2022-09-14 15:19:03 +03:00
yordanov
5f4e62824f Add button size examples 2022-09-14 15:19:03 +03:00
yordanov
f1966f42de Refactor tree scss variables 2022-09-14 15:19:03 +03:00
yordanov
704039afc2 Remove inline styles of checkbox in tree 2022-09-14 15:19:03 +03:00
yordanov
b1c9b27f17 Refactor scheduler variables 2022-09-14 15:19:03 +03:00
yordanov
3a1c0a707a Use RadzenButton in nav-views 2022-09-14 15:19:03 +03:00
yordanov
781c28044a Remove icon css classes 2022-09-14 15:19:03 +03:00
yordanov
76346a435a Add rz-button-box container 2022-09-14 15:19:03 +03:00
yordanov
a4ebe3532b Update tabs variables 2022-09-14 15:19:03 +03:00
yordanov
189c8c5a2a Update switch background colors and sizing 2022-09-14 15:19:03 +03:00
yordanov
c1c50fcdb0 Add slider handle transitions 2022-09-14 15:19:03 +03:00
yordanov
aad91c32d1 Add radio border-width 2022-09-14 15:19:03 +03:00
yordanov
b80a84822e Update panel icon size 2022-09-14 15:19:03 +03:00
yordanov
3e4f86d5fe Update panel-menu styles 2022-09-14 15:19:03 +03:00
yordanov
3cb9fa6926 Add pager border-radius and button hover styles 2022-09-14 15:19:03 +03:00
yordanov
900fe003d4 FIx numeric input padding 2022-09-14 15:19:03 +03:00
yordanov
3c923f7a20 Fix input focus styles 2022-09-14 15:19:03 +03:00
yordanov
6d95c85719 Use proper icon size variable 2022-09-14 15:19:03 +03:00
yordanov
5a0bdb6358 Add checkbox border-width and fix background 2022-09-14 15:19:03 +03:00
yordanov
49f8d7ac56 Fix autocomplete background, transition and transform styles 2022-09-14 15:19:03 +03:00
yordanov
fd99d88510 Add Accordion toggle icon variables 2022-09-14 15:19:03 +03:00
yordanov
29f37bbe43 Add line-height to button 2022-09-14 15:19:03 +03:00
yordanov
1567dd6163 Remove inline style 2022-09-14 15:19:03 +03:00
yordanov
297d0b7466 Update DropDown styles 2022-09-14 15:19:03 +03:00
yordanov
7db378a8c8 Update filtering dropdown width 2022-09-14 15:19:03 +03:00
yordanov
3f5c73ca26 Remove inline margin 2022-09-14 15:19:03 +03:00
yordanov
53f7ddcb82 Add initial typography styles 2022-09-14 15:19:03 +03:00
yordanov
1f54a40147 Update font size 2022-09-14 15:19:03 +03:00
yordanov
4c3cdaf593 Update Roboto font 2022-09-14 15:19:03 +03:00
yordanov
af00eeaf2a Fix border-radius variable 2022-09-14 15:19:03 +03:00
yordanov
ed5629f7cf Add context menu padding 2022-09-14 15:19:03 +03:00
yordanov
88d1854b0d Update theme constants 2022-09-14 15:19:03 +03:00
yordanov
328cb3a4dc Add toggle icon font-size 2022-09-14 15:19:03 +03:00
yordanov
a1c83ebb10 Add font-size and icon-size variables 2022-09-14 15:19:03 +03:00
yordanov
d440a78c7b Update themes 2022-09-14 15:19:03 +03:00
yordanov
6e643d7cda Fix scss vars 2022-09-14 15:19:03 +03:00
yordanov
0f705bd755 Update dark theme 2022-09-14 15:19:03 +03:00
yordanov
f436e44233 Update base palette 2022-09-14 15:19:03 +03:00
yordanov
29f6c5907c Update color variables 2022-09-14 15:19:03 +03:00
yordanov
a4d5015875 Add font smoothing 2022-09-14 15:19:03 +03:00
yordanov
e8aa282a3a Update theme colors 2022-09-14 15:19:03 +03:00
yordanov
44dc55822d Update transitions 2022-09-14 15:19:03 +03:00
yordanov
473bc16384 Add transitions 2022-09-14 15:19:03 +03:00
yordanov
8984a1baf6 Add utilities and typography under components 2022-09-14 15:19:03 +03:00
yordanov
8fda96eabf Organize default global variables 2022-09-14 15:19:03 +03:00
yordanov
5110c5d248 Add css vars and update colors 2022-09-14 15:19:03 +03:00
yordanov
d23bdee6ed Add css vars and update colors 2022-09-14 15:19:03 +03:00
yordanov
2f2ecbbeb0 Add css vars and update colors 2022-09-14 15:19:03 +03:00
yordanov
867fe28c5f Add CSS vars and update colors 2022-09-14 15:19:03 +03:00
yordanov
958cdc627a Add css vars to input and badge 2022-09-14 15:19:03 +03:00
yordanov
473aa9c429 Add css vars to standard and default theme 2022-09-14 15:19:03 +03:00
yordanov
846dd24dde Add global css vars 2022-09-14 15:19:03 +03:00
yordanov
c01823024d Add selection and default body font-size 2022-09-14 15:19:03 +03:00
yordanov
1cba327f24 Remove sizing from standard theme 2022-09-14 15:19:03 +03:00
yordanov
c973edee05 Update typography 2022-09-14 15:19:03 +03:00
yordanov
6744926708 Update sizing 2022-09-14 15:19:03 +03:00
yordanov
a5f040d69d Update sizing 2022-09-14 15:19:03 +03:00
Vladimir Enchev
0507f25e86 DataGrid column ShowTimeForDateTimeFilter() virtual method added
Fix #601
2022-09-13 09:43:25 +03:00
Vladimir Enchev
f782f18f04 RadzenDataGridColumn GetFilterOperators() made virtual
Fix #601
2022-09-12 16:44:30 +03:00
Vladimir Enchev
ddb58f148d Fixed DateTime operators order in DataGrid simple filter mode
Fix #602
2022-09-12 16:14:57 +03:00
Vladimir Enchev
75904cf88c Version updated 2022-09-12 09:58:21 +03:00
Vladimir Enchev
522deec88b DropDownDataGrid AllowRowSelectOnRowClick behavior fixed 2022-09-12 09:57:17 +03:00
Vladimir Enchev
4c07d608c5 Pager GetPage() code fixed 2022-09-10 08:59:37 +03:00
Vladimir Enchev
c3490ac819 SSRSViewer Load event added 2022-09-08 16:35:00 +03:00
Vladimir Enchev
0ada1f2e46 DataGrid pager not recalculated properly when using Page event
Fix #598
2022-09-08 14:40:18 +03:00
Vladimir Enchev
6d7493c6e5 Version updated 2022-09-08 09:34:55 +03:00
Vladimir Enchev
3306d8a276 DropDown/AutoComplete scroll to selected item improved 2022-09-07 10:23:39 +03:00
Vladimir Enchev
d5b607eb72 DropDown item selection check improved 2022-09-07 10:11:41 +03:00
Vladimir Enchev
af22c74602 DropDown and DropDownDataGrid popup cannot be opened when nested in label
Fix #597
2022-09-07 09:30:10 +03:00
Vladimir Enchev
1822850835 DataGridColumn FilterPropertyType made public 2022-09-06 12:37:16 +03:00
Vladimir Enchev
f185b9c30d Numeric AutoComplete set to false by default 2022-09-06 11:06:17 +03:00
Vladimir Enchev
d6c39e05f9 RadzenSelectBarItem Template property added
Fix #595
2022-09-05 15:29:09 +03:00
GioeEng
d7abef33a6 RadzenAutoComplete with IEnumerable of strings (#596)
* feat: Dropdown with badges view

* Rename BadgesView to ChipsView and update styling

* Rename ChipsView to Chips. Do not set Multiple to true - require the developer to set it instead. Some cosmetic changes.

* Tag dropdown demo as updated.

* Reposition popup when chip is removed.

* fix: RadzenAutoComplete support IEnumerable of strings

Co-authored-by: yordanov <vasil@yordanov.info>
Co-authored-by: Atanas Korchev <akorchev@gmail.com>
2022-09-05 14:16:22 +03:00
Vladimir Enchev
a0f6712c57 Version updated 2022-09-05 09:25:18 +03:00
Vladimir Enchev
e81acee86b AutoComplete Multiline property added 2022-09-02 16:05:47 +03:00
Vladimir Enchev
bbc9080cfa Upload ParameterName property added 2022-09-02 15:22:25 +03:00
Vladimir Enchev
2095280783 AutoComplete Template property added 2022-09-02 09:27:35 +03:00
Vladimir Enchev
d2b2e9a0d9 Version updated 2022-09-01 19:29:45 +03:00
Vladimir Enchev
e62adf9131 SelectBar item Icon and Image properties added 2022-09-01 19:29:24 +03:00
Vladimir Enchev
4f22a869b8 DropDown with groups example added 2022-09-01 15:22:12 +03:00
Vladimir Enchev
8cf5868a30 code fixed 2022-09-01 14:17:55 +03:00
Vladimir Enchev
f8d2b47006 Fixed virtualized DropDownBase not refreshed on data change
Fix #592
2022-09-01 14:15:48 +03:00
Vladimir Enchev
71f0f53cae DataGrid should be reset to first page on data change
Fix #591
2022-08-31 16:07:14 +03:00
Vladimir Enchev
5b1fe105ba Version updated 2022-08-30 07:44:14 +03:00
Vladimir Enchev
7f447ac21f Fixed ProgressBar Template 2022-08-30 06:52:23 +03:00
Atanas Korchev
425c7cd390 Fix the search textbox in the navigation. 2022-08-29 09:50:55 +03:00
Vladimir Enchev
7f72143ee7 Version updated 2022-08-29 07:58:49 +03:00
Vladimir Enchev
e743500d6c ProgressBar Template property added 2022-08-28 15:32:52 +03:00
Vladimir Enchev
77e3952849 DialogService Close() method made virtual
Fix #588
2022-08-26 15:02:58 +03:00
Vladimir Enchev
21dab1bf50 DropDownDataGrid clear button should not open popup 2022-08-26 12:08:45 +03:00
Vladimir Enchev
4e9aa726c6 Fixed big number exception in Numeric with nullables
Fix #586
2022-08-26 09:38:18 +03:00
Vladimir Enchev
004babb572 Version updated 2022-08-25 08:43:34 +03:00
Vladimir Enchev
256c048598 Added CloseTooltipOnDocumentClick to TooltipOptions
Fix #582
2022-08-25 08:43:00 +03:00
Vladimir Enchev
59b884f4e4 AutoComplete popup will not open on Android 2022-08-24 12:09:36 +03:00
Jimmy Ho
45ff535d31 Fix Grid width is wrong in responsive mode (#584)
* style: fix grid width is wrong in responsive mode

* style: adjust tbody layer under table
2022-08-24 07:59:44 +03:00
Atanas Korchev
4cd8c53645 Loading indicator appears below the headers of an empty RadzenDataGrid. 2022-08-22 17:33:11 +03:00
Vladimir Enchev
b856ef4ea6 Version updated 2022-08-22 16:15:33 +03:00
Vladimir Enchev
ea3d83962f Fixed exception when filtering virtualized DropDownDataGrid bound with LoadData 2022-08-22 16:13:34 +03:00
Atanas Korchev
1d79076e65 Allow custom bar and column series sizes. 2022-08-22 10:58:06 +03:00
Vladimir Enchev
1e6bae6801 Fixed DataGrid SimpleWithMenu mode IsNotEmpty
Fix #583
2022-08-22 10:38:55 +03:00
Vladimir Enchev
6cda51ebbe Demos navigation expanded state fixed 2022-08-22 09:23:01 +03:00
Vladimir Enchev
e4c4c1b964 Fixed too big number in Numeric will raise exception
Fix #580
2022-08-22 07:53:29 +03:00
Vladimir Enchev
939c8c6d0e PanelMenuItem ExpandedChange argument fixed
#581
2022-08-20 07:49:03 +03:00
GioeEng
33c3963f66 feat: Dropdown with badges view (#568)
* feat: Dropdown with badges view

* Rename BadgesView to ChipsView and update styling

* Rename ChipsView to Chips. Do not set Multiple to true - require the developer to set it instead. Some cosmetic changes.

* Tag dropdown demo as updated.

* Reposition popup when chip is removed.

Co-authored-by: yordanov <vasil@yordanov.info>
Co-authored-by: Atanas Korchev <akorchev@gmail.com>
2022-08-18 19:42:46 +03:00
Vladimir Enchev
88bfaa532d Version updated 2022-08-17 17:14:51 +03:00
Vladimir Enchev
66e321ebea Added optional forceReload argument to PagedDataBoundComponent GoToPage() method 2022-08-17 10:41:02 +03:00
Vladimir Enchev
8d2838e928 Fixed Tooltip cannot be opened on first button click 2022-08-17 09:32:02 +03:00
Vladimir Enchev
98d896eb81 Fixed DataGrid pager not recalculated properly after Count change
#579
2022-08-17 08:57:01 +03:00
Vladimir Enchev
62bd56e70d DataGrid IsEmpty/IsNotEmpty filter expression should use double quotes 2022-08-17 08:25:15 +03:00
Vladimir Enchev
bbc7e0f648 Added support for IList value binding in DropDownBase 2022-08-16 17:08:50 +03:00
Vladimir Enchev
534c8e0bc3 Clear filter button added to DataGrid string columns in simple filter mode 2022-08-16 10:04:05 +03:00
Vladimir Enchev
1f9897e551 Fixed DataGrid frozen columns not properly stacked
Fix #577
2022-08-15 16:43:25 +03:00
Vladimir Enchev
eba54c8da3 Fixed missing attributes in RadzenSplitterPane 2022-08-15 07:51:24 +03:00
359 changed files with 20190 additions and 7935 deletions

View File

@@ -16,7 +16,7 @@ COPY RadzenBlazorDemos /app/RadzenBlazorDemos
WORKDIR /app
RUN docfx DocFX/docfx.json
FROM mcr.microsoft.com/dotnet/sdk:6.0-focal
FROM mcr.microsoft.com/dotnet/sdk:7.0
COPY --from=0 /app/RadzenBlazorDemos /app
WORKDIR /app

View File

@@ -5,7 +5,7 @@
</h1>
<p align="center">
A set of <strong>60+ free and open source</strong> native Blazor UI controls.
A set of <strong>70+ free and open source</strong> native Blazor UI controls.
</p>
<div align="center">
@@ -55,7 +55,7 @@ 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
## 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!
@@ -64,7 +64,7 @@ Everybody is welcome to visit the [Radzen Community forum](https://forum.radzen.
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/pricing/).
Dedicated support for the Radzen Blazor Components is available as part of the [Radzen Professional subscription](https://www.radzen.com/pricing/).
Our flagship product [Radzen Studio](https://www.radzen.com/features/) provides tons of productivity features for Blazor developers:
- The first in the industry WYSIWYG Blazor design time canvas
@@ -80,7 +80,7 @@ Our flagship product [Radzen Studio](https://www.radzen.com/features/) provides
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
- Add the project from the Visual Nuget Package Manager
- Manually edit the .csproj file and add a project reference
### 2. Import the namespace
@@ -89,15 +89,19 @@ Open the `_Imports.razor` file of your Blazor application and add this line `@us
### 3. Include a theme
Open `Pages\_Layout.cshtml` (Blazor Server .NET 6+), `Pages\_Host.cshtml` (Blazor Server before .NET 6) 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/default.css">
```
If you either add Bootstrap manually or don't use it at all, include this instead:
```html
<link rel="stylesheet" href="_content/Radzen.Blazor/css/default-base.css">
```
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 before .NET 6) or `wwwroot/index.html` (Blazor WebAssembly) and include the CSS file of 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
@@ -108,7 +112,7 @@ Open `Pages\_Layout.cshtml` (Blazor Server .NET 6+), `Pages\_Host.cshtml` (Blazo
```
### 5. Use a component
Use any Radzen Blazor component by typing its tag name in a Blazor page e.g.
Use any Radzen Blazor component by typing its tag name in a Blazor page e.g.
```html
<RadzenButton Text="Hi"></RadzenButton>
```

View File

@@ -134,11 +134,11 @@ namespace Radzen.Blazor.Tests
component.SetParametersAndRender(parameters => parameters.Add(p => p.ButtonStyle, ButtonStyle.Primary));
Assert.Contains(@$"btn-primary", component.Markup);
Assert.Contains(@$"rz-primary", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add(p => p.ButtonStyle, ButtonStyle.Secondary));
Assert.Contains(@$"btn-secondary", component.Markup);
Assert.Contains(@$"rz-secondary", component.Markup);
}
[Fact]

View File

@@ -17,7 +17,6 @@ namespace Radzen.Blazor.Tests
component.Render();
Assert.Contains(@$"rz-fieldset", component.Markup);
Assert.Contains(@$"rz-fieldset-legend", component.Markup);
Assert.Contains(@$"rz-fieldset-content-wrapper", component.Markup);
Assert.Contains(@$"rz-fieldset-content", component.Markup);
}

View File

@@ -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(@$"<i class=""rzi d-inline-flex justify-content-center align-items-center""", component.Markup);
Assert.Contains(@$"<i class=""rzi""", component.Markup);
}
[Fact]

View File

@@ -26,7 +26,7 @@ namespace Radzen.Blazor.Tests
var component = ctx.RenderComponent<RadzenLogin>();
Assert.Contains(@$"<label class=""col-sm-3 col-form-label"" for=""username"">Username</label>", component.Markup);
Assert.Contains(@$"<label class=""rz-label"" for=""username"">Username</label>", component.Markup);
}
[Fact]
@@ -114,7 +114,7 @@ namespace Radzen.Blazor.Tests
parameters.Add(p => p.AllowResetPassword, true);
});
Assert.Contains(@$"Forgot password</a>", component.Markup);
Assert.Contains(@$"Forgot password?</a>", component.Markup);
}
[Fact]
@@ -190,7 +190,7 @@ namespace Radzen.Blazor.Tests
parameters.Add(p => p.Register, args => { clicked = true; });
});
component.Find(".register > button").Click();
component.Find(".rz-secondary").Click();
Assert.True(clicked);
}

View File

@@ -18,7 +18,9 @@ namespace Radzen.Blazor.Tests
component.SetParametersAndRender(parameters => parameters.Add<double>(p => p.Value, value));
Assert.Contains(@$"<div class=""rz-progressbar-label"">{value}", component.Markup);
Assert.Contains(@$"<div class=""rz-progressbar-label"">", component.Markup);
Assert.Contains(@$"{value}%", component.Markup);
Assert.Contains(@$"aria-valuenow=""{value}""", component.Markup);
Assert.Contains(@$"aria-valuemin=""0""", component.Markup);
}
@@ -50,13 +52,13 @@ namespace Radzen.Blazor.Tests
component.Render();
Assert.Contains(@$"%</div>", component.Markup);
Assert.Contains(@$"0%", component.Markup);
var value = "mm";
var unit = "mm";
component.SetParametersAndRender(parameters => parameters.Add(p => p.Unit, value));
component.SetParametersAndRender(parameters => parameters.Add(p => p.Unit, unit));
Assert.Contains(@$"{value}</div>", component.Markup);
Assert.Contains(@$"0{unit}", component.Markup);
}
[Fact]

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6</TargetFramework>
<TargetFramework>net7</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>

View File

@@ -127,6 +127,8 @@ namespace Radzen.Blazor.Tests
public void SplitButton_Raises_ClickEvent()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenSplitButton>();

View File

@@ -14,6 +14,73 @@ using System.Threading.Tasks;
namespace Radzen
{
/// <summary>
/// DataGrid settings class used to Save/Load settings.
/// </summary>
public class DataGridSettings
{
/// <summary>
/// Columns.
/// </summary>
public IEnumerable<DataGridColumnSettings> Columns { get; set; }
/// <summary>
/// Groups.
/// </summary>
public IEnumerable<GroupDescriptor> Groups { get; set; }
/// <summary>
/// CurrentPage.
/// </summary>
public int? CurrentPage { get; set; }
/// <summary>
/// PageSize.
/// </summary>
public int? PageSize { get; set; }
}
/// <summary>
/// DataGrid column settings class used to Save/Load settings.
/// </summary>
public class DataGridColumnSettings
{
/// <summary>
/// Property.
/// </summary>
public string Property { get; set; }
/// <summary>
/// Visible.
/// </summary>
public bool Visible { get; set; }
/// <summary>
/// Width.
/// </summary>
public string Width { get; set; }
/// <summary>
/// OrderIndex.
/// </summary>
public int? OrderIndex { get; set; }
/// <summary>
/// SortOrder.
/// </summary>
public SortOrder? SortOrder { get; set; }
/// <summary>
/// FilterValue.
/// </summary>
public object FilterValue { get; set; }
/// <summary>
/// FilterOperator.
/// </summary>
public FilterOperator FilterOperator { get; set; }
/// <summary>
/// SecondFilterValue.
/// </summary>
public object SecondFilterValue { get; set; }
/// <summary>
/// SecondFilterOperator.
/// </summary>
public FilterOperator SecondFilterOperator { get; set; }
}
#if NET7_0_OR_GREATER
#else
/// <summary>
/// Enables "onmouseenter" and "onmouseleave" event support in Blazor. Not for public use.
/// </summary>
@@ -22,9 +89,9 @@ namespace Radzen
public static class EventHandlers
{
}
#endif
/// <summary>
/// Represents the common <see cref="RadzenSelectBar{TValue}" /> API used by
/// Represents the common <see cref="RadzenSelectBar{TValue}" /> API used by
/// its items. Injected as a cascading property in <see cref="RadzenSelectBarItem" />.
/// </summary>
public interface IRadzenSelectBar
@@ -73,7 +140,7 @@ namespace Radzen
/// <summary>
/// A class that represents a <see cref="RadzenGoogleMap" /> position.
/// </summary>
public class GoogleMapPosition
public class GoogleMapPosition : IEquatable<GoogleMapPosition>
{
/// <summary>
/// Gets or sets the latitude.
@@ -85,6 +152,29 @@ namespace Radzen
/// </summary>
/// <value>The longitude.</value>
public double Lng { get; set; }
/// <inheritdoc />
public bool Equals(GoogleMapPosition other)
{
if (other != null)
{
return this.Lat == other.Lat && this.Lng == other.Lng;
}
return true;
}
/// <inheritdoc />
public override bool Equals(object obj)
{
return this.Equals(obj as GoogleMapPosition);
}
/// <inheritdoc />
public override int GetHashCode()
{
return base.GetHashCode();
}
}
/// <summary>
@@ -436,6 +526,36 @@ namespace Radzen
}
}
/// <summary>
/// Specifies component density.
/// </summary>
public enum Density
{
/// <summary>
/// The default density.
/// </summary>
Default,
/// <summary>
/// А high density compact mode.
/// </summary>
Compact
}
/// <summary>
/// Specifies the ways a component renders its popup.
/// </summary>
public enum PopupRenderMode
{
/// <summary>
/// The component renders its popup on-demand.
/// </summary>
OnDemand,
/// <summary>
/// The component renders its popup initially.
/// </summary>
Initial
}
/// <summary>
/// Specifies the ways a <see cref="RadzenTabs" /> component renders its items.
/// </summary>
@@ -560,7 +680,7 @@ namespace Radzen
/// </summary>
Info,
/// <summary>
/// Represents a success.
/// Represents a success.
/// </summary>
Success,
/// <summary>
@@ -569,6 +689,72 @@ namespace Radzen
Warning
}
/// <summary>
/// Specifies the display style or severity of a <see cref="RadzenAlert" />. Affects the visual styling of RadzenAlert (background and text color).
/// </summary>
public enum AlertStyle
{
/// <summary>
/// Primary styling. Similar to primary buttons.
/// </summary>
Primary,
/// <summary>
/// Secondary styling. Similar to secondary buttons.
/// </summary>
Secondary,
/// <summary>
/// Light styling. Similar to light buttons.
/// </summary>
Light,
/// <summary>
/// Dark styling. Similar to dark buttons.
/// </summary>
Base,
/// <summary>
/// The default styling.
/// </summary>
Dark,
/// <summary>
/// Success styling.
/// </summary>
Success,
/// <summary>
/// Danger styling.
/// </summary>
Danger,
/// <summary>
/// Warning styling.
/// </summary>
Warning,
/// <summary>
/// Informative styling.
/// </summary>
Info
}
/// <summary>
/// Specifies the size of a <see cref="RadzenAlert" />.
/// </summary>
public enum AlertSize
{
/// <summary>
/// The smallest alert.
/// </summary>
ExtraSmall,
/// <summary>
/// A alert smaller than the default.
/// </summary>
Small,
/// <summary>
/// The default size of an alert.
/// </summary>
Medium,
/// <summary>
/// An alert larger than the default.
/// </summary>
Large
}
/// <summary>
/// Specifies the behavior of <see cref="RadzenProgressBar" />.
/// </summary>
@@ -579,7 +765,7 @@ namespace Radzen
/// </summary>
Determinate,
/// <summary>
/// RadzenProgressBar displays continuous animation.
/// RadzenProgressBar displays continuous animation.
/// </summary>
Indeterminate
}
@@ -602,6 +788,10 @@ namespace Radzen
/// </summary>
Light,
/// <summary>
/// Dark styling. Similar to dark buttons.
/// </summary>
Dark,
/// <summary>
/// Success styling.
/// </summary>
Success,
@@ -678,9 +868,17 @@ namespace Radzen
/// </summary>
Medium,
/// <summary>
/// A button larger than the default.
/// </summary>
Large,
/// <summary>
/// A button smaller than the default.
/// </summary>
Small
Small,
/// <summary>
/// The smallest button.
/// </summary>
ExtraSmall
}
/// <summary>
@@ -701,6 +899,10 @@ namespace Radzen
/// </summary>
Light,
/// <summary>
/// A button with dark styling.
/// </summary>
Dark,
/// <summary>
/// A button with success styling.
/// </summary>
Success,
@@ -718,6 +920,56 @@ namespace Radzen
Info
}
/// <summary>
/// Specifies the design variant of <see cref="RadzenButton" /> and <see cref="RadzenBadge" />. Affects the visual styling of RadzenButton and RadzenBadge.
/// </summary>
public enum Variant
{
/// <summary>
/// A filled appearance.
/// </summary>
Filled,
/// <summary>
/// A flat appearance without any drop shadows.
/// </summary>
Flat,
/// <summary>
/// A text appearance.
/// </summary>
Text,
/// <summary>
/// An outlined appearance.
/// </summary>
Outlined
}
/// <summary>
/// Specifies the color shade of a <see cref="RadzenButton" />. Affects the visual styling of RadzenButton.
/// </summary>
public enum Shade
{
/// <summary>
/// A button with lighter styling.
/// </summary>
Lighter,
/// <summary>
/// A button with light styling.
/// </summary>
Light,
/// <summary>
/// A button with default styling.
/// </summary>
Default,
/// <summary>
/// A button with dark styling.
/// </summary>
Dark,
/// <summary>
/// A button with darker styling.
/// </summary>
Darker
}
/// <summary>
/// Specifies the filtering mode of <see cref="RadzenDataGrid{TItem}" />.
/// </summary>
@@ -865,7 +1117,15 @@ namespace Radzen
/// <summary>
/// The text is centered in its container.
/// </summary>
Center
Center,
/// <summary>The text is justified.</summary>
Justify,
/// <summary>Same as justify, but also forces the last line to be justified.</summary>
JustifyAll,
/// <summary>The same as left if direction is left-to-right and right if direction is right-to-left..</summary>
Start,
/// <summary>The same as right if direction is left-to-right and left if direction is right-to-left..</summary>
End
}
/// <summary>
@@ -909,6 +1169,10 @@ namespace Radzen
/// </summary>
Light,
/// <summary>
/// Dark styling. Similar to dark buttons.
/// </summary>
Dark,
/// <summary>
/// Success styling.
/// </summary>
Success,
@@ -944,6 +1208,10 @@ namespace Radzen
/// </summary>
Light,
/// <summary>
/// Dark styling. Similar to dark buttons.
/// </summary>
Dark,
/// <summary>
/// Success styling.
/// </summary>
Success,
@@ -1134,6 +1402,42 @@ namespace Radzen
public LogicalFilterOperator LogicalFilterOperator { get; set; }
}
/// <summary>
/// Represents a filter in a component that supports filtering.
/// </summary>
public class CompositeFilterDescriptor
{
/// <summary>
/// Gets or sets the name of the filtered property.
/// </summary>
/// <value>The property.</value>
public string Property { get; set; }
/// <summary>
/// Gets or sets the value to filter by.
/// </summary>
/// <value>The filter value.</value>
public object FilterValue { get; set; }
/// <summary>
/// Gets or sets the operator which will compare the property value with <see cref="FilterValue" />.
/// </summary>
/// <value>The filter operator.</value>
public FilterOperator FilterOperator { get; set; }
/// <summary>
/// Gets or sets the logic used to combine the outcome of filtering by <see cref="FilterValue" />.
/// </summary>
/// <value>The logical filter operator.</value>
public LogicalFilterOperator LogicalFilterOperator { get; set; }
/// <summary>
/// Gets or sets the filters.
/// </summary>
/// <value>The filters.</value>
public IEnumerable<CompositeFilterDescriptor> Filters { get; set; }
}
/// <summary>
/// Represents a sorting description. Used in components that support sorting.
/// </summary>
@@ -1240,6 +1544,31 @@ namespace Radzen
public IEnumerable<SortDescriptor> Sorts { get; set; }
}
/// <summary>
/// Supplies information about a <see cref="RadzenDataGrid{TItem}.LoadChildData" /> event that is being raised.
/// </summary>
public class DataGridLoadChildDataEventArgs<T>
{
/// <summary>
/// Gets or sets the data.
/// </summary>
/// <value>The data.</value>
public IEnumerable<T> Data { get; set; }
/// <summary>
/// Gets the item.
/// </summary>
/// <value>The item.</value>
public T Item { get; internal set; }
}
internal class DataGridChildData<T>
{
internal DataGridChildData<T> ParentChildData { get; set; }
internal int Level { get; set; }
internal IEnumerable<T> Data { get; set; }
}
/// <summary>
/// Supplies information about a <see cref="RadzenPager.PageChanged" /> event that is being raised.
/// </summary>
@@ -1547,6 +1876,9 @@ namespace Radzen
/// Gets or sets the password.
/// </summary>
public string Password { get; set; }
/// <summary> Gets or sets a value indicating whether the user wants to remember their credentials. </summary>
public bool RememberMe { get; set; }
}
/// <summary>
@@ -1576,7 +1908,7 @@ namespace Radzen
{
return Enum.Parse(Nullable.GetUnderlyingType(type), value.ToString());
}
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IEnumerable<>))
{
Type itemType = type.GetGenericArguments()[0];
@@ -1604,16 +1936,27 @@ namespace Radzen
/// <typeparam name="TItem">The owner type.</typeparam>
/// <typeparam name="TValue">The value type.</typeparam>
/// <param name="propertyName">Name of the property to return.</param>
/// <param name="type">Type of the object.</param>
/// <returns>A function which return the specified property by its name.</returns>
public static Func<TItem, TValue> Getter<TItem, TValue>(string propertyName)
public static Func<TItem, TValue> Getter<TItem, TValue>(string propertyName, Type type = null)
{
var arg = Expression.Parameter(typeof(TItem));
Expression body = arg;
if (type != null)
{
body = Expression.Convert(body, type);
}
foreach (var member in propertyName.Split("."))
{
body = Expression.PropertyOrField(body, member);
body = !body.Type.IsInterface ?
Expression.PropertyOrField(body, member) :
Expression.Property(
body,
new Type[] { body.Type }.Concat(body.Type.GetInterfaces()).FirstOrDefault(t => t.GetProperty(member) != null),
member);
}
body = Expression.Convert(body, typeof(TValue));
@@ -1811,11 +2154,11 @@ namespace Radzen
return source.IsEnum;
}
/// <summary>
/// Determines whether the specified type is a Nullable enum.
/// </summary>
/// <param name="source">The type.</param>
/// <returns><c>true</c> if the specified source is an enum; otherwise, <c>false</c>.</returns>
/// <summary>
/// Determines whether the specified type is a Nullable enum.
/// </summary>
/// <param name="source">The type.</param>
/// <returns><c>true</c> if the specified source is an enum; otherwise, <c>false</c>.</returns>
public static bool IsNullableEnum(Type source)
{
if (source == null) return false;
@@ -1845,7 +2188,6 @@ namespace Radzen
return false;
}
/// <summary>
/// Gets the type of the property.
/// </summary>
@@ -1857,15 +2199,30 @@ namespace Radzen
if (property.Contains("."))
{
var part = property.Split('.').FirstOrDefault();
return GetPropertyType(type?.GetProperty(part)?.PropertyType, property.Replace($"{part}.", ""));
return GetPropertyType(GetPropertyTypeIncludeInterface(type, part), property.Replace($"{part}.", ""));
}
return type?.GetProperty(property)?.PropertyType;
return GetPropertyTypeIncludeInterface(type, property);
}
private static Type GetPropertyTypeIncludeInterface(Type type, string property)
{
if (type != null)
{
return !type.IsInterface ?
type.GetProperty(property)?.PropertyType :
new Type[] { type }
.Concat(type.GetInterfaces())
.FirstOrDefault(t => t.GetProperty(property) != null)?
.GetProperty(property)?.PropertyType;
}
return null;
}
}
/// <summary>
/// Represents the common <see cref="RadzenTemplateForm{TItem}" /> API used by
/// Represents the common <see cref="RadzenTemplateForm{TItem}" /> API used by
/// its items. Injected as a cascading property in <see cref="IRadzenFormComponent" />.
/// </summary>
public interface IRadzenForm

View File

@@ -200,6 +200,7 @@ namespace Radzen
AutoFocusFirstElement = options != null ? options.AutoFocusFirstElement : true,
CloseDialogOnOverlayClick = options != null ? options.CloseDialogOnOverlayClick : false,
CloseDialogOnEsc = options != null ? options.CloseDialogOnEsc : true,
CssClass = options != null ? options.CssClass : "",
});
}
@@ -208,7 +209,7 @@ namespace Radzen
/// </summary>
/// <param name="result">The result.</param>
[JSInvokable("DialogService.Close")]
public void Close(dynamic result = null)
public virtual void Close(dynamic result = null)
{
var dialog = dialogs.LastOrDefault();
@@ -229,6 +230,9 @@ namespace Radzen
/// <inheritdoc />
public void Dispose()
{
reference?.Dispose();
reference = null;
UriHelper.LocationChanged -= UriHelper_OnLocationChanged;
}
@@ -243,7 +247,7 @@ namespace Radzen
{
var dialogOptions = new DialogOptions()
{
Width = options != null ? !string.IsNullOrEmpty(options.Width) ? options.Width : "355px" : "355px",
Width = options != null ? !string.IsNullOrEmpty(options.Width) ? options.Width : "" : "",
Height = options != null ? options.Height : null,
Left = options != null ? options.Left : null,
Top = options != null ? options.Top : null,
@@ -257,6 +261,7 @@ namespace Radzen
AutoFocusFirstElement = options != null ? options.AutoFocusFirstElement : true,
CloseDialogOnOverlayClick = options != null ? options.CloseDialogOnOverlayClick : false,
CloseDialogOnEsc = options != null ? options.CloseDialogOnEsc : true,
CssClass = options != null ? $"rz-dialog-confirm {options.CssClass}" : "rz-dialog-confirm",
};
await JSRuntime.InvokeAsync<string>("Radzen.openDialog", dialogOptions, Reference);
@@ -266,32 +271,79 @@ namespace Radzen
RenderFragment content = b =>
{
var i = 0;
b.OpenElement(i++, "div");
b.OpenElement(i++, "p");
b.AddAttribute(i++, "style", "margin-bottom: 20px;");
b.AddAttribute(i++, "class", "rz-dialog-confirm-message");
b.AddContent(i++, message);
b.CloseElement();
b.OpenElement(i++, "div");
b.AddAttribute(i++, "class", "row");
b.OpenElement(i++, "div");
b.AddAttribute(i++, "class", "col-md-12");
b.AddAttribute(i++, "class", "rz-dialog-confirm-buttons");
b.OpenComponent<Blazor.RadzenButton>(i++);
b.AddAttribute(i++, "Text", options != null ? options.OkButtonText : "Ok");
b.AddAttribute(i++, "Style", "margin-bottom: 10px; width: 150px");
b.AddAttribute(i++, "Click", EventCallback.Factory.Create<Microsoft.AspNetCore.Components.Web.MouseEventArgs>(this, () => ds.Close(true)));
b.CloseComponent();
b.OpenComponent<Blazor.RadzenButton>(i++);
b.AddAttribute(i++, "Text", options != null ? options.CancelButtonText : "Cancel");
b.AddAttribute(i++, "ButtonStyle", ButtonStyle.Secondary);
b.AddAttribute(i++, "Style", "margin-bottom: 10px; margin-left: 10px; width: 150px");
b.AddAttribute(i++, "Click", EventCallback.Factory.Create<Microsoft.AspNetCore.Components.Web.MouseEventArgs>(this, () => ds.Close(false)));
b.CloseComponent();
b.CloseElement();
};
return content;
}, dialogOptions);
}
/// <summary>
/// Displays a alert dialog.
/// </summary>
/// <param name="message">The message displayed to the user.</param>
/// <param name="title">The text displayed in the title bar of the dialog.</param>
/// <param name="options">The options.</param>
/// <returns><c>true</c> if the user clicked the OK button, <c>false</c> otherwise.</returns>
public async Task<bool?> Alert(string message = "", string title = "Message", AlertOptions options = null)
{
var dialogOptions = new DialogOptions()
{
Width = options != null ? !string.IsNullOrEmpty(options.Width) ? options.Width : "" : "",
Height = options != null ? options.Height : null,
Left = options != null ? options.Left : null,
Top = options != null ? options.Top : null,
Bottom = options != null ? options.Bottom : null,
ChildContent = options != null ? options.ChildContent : null,
ShowTitle = options != null ? options.ShowTitle : true,
ShowClose = options != null ? options.ShowClose : true,
Resizable = options != null ? options.Resizable : false,
Draggable = options != null ? options.Draggable : false,
Style = options != null ? options.Style : "",
AutoFocusFirstElement = options != null ? options.AutoFocusFirstElement : true,
CloseDialogOnOverlayClick = options != null ? options.CloseDialogOnOverlayClick : false,
CloseDialogOnEsc = options != null ? options.CloseDialogOnEsc : true,
CssClass = options != null ? $"rz-dialog-alert {options.CssClass}" : "rz-dialog-alert",
};
await JSRuntime.InvokeAsync<string>("Radzen.openDialog", dialogOptions, Reference);
return await OpenAsync(title, ds =>
{
RenderFragment content = b =>
{
var i = 0;
b.OpenElement(i++, "p");
b.AddAttribute(i++, "class", "rz-dialog-alert-message");
b.AddContent(i++, message);
b.CloseElement();
b.OpenElement(i++, "div");
b.AddAttribute(i++, "class", "rz-dialog-alert-buttons");
b.OpenComponent<Blazor.RadzenButton>(i++);
b.AddAttribute(i++, "Text", options != null ? options.OkButtonText : "Ok");
b.AddAttribute(i++, "Click", EventCallback.Factory.Create<Microsoft.AspNetCore.Components.Web.MouseEventArgs>(this, () => ds.Close(true)));
b.CloseComponent();
b.CloseElement();
};
return content;
@@ -377,17 +429,29 @@ namespace Radzen
/// </summary>
/// <value><c>true</c> if closeable; otherwise, <c>false</c>.</value>
public bool CloseDialogOnEsc { get; set; } = true;
/// <summary>
/// Gets or sets dialog box custom class
/// </summary>
public string CssClass { get; set; }
}
/// <summary>
/// Class ConfirmOptions.
/// </summary>
public class ConfirmOptions : DialogOptions
public class AlertOptions : DialogOptions
{
/// <summary>
/// Gets or sets the text of the OK button.
/// </summary>
public string OkButtonText { get; set; }
}
/// <summary>
/// Class ConfirmOptions.
/// </summary>
public class ConfirmOptions : AlertOptions
{
/// <summary>
/// Gets or sets the text of the Cancel button.
/// </summary>

View File

@@ -135,7 +135,14 @@ namespace Radzen
{
return !string.IsNullOrEmpty($"{internalValue}");
}
return internalValue != null;
else if (typeof(IEnumerable).IsAssignableFrom(typeof(T)))
{
return internalValue != null && ((IEnumerable)internalValue).Cast<object>().Any();
}
else
{
return internalValue != null;
}
}
}
@@ -153,7 +160,7 @@ namespace Radzen
internal object GetKey(object item)
{
var value = PropertyAccess.GetItemOrValueFromProperty(item, ValueProperty);
var value = GetItemOrValueFromProperty(item, ValueProperty);
if (!keys.Contains(value))
{
@@ -187,6 +194,13 @@ namespace Radzen
[Parameter]
public bool Multiple { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the user can select all values in multiple selection. Set to <c>true</c> by default.
/// </summary>
/// <value><c>true</c> if select all values is allowed; otherwise, <c>false</c>.</value>
[Parameter]
public bool AllowSelectAll { get; set; } = true;
/// <summary>
/// Gets or sets the template.
/// </summary>
@@ -247,7 +261,7 @@ namespace Radzen
if (!string.IsNullOrEmpty(ValueProperty))
{
System.Reflection.PropertyInfo pi = PropertyAccess.GetElementType(Data.GetType()).GetProperty(ValueProperty);
internalValue = selectedItems.Select(i => PropertyAccess.GetItemOrValueFromProperty(i, ValueProperty)).AsQueryable().Cast(pi.PropertyType);
internalValue = selectedItems.Select(i => GetItemOrValueFromProperty(i, ValueProperty)).AsQueryable().Cast(pi.PropertyType);
}
else
{
@@ -255,7 +269,19 @@ namespace Radzen
internalValue = selectedItems.AsQueryable().Cast(type);
}
await ValueChanged.InvokeAsync((T)internalValue);
if (typeof(IList).IsAssignableFrom(typeof(T)))
{
var list = (IList)Activator.CreateInstance(typeof(T));
foreach (var i in (IEnumerable)internalValue)
{
list.Add(i);
}
await ValueChanged.InvokeAsync((T)(object)list);
}
else
{
await ValueChanged.InvokeAsync((T)internalValue);
}
if (FieldIdentifier.FieldName != null) { EditContext?.NotifyFieldChanged(FieldIdentifier); }
await Change.InvokeAsync(internalValue);
@@ -266,7 +292,7 @@ namespace Radzen
{
if (LoadData.HasDelegate && !string.IsNullOrEmpty(ValueProperty))
{
return View != null && View.Cast<object>().All(i => IsItemSelectedByValue(PropertyAccess.GetValue(i, ValueProperty)));
return View != null && View.Cast<object>().All(i => IsItemSelectedByValue(GetItemOrValueFromProperty(i, ValueProperty)));
}
return View != null && selectedItems.Count == View.Cast<object>().Count();
@@ -336,14 +362,86 @@ namespace Radzen
selectedItem = null;
selectedItems.Clear();
}
OnDataChanged();
StateHasChanged();
InvokeAsync(OnDataChanged);
}
}
}
/// <inheritdoc/>
protected override void OnParametersSet()
{
base.OnParametersSet();
if (_data != null)
{
var query = _data.AsQueryable();
var type = query.ElementType;
if (type == typeof(object) && typeof(EnumerableQuery).IsAssignableFrom(query.GetType()) && query.Any())
{
type = query.FirstOrDefault().GetType();
}
if (!string.IsNullOrEmpty(ValueProperty))
{
valuePropertyGetter = PropertyAccess.Getter<object, object>(ValueProperty, type);
}
if (!string.IsNullOrEmpty(TextProperty))
{
textPropertyGetter = PropertyAccess.Getter<object, object>(TextProperty, type);
}
if (!string.IsNullOrEmpty(DisabledProperty))
{
disabledPropertyGetter = PropertyAccess.Getter<object, object>(DisabledProperty, type);
}
}
}
internal Func<object, object> valuePropertyGetter;
internal Func<object, object> textPropertyGetter;
internal Func<object, object> disabledPropertyGetter;
/// <summary>
/// Gets the item or value from property.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="property">The property.</param>
/// <returns>System.Object.</returns>
public object GetItemOrValueFromProperty(object item, string property)
{
if (property == TextProperty && textPropertyGetter != null)
{
return textPropertyGetter(item);
}
else if (property == ValueProperty && valuePropertyGetter != null)
{
return valuePropertyGetter(item);
}
else if (property == DisabledProperty && disabledPropertyGetter != null)
{
return disabledPropertyGetter(item);
}
return item;
}
#if NET5_0_OR_GREATER
/// <inheritdoc/>
protected override async Task OnDataChanged()
{
await base.OnDataChanged();
if (AllowVirtualization && Virtualize != null && !LoadData.HasDelegate)
{
await InvokeAsync(Virtualize.RefreshDataAsync);
}
}
#endif
/// <summary>
/// Gets the popup identifier.
/// </summary>
@@ -740,9 +838,9 @@ namespace Radzen
/// <returns><c>true</c> if the specified item is selected; otherwise, <c>false</c>.</returns>
internal bool isSelected(object item)
{
if (LoadData.HasDelegate && !string.IsNullOrEmpty(ValueProperty))
if (!string.IsNullOrEmpty(ValueProperty))
{
return IsItemSelectedByValue(PropertyAccess.GetValue(item, ValueProperty));
return IsItemSelectedByValue(GetItemOrValueFromProperty(item, ValueProperty));
}
else
{
@@ -752,7 +850,7 @@ namespace Radzen
}
else
{
return item == selectedItem;
return object.Equals(item,selectedItem);
}
}
}
@@ -777,6 +875,13 @@ namespace Radzen
}
}
/// <summary>
/// Gets or sets the item separator for Multiple dropdown.
/// </summary>
/// <value>Item separator</value>
[Parameter]
public string Separator { get; set; } = ",";
/// <summary>
/// Gets the items.
/// </summary>
@@ -890,7 +995,7 @@ namespace Radzen
selectedItem = item;
if (!string.IsNullOrEmpty(ValueProperty))
{
internalValue = PropertyAccess.GetItemOrValueFromProperty(item, ValueProperty);
internalValue = GetItemOrValueFromProperty(item, ValueProperty);
}
else
{
@@ -903,40 +1008,23 @@ namespace Radzen
}
else
{
if (!string.IsNullOrEmpty(ValueProperty))
{
if (LoadData.HasDelegate)
{
var v = PropertyAccess.GetValue(item, ValueProperty);
var si = (selectedItems ?? Enumerable.Empty<object>()).AsQueryable().Where($@"object.Equals({ValueProperty},@0)", v).FirstOrDefault();
if (si == null)
{
selectedItems.Add(item);
}
else
{
selectedItems.Remove(si);
}
}
else
{
UpdateSelectedItems(item);
}
}
else
{
UpdateSelectedItems(item);
}
UpdateSelectedItems(item);
if (!string.IsNullOrEmpty(ValueProperty))
{
System.Reflection.PropertyInfo pi = PropertyAccess.GetElementType(Data.GetType()).GetProperty(ValueProperty);
internalValue = selectedItems.Select(i => PropertyAccess.GetItemOrValueFromProperty(i, ValueProperty)).AsQueryable().Cast(pi.PropertyType);
internalValue = selectedItems.Select(i => GetItemOrValueFromProperty(i, ValueProperty)).AsQueryable().Cast(pi.PropertyType);
}
else
{
var firstElement = Data.Cast<object>().FirstOrDefault();
var elementType = firstElement != null ? firstElement.GetType() : null;
var query = Data.AsQueryable();
var elementType = query.ElementType;
if (elementType == typeof(object) && typeof(EnumerableQuery).IsAssignableFrom(query.GetType()) && query.Any())
{
elementType = query.FirstOrDefault().GetType();
}
if (elementType != null)
{
internalValue = selectedItems.AsQueryable().Cast(elementType);
@@ -951,7 +1039,26 @@ namespace Radzen
{
if (ValueChanged.HasDelegate)
{
await ValueChanged.InvokeAsync(object.Equals(internalValue, null) ? default(T) : (T)internalValue);
if (typeof(IList).IsAssignableFrom(typeof(T)))
{
if (object.Equals(internalValue, null))
{
await ValueChanged.InvokeAsync(default(T));
}
else
{
var list = (IList)Activator.CreateInstance(typeof(T));
foreach (var i in (IEnumerable)internalValue)
{
list.Add(i);
}
await ValueChanged.InvokeAsync((T)(object)list);
}
}
else
{
await ValueChanged.InvokeAsync(object.Equals(internalValue, null) ? default(T) : (T)internalValue);
}
}
if (FieldIdentifier.FieldName != null) { EditContext?.NotifyFieldChanged(FieldIdentifier); }
@@ -963,13 +1070,29 @@ namespace Radzen
internal void UpdateSelectedItems(object item)
{
if (selectedItems.IndexOf(item) == -1)
if (!string.IsNullOrEmpty(ValueProperty))
{
selectedItems.Add(item);
var value = GetItemOrValueFromProperty(item, ValueProperty);
if (!IsItemSelectedByValue(value))
{
selectedItems.Add(item);
}
else
{
selectedItems = selectedItems.AsQueryable().Where($@"!object.Equals({ValueProperty},@0)", value).ToList();
}
}
else
{
selectedItems.Remove(item);
if (!selectedItems.Any(i => object.Equals(i, item)))
{
selectedItems.Add(item);
}
else
{
selectedItems = selectedItems.Where(i => !object.Equals(i, item)).ToList();
}
}
}
@@ -987,7 +1110,7 @@ namespace Radzen
{
if (typeof(EnumerableQuery).IsAssignableFrom(View.GetType()))
{
SelectedItem = View.OfType<object>().Where(i => object.Equals(PropertyAccess.GetValue(i, ValueProperty), value)).FirstOrDefault();
SelectedItem = View.OfType<object>().Where(i => object.Equals(GetItemOrValueFromProperty(i, ValueProperty), value)).FirstOrDefault();
}
else
{
@@ -1016,14 +1139,14 @@ namespace Radzen
if (typeof(EnumerableQuery).IsAssignableFrom(View.GetType()))
{
item = View.OfType<object>().Where(i => object.Equals(PropertyAccess.GetValue(i, ValueProperty), v)).FirstOrDefault();
item = View.OfType<object>().Where(i => object.Equals(GetItemOrValueFromProperty(i, ValueProperty), v)).FirstOrDefault();
}
else
{
item = View.AsQueryable().Where($@"{ValueProperty} == @0", v).FirstOrDefault();
}
if (!object.Equals(item, null) && (LoadData.HasDelegate ? !IsItemSelectedByValue(v) : selectedItems.IndexOf(item) == -1))
if (!object.Equals(item, null) && !selectedItems.AsQueryable().Where($@"object.Equals({ValueProperty},@0)", v).Any())
{
selectedItems.Add(item);
}
@@ -1045,8 +1168,20 @@ namespace Radzen
internal bool IsItemSelectedByValue(object v)
{
return ((Multiple ? selectedItems : selectedItem != null ? new[] { selectedItem } : Enumerable.Empty<object>()) ?? Enumerable.Empty<object>())
.AsQueryable().Where($@"object.Equals({ValueProperty},@0)", v).Any();
if (internalValue != null)
{
var values = internalValue as IEnumerable;
if (values != null)
{
return values.Cast<object>().Contains(v);
}
else
{
return object.Equals(internalValue, v);
}
}
return false;
}
/// <inheritdoc />

View File

@@ -65,7 +65,13 @@ namespace Radzen.Blazor
if (start == end)
{
start = 0;
end = end + NiceNumber(end / ticks, false);
end += NiceNumber(end / ticks, false);
}
if (Round && end < 0)
{
end = 0;
start += NiceNumber(start / ticks, false);
}
var range = end - start;

View File

@@ -1,4 +1,6 @@
using System;
using Microsoft.AspNetCore.Components;
using Radzen.Blazor;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
@@ -35,7 +37,10 @@ namespace Radzen
Severity = message.Severity,
Summary = message.Summary,
Detail = message.Detail,
Style = message.Style
Style = message.Style,
Click = message.Click,
CloseOnClick = message.CloseOnClick,
Payload = message.Payload
};
if (!Messages.Contains(newMessage))
@@ -44,21 +49,27 @@ namespace Radzen
}
}
/// <summary>
/// Notifies the specified severity.
/// </summary>
/// <param name="severity">The severity.</param>
/// <param name="summary">The summary.</param>
/// <param name="detail">The detail.</param>
/// <param name="duration">The duration.</param>
public void Notify(NotificationSeverity severity = NotificationSeverity.Info, string summary = "", string detail = "", double duration = 3000)
/// <summary>
/// Notifies the specified severity.
/// </summary>
/// <param name="severity">The severity.</param>
/// <param name="summary">The summary.</param>
/// <param name="detail">The detail.</param>
/// <param name="duration">The duration.</param>
/// <param name="click">The click event.</param>
/// <param name="closeOnClick">If true, then the notification will be closed when clicked on.</param>
/// <param name="payload">Used to store a custom payload that can be retreived later in the click event handler.</param>
public void Notify(NotificationSeverity severity = NotificationSeverity.Info, string summary = "", string detail = "", double duration = 3000, Action<NotificationMessage> click = null, bool closeOnClick = false, object payload = null)
{
var newMessage = new NotificationMessage()
{
Duration = duration,
Severity = severity,
Summary = summary,
Detail = detail
Detail = detail,
Click = click,
CloseOnClick = closeOnClick,
Payload = payload
};
if (!Messages.Contains(newMessage))
@@ -98,5 +109,20 @@ namespace Radzen
/// </summary>
/// <value>The style.</value>
public string Style { get; set; }
}
/// <summary>
/// Gets or sets the click event.
/// </summary>
/// <value>This event handler is called when the notification is clicked on.</value>
public Action<NotificationMessage> Click { get; set; }
/// <summary>
/// Gets or sets click on close action.
/// </summary>
/// <value>If true, then the notification will be closed when clicked on.</value>
public bool CloseOnClick { get; set; }
/// <summary>
/// Gets or sets notification payload.
/// </summary>
/// <value>Used to store a custom payload that can be retreived later in the click event handler.</value>
public object Payload { get; set; }
}
}

View File

@@ -141,10 +141,7 @@ namespace Radzen
[Parameter]
public string PagingSummaryFormat { get; set; } = "Page {0} of {1} ({2} items)";
/// <summary>
/// The view
/// </summary>
protected IQueryable<T> _view = null;
internal IQueryable<T> _view = null;
/// <summary>
/// Gets the paged view.
/// </summary>
@@ -311,13 +308,13 @@ namespace Radzen
await InvokeAsync(Reload);
}
int? pageSize;
internal int? pageSize;
/// <summary>
/// Called when [page size changed].
/// </summary>
/// <param name="value">The value.</param>
protected async Task OnPageSizeChanged(int value)
protected virtual async Task OnPageSizeChanged(int value)
{
pageSize = value;
await InvokeAsync(Reload);
@@ -345,16 +342,17 @@ namespace Radzen
/// Goes to page.
/// </summary>
/// <param name="page">The page.</param>
public async Task GoToPage(int page)
/// <param name="forceReload">if set to <c>true</c> [force reload].</param>
public async Task GoToPage(int page, bool forceReload = false)
{
if (topPager != null)
{
await topPager.GoToPage(page);
await topPager.GoToPage(page, forceReload);
}
if (bottomPager != null)
{
await bottomPager.GoToPage(page);
await bottomPager.GoToPage(page, forceReload);
}
}

View File

@@ -419,11 +419,11 @@ namespace Radzen
}
else if (columnFilterOperator == FilterOperator.IsEmpty)
{
return $@"np({property}) == ''";
return $@"np({property}) == """"";
}
else if (columnFilterOperator == FilterOperator.IsNotEmpty)
{
return $@"np({property}) != ''";
return $@"np({property}) != """"";
}
else if (columnFilterOperator == FilterOperator.IsNotNull)
{
@@ -438,7 +438,7 @@ namespace Radzen
}
else if (column.GetFilterOperator() == FilterOperator.IsEmpty || column.GetFilterOperator() == FilterOperator.IsNotEmpty)
{
return $"{property} {linqOperator} ''";
return $@"{property} {linqOperator} """"";
}
else
{
@@ -456,7 +456,7 @@ namespace Radzen
}
else if (column.GetFilterOperator() == FilterOperator.IsEmpty || column.GetFilterOperator() == FilterOperator.IsNotEmpty)
{
return $"{property} {linqOperator} ''";
return $@"{property} {linqOperator} """"";
}
else
{
@@ -480,7 +480,7 @@ namespace Radzen
}
else if (column.GetFilterOperator() == FilterOperator.IsEmpty || column.GetFilterOperator() == FilterOperator.IsNotEmpty)
{
return $"{property} {linqOperator} ''";
return $@"{property} {linqOperator} """"";
}
else
{
@@ -1033,6 +1033,132 @@ namespace Radzen
return source;
}
/// <summary>
/// Wheres the specified filters.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source">The source.</param>
/// <param name="dataFilter">The DataFilter.</param>
/// <returns>IQueryable&lt;T&gt;.</returns>
public static IQueryable<T> Where<T>(this IQueryable<T> source, RadzenDataFilter<T> dataFilter)
{
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 (dataFilter.Filters.Where(canFilter).Any())
{
var index = 0;
var filterExpressions = new List<string>();
var filterValues = new List<object[]>();
foreach (var filter in dataFilter.Filters)
{
AddWhereExpression(canFilter, filter, ref filterExpressions, ref filterValues, ref index, dataFilter);
}
return filterExpressions.Any() ?
source.Where(string.Join($" {dataFilter.LogicalFilterOperator.ToString().ToLower()} ", filterExpressions), filterValues.SelectMany(i => i.ToArray()).ToArray())
: source;
}
return source;
}
private static void AddWhereExpression<T>(Func<CompositeFilterDescriptor, bool> canFilter, CompositeFilterDescriptor filter, ref List<string> filterExpressions, ref List<object[]> filterValues, ref int index, RadzenDataFilter<T> dataFilter)
{
if (filter.Filters != null)
{
var innerFilterExpressions = new List<string>();
foreach (var f in filter.Filters)
{
AddWhereExpression(canFilter, f, ref innerFilterExpressions, ref filterValues, ref index, dataFilter);
}
if (innerFilterExpressions.Any())
{
filterExpressions.Add("(" + string.Join($" {filter.LogicalFilterOperator.ToString().ToLower()} ", innerFilterExpressions) + ")");
}
}
else
{
var property = PropertyAccess.GetProperty(filter.Property);
if (property.IndexOf(".") != -1)
{
property = $"({property})";
}
var column = dataFilter.properties.Where(c => c.Property == filter.Property).FirstOrDefault();
if (column == null) return;
if (column.FilterPropertyType == typeof(string) &&
!(filter.FilterOperator == FilterOperator.IsNotNull || filter.FilterOperator == FilterOperator.IsNull
|| filter.FilterOperator == FilterOperator.IsEmpty || filter.FilterOperator == FilterOperator.IsNotEmpty))
{
property = $@"({property} == null ? """" : {property})";
}
string filterCaseSensitivityOperator = column.FilterPropertyType == typeof(string)
&& filter.FilterOperator != FilterOperator.IsNotNull && filter.FilterOperator != FilterOperator.IsNull
&& filter.FilterOperator != FilterOperator.IsEmpty && filter.FilterOperator != FilterOperator.IsNotEmpty
&& dataFilter.FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ? ".ToLower()" : "";
var comparison = LinqFilterOperators[filter.FilterOperator];
if (comparison == "StartsWith" || comparison == "EndsWith" || comparison == "Contains")
{
if (column.FilterPropertyType == typeof(string) && filter.FilterValue == null)
{
filter.FilterValue = "";
}
if (IsEnumerable(column.FilterPropertyType) && column.FilterPropertyType != typeof(string) && comparison == "Contains")
{
filterExpressions.Add($@"(@{index}).Contains({property})");
filterValues.Add(new object[] { filter.FilterValue });
}
else
{
filterExpressions.Add($@"{property}{filterCaseSensitivityOperator}.{comparison}(@{index}{filterCaseSensitivityOperator})");
filterValues.Add(new object[] { filter.FilterValue });
}
index++;
}
else if (comparison == "DoesNotContain")
{
if (column.FilterPropertyType == typeof(string) && filter.FilterValue == null)
{
filter.FilterValue = "";
}
if (IsEnumerable(column.FilterPropertyType) && column.FilterPropertyType != typeof(string) && comparison == "DoesNotContain")
{
filterExpressions.Add($@"!(@{index}).Contains({property})");
filterValues.Add(new object[] { filter.FilterValue });
}
else
{
filterExpressions.Add($@"!{property}{filterCaseSensitivityOperator}.Contains(@{index}{filterCaseSensitivityOperator})");
filterValues.Add(new object[] { filter.FilterValue });
}
index++;
}
else if (!(IsEnumerable(column.FilterPropertyType) && column.FilterPropertyType != typeof(string)))
{
filterExpressions.Add($@"{property}{filterCaseSensitivityOperator} {comparison} @{index}{filterCaseSensitivityOperator}");
filterValues.Add(new object[] { filter.FilterValue });
index++;
}
}
}
/// <summary>
/// Ases the o data enumerable.
/// </summary>

105
Radzen.Blazor/README.md Normal file
View File

@@ -0,0 +1,105 @@
## 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.
![Radzen Blazor Components](https://raw.githubusercontent.com/radzenhq/radzen-blazor/master/RadzenBlazorDemos/wwwroot/images/radzen-blazor-components.png)
## 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/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/pricing/).
Our flagship product [Radzen Studio](https://www.radzen.com/features/) provides tons of productivity features for Blazor developers:
- The first in the industry 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 before .NET 6) or `wwwroot/index.html` (Blazor WebAssembly) and include the CSS file of 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 before .NET 6) 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()
{
}
}
```

View File

@@ -1,18 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<NoWarn>BL9993</NoWarn>
<TargetFrameworks>netstandard2.1;net5.0;net6.0</TargetFrameworks>
<TargetFrameworks>netstandard2.1;net5.0;net6.0;net7.0</TargetFrameworks>
<RazorLangVersion>3.0</RazorLangVersion>
<LangVersion>7.3</LangVersion>
<OutputType>Library</OutputType>
<IsPackable>true</IsPackable>
<PackageId>Radzen.Blazor</PackageId>
<Product>Radzen.Blazor</Product>
<Version>3.20.3</Version>
<Version>4.3.1</Version>
<Copyright>Radzen Ltd.</Copyright>
<Authors>Radzen Ltd.</Authors>
<Description>Native Blazor UI components by Radzen Ltd.</Description>
<PackageTags>blazor blazor-component blazor-grid blazor-datagrid</PackageTags>
<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>
<PackageTags>blazor material design fluent fluentui components datagrid scheduler charts</PackageTags>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageProjectUrl>https://www.radzen.com</PackageProjectUrl>
<PackageIcon>icon.png</PackageIcon>
<PackageLicenseFile>LICENSE.txt</PackageLicenseFile>
@@ -28,13 +29,16 @@
<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.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Condition="'$(TargetFramework)' == 'net6.0'" Version="6.0.0" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="Microsoft.AspNetCore.Components" Condition="'$(TargetFramework)' == 'net7.0'" Version="7.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Condition="'$(TargetFramework)' == 'net7.0'" Version="7.0.0" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.2.12" />
</ItemGroup>
<ItemGroup>
<None Include="LICENSE.txt" Pack="true" PackagePath="" />
<None Include="icon.png" Pack="true" PackagePath="" />
<None Include="README.md" Pack="true" PackagePath="\"/>
</ItemGroup>
<ItemGroup>

View File

@@ -0,0 +1,81 @@
@inherits RadzenComponentWithChildren
@if (GetVisible())
{
<div @ref="@Element" style="@Style" @attributes="Attributes" class="@GetCssClass()" id="@GetId()" aria-live="polite">
<div class="rz-alert-item">
@if (ShowIcon)
{
<RadzenIcon Icon="@getIcon()" Class="rz-alert-icon" />
}
<div class="rz-alert-message">
@if (!string.IsNullOrEmpty(Title))
{
<div class="rz-alert-title">@Title</div>
}
<div class="rz-alert-content">@ChildContent</div>
</div>
</div>
@if (AllowClose)
{
if (Shade == Shade.Lighter)
{
if (AlertStyle == AlertStyle.Primary)
{
<RadzenButton Click=@Close Icon="close" Variant="Variant.Text" ButtonStyle="ButtonStyle.Primary" Shade="Shade.Dark" Size="@getCloseButtonSize()" />
}
else if (AlertStyle == AlertStyle.Secondary)
{
<RadzenButton Click=@Close Icon="close" Variant="Variant.Text" ButtonStyle="ButtonStyle.Secondary" Shade="Shade.Dark" Size="@getCloseButtonSize()" />
}
else if (AlertStyle == AlertStyle.Light)
{
<RadzenButton Click=@Close Icon="close" Variant="Variant.Text" ButtonStyle="ButtonStyle.Dark" Shade="Shade.Dark" Size="@getCloseButtonSize()" />
}
else if (AlertStyle == AlertStyle.Base)
{
<RadzenButton Click=@Close Icon="close" Variant="Variant.Text" ButtonStyle="ButtonStyle.Dark" Shade="Shade.Dark" Size="@getCloseButtonSize()" />
}
else if (AlertStyle == AlertStyle.Dark)
{
<RadzenButton Click=@Close Icon="close" Variant="Variant.Text" ButtonStyle="ButtonStyle.Light" Shade="Shade.Dark" Size="@getCloseButtonSize()" />
}
else if (AlertStyle == AlertStyle.Success)
{
<RadzenButton Click=@Close Icon="close" Variant="Variant.Text" ButtonStyle="ButtonStyle.Success" Shade="Shade.Dark" Size="@getCloseButtonSize()" />
}
else if (AlertStyle == AlertStyle.Danger)
{
<RadzenButton Click=@Close Icon="close" Variant="Variant.Text" ButtonStyle="ButtonStyle.Danger" Shade="Shade.Dark" Size="@getCloseButtonSize()" />
}
else if (AlertStyle == AlertStyle.Warning)
{
<RadzenButton Click=@Close Icon="close" Variant="Variant.Text" ButtonStyle="ButtonStyle.Warning" Shade="Shade.Dark" Size="@getCloseButtonSize()" />
}
else if (AlertStyle == AlertStyle.Info)
{
<RadzenButton Click=@Close Icon="close" Variant="Variant.Text" ButtonStyle="ButtonStyle.Info" Shade="Shade.Dark" Size="@getCloseButtonSize()" />
}
}
else
{
if (AlertStyle == AlertStyle.Light)
{
<RadzenButton Click=@Close Icon="close" Variant="Variant.Text" ButtonStyle="ButtonStyle.Dark" Size="@getCloseButtonSize()" />
}
else if (AlertStyle == AlertStyle.Base)
{
<RadzenButton Click=@Close Icon="close" Variant="Variant.Text" ButtonStyle="ButtonStyle.Dark" Size="@getCloseButtonSize()" />
}
else if (AlertStyle == AlertStyle.Dark)
{
<RadzenButton Click=@Close Icon="close" Variant="Variant.Text" ButtonStyle="ButtonStyle.Light" Size="@getCloseButtonSize()" />
}
else
{
<RadzenButton Click=@Close Icon="close" Variant="Variant.Text" ButtonStyle="ButtonStyle.Light" Size="@getCloseButtonSize()" />
}
}
}
</div>
}

View File

@@ -0,0 +1,151 @@
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using System;
using System.Threading.Tasks;
namespace Radzen.Blazor
{
/// <summary>
/// RadzenAlert component.
/// </summary>
/// <example>
/// <code>
/// &lt;RadzenAlert&gt;
/// &lt;ChildContent&gt;
/// Content
/// &lt;/ChildContent&gt;
/// &lt;/RadzenAlert&gt;
/// </code>
/// </example>
public partial class RadzenAlert : RadzenComponentWithChildren
{
private string getAlertSize()
{
return Size == AlertSize.Medium ? "md" : Size == AlertSize.Large ? "lg" : Size == AlertSize.Small ? "sm" : "xs";
}
/// <summary>
/// Gets or sets a value indicating whether close is allowed. Set to <c>true</c> by default.
/// </summary>
/// <value><c>true</c> if close is allowed; otherwise, <c>false</c>.</value>
[Parameter]
public bool AllowClose { get; set; } = true;
/// <summary>
/// Gets or sets a value indicating whether icon should be shown. Set to <c>true</c> by default.
/// </summary>
/// <value><c>true</c> if icon is shown; otherwise, <c>false</c>.</value>
[Parameter]
public bool ShowIcon { get; set; } = true;
/// <summary>
/// Gets or sets the title.
/// </summary>
/// <value>The title.</value>
[Parameter]
public string Title { get; set; }
/// <summary>
/// Gets or sets the icon.
/// </summary>
/// <value>The icon.</value>
[Parameter]
public string Icon { get; set; }
/// <summary>
/// Gets or sets the severity.
/// </summary>
/// <value>The severity.</value>
[Parameter]
public AlertStyle AlertStyle { get; set; } = AlertStyle.Base;
/// <summary>
/// Gets or sets the design variant of the alert.
/// </summary>
/// <value>The variant of the alert.</value>
[Parameter]
public Variant Variant { get; set; } = Variant.Filled;
/// <summary>
/// Gets or sets the color shade of the alert.
/// </summary>
/// <value>The color shade of the alert.</value>
[Parameter]
public Shade Shade { get; set; } = Shade.Default;
/// <summary>
/// Gets or sets the size.
/// </summary>
/// <value>The size.</value>
[Parameter]
public AlertSize Size { get; set; } = AlertSize.Medium;
ButtonSize getCloseButtonSize()
{
return Size == AlertSize.ExtraSmall ? ButtonSize.ExtraSmall : ButtonSize.Small;
}
bool? visible;
bool GetVisible()
{
return visible ?? Visible;
}
/// <inheritdoc />
protected override string GetComponentCssClass()
{
return $"rz-alert rz-alert-{getAlertSize()} rz-variant-{Enum.GetName(typeof(Variant), Variant).ToLowerInvariant()} rz-{Enum.GetName(typeof(AlertStyle), AlertStyle).ToLowerInvariant()} rz-shade-{Enum.GetName(typeof(Shade), Shade).ToLowerInvariant()}";
}
string getIcon()
{
if (!string.IsNullOrEmpty(Icon))
{
return Icon;
}
else if (AlertStyle == AlertStyle.Primary)
{
return "lightbulb_outline";
}
else if (AlertStyle == AlertStyle.Secondary)
{
return "lightbulb_outline";
}
else if (AlertStyle == AlertStyle.Light)
{
return "lightbulb_outline";
}
else if (AlertStyle == AlertStyle.Base)
{
return "lightbulb_outline";
}
else if (AlertStyle == AlertStyle.Dark)
{
return "lightbulb_outline";
}
else if (AlertStyle == AlertStyle.Success)
{
return "check_circle_outline";
}
else if (AlertStyle == AlertStyle.Danger)
{
return "error_outline";
}
else if (AlertStyle == AlertStyle.Warning)
{
return "warning_amber";
}
else if (AlertStyle == AlertStyle.Info)
{
return "info_outline";
}
return "";
}
void Close()
{
visible = false;
}
}
}

View File

@@ -10,19 +10,39 @@
@if (Visible)
{
<div @ref="@Element" style="@($"{Style};display:inline-block;")" @attributes="Attributes" class="@GetCssClass()" id="@GetId()">
<input @ref="@search" @onkeydown="@OnFilterKeyPress" value="@Value" disabled="@Disabled"
onkeypress="@OpenScript()" tabindex="@TabIndex" @onchange="@OnChange"
@if (Multiline)
{
<textarea @ref="@search" @onkeydown="@OnFilterKeyPress" value="@Value" disabled="@Disabled"
oninput="@OpenScript()" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" @onchange="@OnChange"
aria-autocomplete="list" aria-haspopup="true" autocomplete="off" role="combobox"
class="@InputClassList"
id="@Name" aria-expanded="true" placeholder="@Placeholder" />
}
else
{
<input @ref="@search" @onkeydown="@OnFilterKeyPress" value="@Value" disabled="@Disabled"
oninput="@OpenScript()" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" @onchange="@OnChange"
aria-autocomplete="list" aria-haspopup="true" autocomplete="off" role="combobox"
class="@InputClassList"
type="text" id="@Name" aria-expanded="true" placeholder="@Placeholder" />
<div id="@PopupID" class="rz-autocomplete-panel" style="display:none; transform: none; box-sizing: border-box; max-height: 200px;">
}
<div id="@PopupID" class="rz-autocomplete-panel" style="@PopupStyle">
<ul @ref="@list" class="rz-autocomplete-items rz-autocomplete-list" role="listbox">
@if (!string.IsNullOrEmpty(searchText) || !string.IsNullOrEmpty(customSearchText))
{
@foreach (var item in LoadData.HasDelegate ? Data != null ? Data : Enumerable.Empty<object>() : (View != null ? View : Enumerable.Empty<object>()))
{
<li role="option" class="rz-autocomplete-list-item" @onclick="@(() => OnSelectItem(item))" onmousedown="Radzen.activeElement = null">
<span>@PropertyAccess.GetItemOrValueFromProperty(item, TextProperty)</span>
<span>
@if (Template != null)
{
@Template(item)
}
else
{
@PropertyAccess.GetItemOrValueFromProperty(item, TextProperty)
}
</span>
</li>
}
}

View File

@@ -22,6 +22,27 @@ namespace Radzen.Blazor
/// </example>
public partial class RadzenAutoComplete : DataBoundFormComponent<string>
{
/// <summary>
/// Gets or sets a value indicating whether this <see cref="RadzenAutoComplete"/> is multiline.
/// </summary>
/// <value><c>true</c> if multiline; otherwise, <c>false</c>.</value>
[Parameter]
public bool Multiline { get; set; }
/// <summary>
/// Gets or sets the Popup height.
/// </summary>
/// <value>The number Popup height.</value>
[Parameter]
public string PopupStyle { get; set; } = "display:none; transform: none; box-sizing: border-box; max-height: 200px;";
/// <summary>
/// Gets or sets the template.
/// </summary>
/// <value>The template.</value>
[Parameter]
public RenderFragment<dynamic> Template { get; set; }
/// <summary>
/// Gets or sets the minimum length.
/// </summary>
@@ -148,7 +169,9 @@ namespace Radzen.Blazor
{
string filterCaseSensitivityOperator = FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ? ".ToLower()" : "";
return Query.Where($"{TextProperty}{filterCaseSensitivityOperator}.{Enum.GetName(typeof(StringFilterOperator), FilterOperator)}(@0)",
string textProperty = string.IsNullOrEmpty(TextProperty) ? string.Empty : $".{TextProperty}";
return Query.Where($"o=>o{textProperty}{filterCaseSensitivityOperator}.{Enum.GetName(typeof(StringFilterOperator), FilterOperator)}(@0)",
FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ? searchText.ToLower() : searchText);
}

View File

@@ -20,6 +20,8 @@ namespace Radzen.Blazor
classList.Add("rz-badge");
classList.Add($"rz-badge-{BadgeStyle.ToString().ToLowerInvariant()}");
classList.Add($"rz-variant-{Variant.ToString().ToLowerInvariant()}");
classList.Add($"rz-shade-{Shade.ToString().ToLowerInvariant()}");
if (IsPill)
{
@@ -50,6 +52,20 @@ namespace Radzen.Blazor
[Parameter]
public BadgeStyle BadgeStyle { get; set; }
/// <summary>
/// Gets or sets the badge variant.
/// </summary>
/// <value>The badge variant.</value>
[Parameter]
public Variant Variant { get; set; } = Variant.Filled;
/// <summary>
/// Gets or sets the badge shade color.
/// </summary>
/// <value>The badge shade color.</value>
[Parameter]
public Shade Shade { get; set; } = Shade.Default;
/// <summary>
/// Gets or sets a value indicating whether this instance is pill.
/// </summary>

View File

@@ -21,6 +21,13 @@ namespace Radzen.Blazor
[Parameter]
public double Margin { get; set; } = 10;
/// <summary>
/// Gets or sets the height of all bars in pixels. By default it is automatically calculated depending on the chart height.
/// </summary>
/// <value>The pixel height of the bar. By default set to <c>null</c></value>
[Parameter]
public double? Height { get; set;}
/// <inheritdoc />
protected override void Initialize()
{
@@ -30,7 +37,9 @@ namespace Radzen.Blazor
/// <inheritdoc />
protected override bool ShouldRefreshChart(ParameterView parameters)
{
return DidParameterChange(parameters, nameof(Radius), Radius) || DidParameterChange(parameters, nameof(Margin), Margin);
return DidParameterChange(parameters, nameof(Radius), Radius) ||
DidParameterChange(parameters, nameof(Height), Height) ||
DidParameterChange(parameters, nameof(Margin), Margin);
}
}
}

View File

@@ -121,9 +121,18 @@ namespace Radzen.Blazor
{
get
{
var availableHeight = Chart.ValueScale.OutputSize; // - (Chart.ValueAxis.Padding * 2);
var bands = VisibleBarSeries.Cast<IChartBarSeries>().Max(series => series.Count) + 2;
return availableHeight / bands;
var barSeries = VisibleBarSeries;
if (Chart.BarOptions.Height.HasValue)
{
return Chart.BarOptions.Height.Value * barSeries.Count;
}
else
{
var availableHeight = Chart.ValueScale.OutputSize; // - (Chart.ValueAxis.Padding * 2);
var bands = barSeries.Cast<IChartBarSeries>().Max(series => series.Count) + 2;
return availableHeight / bands;
}
}
}

View File

@@ -6,35 +6,37 @@
type="@Enum.GetName(typeof(ButtonType), ButtonType).ToLower()"
@attributes="Attributes" class="@GetCssClass()" id="@GetId()"
@onclick="@OnClick">
@if (ChildContent != null)
{
@ChildContent
}
else
{
@if (IsBusy)
<span class="rz-button-box">
@if (ChildContent != null)
{
<RadzenIcon Icon="refresh" Style="animation: rotation 700ms linear infinite" />
@if (!string.IsNullOrEmpty(BusyText))
{
<span class="rz-button-text">@BusyText</span>
}
@ChildContent
}
else
{
@if (!string.IsNullOrEmpty(@Icon))
@if (IsBusy)
{
<i class="rz-button-icon-left rzi">@((MarkupString)Icon)</i>
<RadzenIcon Icon="refresh" Style="animation: rotation 700ms linear infinite" />
@if (!string.IsNullOrEmpty(BusyText))
{
<span class="rz-button-text">@BusyText</span>
}
}
@if (!string.IsNullOrEmpty(Image))
else
{
<img class="rz-button-icon-left rzi" src="@Image" />
}
@if (!string.IsNullOrEmpty(Text))
{
<span class="rz-button-text">@Text</span>
@if (!string.IsNullOrEmpty(@Icon))
{
<i class="rz-button-icon-left rzi">@((MarkupString)Icon)</i>
}
@if (!string.IsNullOrEmpty(Image))
{
<img class="rz-button-icon-left rzi" src="@Image" />
}
@if (!string.IsNullOrEmpty(Text))
{
<span class="rz-button-text">@Text</span>
}
}
}
}
</span>
</button>
}

View File

@@ -17,7 +17,7 @@ namespace Radzen.Blazor
{
private string getButtonSize()
{
return Size == ButtonSize.Medium ? "md" : "sm";
return Size == ButtonSize.Medium ? "md" : Size == ButtonSize.Large ? "lg" : Size == ButtonSize.Small ? "sm" : "xs";
}
/// <summary>
@@ -62,6 +62,20 @@ namespace Radzen.Blazor
[Parameter]
public ButtonType ButtonType { get; set; } = ButtonType.Button;
/// <summary>
/// Gets or sets the design variant of the button.
/// </summary>
/// <value>The variant of the button.</value>
[Parameter]
public Variant Variant { get; set; } = Variant.Filled;
/// <summary>
/// Gets or sets the color shade of the button.
/// </summary>
/// <value>The color shade of the button.</value>
[Parameter]
public Shade Shade { get; set; } = Shade.Default;
/// <summary>
/// Gets or sets the size.
/// </summary>
@@ -131,7 +145,7 @@ namespace Radzen.Blazor
/// <inheritdoc />
protected override string GetComponentCssClass()
{
return $"rz-button rz-button-{getButtonSize()} btn-{Enum.GetName(typeof(ButtonStyle), ButtonStyle).ToLowerInvariant()}{(IsDisabled ? " rz-state-disabled" : "")}{(string.IsNullOrEmpty(Text) && !string.IsNullOrEmpty(Icon) ? " rz-button-icon-only" : "")}";
return $"rz-button rz-button-{getButtonSize()} rz-variant-{Enum.GetName(typeof(Variant), Variant).ToLowerInvariant()} rz-{Enum.GetName(typeof(ButtonStyle), ButtonStyle).ToLowerInvariant()} rz-shade-{Enum.GetName(typeof(Shade), Shade).ToLowerInvariant()}{(IsDisabled ? " rz-state-disabled" : "")}{(string.IsNullOrEmpty(Text) && !string.IsNullOrEmpty(Icon) ? " rz-button-icon-only" : "")}";
}
}
}

View File

@@ -13,7 +13,7 @@ namespace Radzen.Blazor
/// <inheritdoc />
protected override string GetComponentCssClass()
{
return "rz-card card";
return "rz-card";
}
}
}

View File

@@ -5,7 +5,7 @@
@inherits FormComponent<TValue>
@if (Visible)
{
<div @ref="@Element" @attributes="Attributes" class="@GetCssClass()" @onkeypress=@OnKeyPress @onkeypress:preventDefault style="@Style" tabindex="@TabIndex" id="@GetId()">
<div @ref="@Element" @attributes="Attributes" class="@GetCssClass()" @onkeypress=@OnKeyPress @onkeypress:preventDefault style="@Style" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" id="@GetId()">
<div class="rz-helper-hidden-accessible">
<input type="checkbox" @onchange=@Toggle value=@CheckBoxValue name=@Name id=@Name checked=@CheckBoxChecked
tabindex="-1">

View File

@@ -15,10 +15,17 @@
@if (Visible)
{
<div @ref="@Element" style="@Style" @attributes="Attributes" class="@GetCssClass()" id="@GetId()">
@if (AllowSelectAll)
{
<div class="rz-multiselect-header rz-helper-clearfix" @onclick:preventDefault>
<RadzenCheckBox Name="SelectAll" TValue="bool?" Value="@IsAllSelected()" Change="@SelectAll" />
<RadzenLabel Component="SelectAll" Text="@SelectAllText" class="rz-chkbox-label" />
</div>
}
@foreach (var item in allItems.Where(i => i.Visible))
{
<div class="rz-checkbox" @onclick="@(args => SelectItem(item))" @attributes="item.Attributes" style="@item.Style">
<div class="rz-chkbox " @onkeypress="@(async args => { if (args.Code == "Space") { await SelectItem(item); } })" tabindex="@TabIndex">
<div class="rz-chkbox " @onkeypress="@(async args => { if (args.Code == "Space") { await SelectItem(item); } })" tabindex="@(Disabled || item.Disabled ? "-1" : $"{TabIndex}")">
<div class="rz-helper-hidden-accessible">
<input type="checkbox" name="@Name" value="@item.Value" disabled="@Disabled" tabindex="-1">
</div>

View File

@@ -1,6 +1,7 @@
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using Radzen.Blazor.Rendering;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
@@ -59,6 +60,59 @@ namespace Radzen.Blazor
}
}
/// <summary>
/// Gets or sets a value indicating whether the user can select all values. Set to <c>false</c> by default.
/// </summary>
/// <value><c>true</c> if select all values is allowed; otherwise, <c>false</c>.</value>
[Parameter]
public bool AllowSelectAll { get; set; } = false;
/// <summary>
/// Gets or sets the select all text.
/// </summary>
/// <value>The select all text.</value>
[Parameter]
public string SelectAllText { get; set; }
async Task SelectAll(bool? value)
{
if (Disabled)
{
return;
}
if (value == true)
{
Value = items.Select(i => i.Value);
}
else if (value == false)
{
Value = null;
}
await ValueChanged.InvokeAsync(Value);
if (FieldIdentifier.FieldName != null) { EditContext?.NotifyFieldChanged(FieldIdentifier); }
await Change.InvokeAsync(Value);
StateHasChanged();
}
bool? IsAllSelected()
{
Func<RadzenCheckBoxListItem<TValue>, bool> predicate = i => Value != null && Value.Contains(i.Value);
var all = items.All(predicate);
var any = items.Any(predicate);
if (all)
{
return true;
}
else
{
return any ? null : (bool?)false;
}
}
IEnumerable _data = null;
/// <summary>
/// Gets or sets the data used to generate items.

View File

@@ -12,7 +12,7 @@
}
<div class="rz-colorpicker-value" style="background-color: @Color" ></div>
<button type="button" tabindex="-1" class="rz-colorpicker-trigger" disabled=@Disabled @onclick:preventDefault><i class="rzi" /></button>
<Popup @ref=@Popup class="rz-colorpicker-popup" Close=@Close Open=@Open>
<Popup Lazy=@(PopupRenderMode == PopupRenderMode.OnDemand) @ref=@Popup class="rz-colorpicker-popup" Close=@Close Open=@Open>
@if (ShowHSV)
{
<Draggable class="rz-saturation-picker rz-colorpicker-section" style=@($"background-color: {HSV.ToRGB().ToCSS()}") Drag=@OnSaturationMove>

View File

@@ -321,6 +321,13 @@ namespace Radzen.Blazor
[Parameter]
public RenderFragment ChildContent { get; set; }
/// <summary>
/// Gets or sets the render mode.
/// </summary>
/// <value>The render mode.</value>
[Parameter]
public PopupRenderMode PopupRenderMode { get; set; } = PopupRenderMode.Initial;
double SaturationHandleLeft { get; set; }
double HueHandleLeft { get; set; }
double AlphaHandleLeft { get; set; } = 1;

View File

@@ -21,6 +21,13 @@ namespace Radzen.Blazor
[Parameter]
public double Margin { get; set; } = 10;
/// <summary>
/// Gets or sets the width of all columns in pixels. By default it is automatically calculated depending on the chart width.
/// </summary>
/// <value>The pixel width of the column. By default set to <c>null</c></value>
[Parameter]
public double? Width { get; set;}
/// <inheritdoc />
protected override void Initialize()
{
@@ -30,7 +37,9 @@ namespace Radzen.Blazor
/// <inheritdoc />
protected override bool ShouldRefreshChart(ParameterView parameters)
{
return DidParameterChange(parameters, nameof(Radius), Radius) || DidParameterChange(parameters, nameof(Margin), Margin);
return DidParameterChange(parameters, nameof(Radius), Radius) ||
DidParameterChange(parameters, nameof(Width), Width) ||
DidParameterChange(parameters, nameof(Margin), Margin);
}
}
}

View File

@@ -116,9 +116,18 @@ namespace Radzen.Blazor
{
get
{
var availableWidth = Chart.CategoryScale.OutputSize - (Chart.CategoryAxis.Padding * 2);
var bands = VisibleColumnSeries.Cast<IChartColumnSeries>().Max(series => series.Count) + 2;
return availableWidth / bands;
var columnSeries = VisibleColumnSeries;
if (Chart.ColumnOptions.Width.HasValue)
{
return Chart.ColumnOptions.Width.Value * columnSeries.Count + Chart.ColumnOptions.Margin * (columnSeries.Count - 1);
}
else
{
var availableWidth = Chart.CategoryScale.OutputSize - (Chart.CategoryAxis.Padding * 2);
var bands = columnSeries.Cast<IChartColumnSeries>().Max(series => series.Count) + 2;
return availableWidth / bands;
}
}
}
@@ -164,7 +173,7 @@ namespace Radzen.Blazor
var index = columnSeries.IndexOf(this);
var padding = Chart.ColumnOptions.Margin;
var bandWidth = BandWidth;
var width = bandWidth / columnSeries.Count() - padding + padding / columnSeries.Count();
var width = Chart.ColumnOptions.Width ?? bandWidth / columnSeries.Count() - padding + padding / columnSeries.Count();
foreach (var data in Items)
{

View File

@@ -35,7 +35,7 @@ namespace Radzen.Blazor
/// }
/// </code>
/// </example>
public partial class RadzenContextMenu
public partial class RadzenContextMenu : IDisposable
{
/// <summary>
/// Gets or sets the unique identifier.
@@ -77,7 +77,28 @@ namespace Radzen.Blazor
await JSRuntime.InvokeVoidAsync("Radzen.openContextMenu",
menu.MouseEventArgs.ClientX,
menu.MouseEventArgs.ClientY,
UniqueID);
UniqueID,
Reference,
"RadzenContextMenu.CloseMenu");
}
}
private DotNetObjectReference<RadzenContextMenu> reference;
/// <summary>
/// Gets the reference for the current component.
/// </summary>
/// <value>The reference.</value>
protected DotNetObjectReference<RadzenContextMenu> Reference
{
get
{
if (reference == null)
{
reference = DotNetObjectReference.Create(this);
}
return reference;
}
}
@@ -96,9 +117,21 @@ namespace Radzen.Blazor
await InvokeAsync(() => { StateHasChanged(); });
}
/// <summary>
/// Closes this instance.
/// </summary>
[JSInvokable("RadzenContextMenu.CloseMenu")]
public void CloseMenu()
{
Service.Close();
}
/// <inheritdoc />
public void Dispose()
{
reference?.Dispose();
reference = null;
if (IsJSRuntimeAvailable)
{
JSRuntime.InvokeVoidAsync("Radzen.destroyPopup", UniqueID);

View File

@@ -0,0 +1,38 @@
@using System.Linq.Expressions
@typeparam TItem
@inherits RadzenComponent
@if (Properties != null)
{
<CascadingValue Value=this>
@Properties
</CascadingValue>
}
@if (Visible)
{
<div @ref="@Element" style="@Style" @attributes="Attributes" class="@GetCssClass()" id="@GetId()">
<RadzenSelectBar @bind-Value=LogicalFilterOperator Change="@((LogicalFilterOperator args) => { InvokeAsync(ChangeState); if(Auto) { InvokeAsync(Filter); } })" Size="ButtonSize.Small">
<Items>
<RadzenSelectBarItem Text="@AndOperatorText" Value="LogicalFilterOperator.And" title="@AndOperatorText" />
<RadzenSelectBarItem Text="@OrOperatorText" Value="LogicalFilterOperator.Or" title="@OrOperatorText" />
</Items>
</RadzenSelectBar>
<RadzenButton title="@ClearFilterText" class="rz-datafilter-item-clear" Icon="clear" Click="@(args => ClearFilters())" Visible=@(Filters.Any()) Variant="Variant.Text" Size="ButtonSize.Small" ButtonStyle="ButtonStyle.Dark" />
<ul class="rz-datafilter-group">
@foreach(var filter in Filters)
{
<li class="rz-datafilter-item @(filter.Filters != null ? "rz-datafilter-group-item" : "")">
<RadzenDataFilterItem DataFilter="@this" Filter="@filter" />
</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">
<RadzenSplitButtonItem Icon="add" Text="@AddFilterText" />
<RadzenSplitButtonItem Icon="playlist_add" Value="group" Text="@AddFilterGroupText" />
</RadzenSplitButton>
</li>
</ul>
</div>
}

View File

@@ -0,0 +1,378 @@
using Microsoft.AspNetCore.Components;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Radzen.Blazor
{
/// <summary>
/// RadzenDataFilter component.
/// </summary>
/// <typeparam name="TItem">The type of the item.</typeparam>
public partial class RadzenDataFilter<TItem> : RadzenComponent
{
/// <inheritdoc />
protected override string GetComponentCssClass()
{
return "rz-datafilter";
}
/// <summary>
/// Gets or sets the properties.
/// </summary>
/// <value>The properties.</value>
[Parameter]
public RenderFragment Properties { get; set; }
/// <summary>
/// The data
/// </summary>
IEnumerable<TItem> _data;
/// <summary>
/// Gets or sets the data.
/// </summary>
/// <value>The data.</value>
[Parameter]
public IEnumerable<TItem> Data
{
get
{
return _data;
}
set
{
if (_data != value)
{
_data = value;
StateHasChanged();
}
}
}
IQueryable<TItem> _view = null;
/// <summary>
/// Gets the view.
/// </summary>
/// <value>The view.</value>
public virtual IQueryable<TItem> View
{
get
{
if (_view == null)
{
_view = Data != null ? Data.AsQueryable().Where<TItem>(this) : Enumerable.Empty<TItem>().AsQueryable();
}
return _view;
}
}
/// <summary>
/// Gets or sets a value indicating whether this filter is automatic.
/// </summary>
/// <value><c>true</c> if filter automatic; otherwise, <c>false</c>.</value>
[Parameter]
public bool Auto { get; set; } = true;
/// <summary>
/// Gets or sets the filters.
/// </summary>
/// <value>The filters.</value>
public IEnumerable<CompositeFilterDescriptor> Filters { get; set; } = Enumerable.Empty<CompositeFilterDescriptor>();
/// <summary>
/// Gets or sets the logical filter operator.
/// </summary>
/// <value>The logical filter operator.</value>
[Parameter]
public LogicalFilterOperator LogicalFilterOperator { get; set; } = LogicalFilterOperator.And;
/// <summary>
/// Gets or sets the filter case sensitivity.
/// </summary>
/// <value>The filter case sensitivity.</value>
[Parameter]
public FilterCaseSensitivity FilterCaseSensitivity { get; set; } = FilterCaseSensitivity.Default;
/// <summary>
/// Gets or sets the filter text.
/// </summary>
/// <value>The filter text.</value>
[Parameter]
public string FilterText { get; set; } = "Filter";
/// <summary>
/// Gets or sets the enum filter select text.
/// </summary>
/// <value>The enum filter select text.</value>
[Parameter]
public string EnumFilterSelectText { get; set; } = "Select...";
/// <summary>
/// Gets or sets the and operator text.
/// </summary>
/// <value>The and operator text.</value>
[Parameter]
public string AndOperatorText { get; set; } = "And";
/// <summary>
/// Gets or sets the or operator text.
/// </summary>
/// <value>The or operator text.</value>
[Parameter]
public string OrOperatorText { get; set; } = "Or";
/// <summary>
/// Gets or sets the apply filter text.
/// </summary>
/// <value>The apply filter text.</value>
[Parameter]
public string ApplyFilterText { get; set; } = "Apply";
/// <summary>
/// Gets or sets the clear filter text.
/// </summary>
/// <value>The clear filter text.</value>
[Parameter]
public string ClearFilterText { get; set; } = "Clear all";
/// <summary>
/// Gets or sets the add filter text.
/// </summary>
/// <value>The add filter text.</value>
[Parameter]
public string AddFilterText { get; set; } = "Add filter";
/// <summary>
/// Gets or sets the remove filter text.
/// </summary>
/// <value>The remove filter text.</value>
[Parameter]
public string RemoveFilterText { get; set; } = "Remove filter";
/// <summary>
/// Gets or sets the add filter group text.
/// </summary>
/// <value>The add filter group text.</value>
[Parameter]
public string AddFilterGroupText { get; set; } = "Add filter group";
/// <summary>
/// Gets or sets the equals text.
/// </summary>
/// <value>The equals text.</value>
[Parameter]
public string EqualsText { get; set; } = "Equals";
/// <summary>
/// Gets or sets the not equals text.
/// </summary>
/// <value>The not equals text.</value>
[Parameter]
public string NotEqualsText { get; set; } = "Not equals";
/// <summary>
/// Gets or sets the less than text.
/// </summary>
/// <value>The less than text.</value>
[Parameter]
public string LessThanText { get; set; } = "Less than";
/// <summary>
/// Gets or sets the less than or equals text.
/// </summary>
/// <value>The less than or equals text.</value>
[Parameter]
public string LessThanOrEqualsText { get; set; } = "Less than or equals";
/// <summary>
/// Gets or sets the greater than text.
/// </summary>
/// <value>The greater than text.</value>
[Parameter]
public string GreaterThanText { get; set; } = "Greater than";
/// <summary>
/// Gets or sets the greater than or equals text.
/// </summary>
/// <value>The greater than or equals text.</value>
[Parameter]
public string GreaterThanOrEqualsText { get; set; } = "Greater than or equals";
/// <summary>
/// Gets or sets the ends with text.
/// </summary>
/// <value>The ends with text.</value>
[Parameter]
public string EndsWithText { get; set; } = "Ends with";
/// <summary>
/// Gets or sets the contains text.
/// </summary>
/// <value>The contains text.</value>
[Parameter]
public string ContainsText { get; set; } = "Contains";
/// <summary>
/// Gets or sets the does not contain text.
/// </summary>
/// <value>The does not contain text.</value>
[Parameter]
public string DoesNotContainText { get; set; } = "Does not contain";
/// <summary>
/// Gets or sets the starts with text.
/// </summary>
/// <value>The starts with text.</value>
[Parameter]
public string StartsWithText { get; set; } = "Starts with";
/// <summary>
/// Gets or sets the not null text.
/// </summary>
/// <value>The not null text.</value>
[Parameter]
public string IsNotNullText { get; set; } = "Is not null";
/// <summary>
/// Gets or sets the is null text.
/// </summary>
/// <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>
/// <value>The not empty text.</value>
[Parameter]
public string IsNotEmptyText { get; set; } = "Is not empty";
internal List<RadzenDataFilterProperty<TItem>> properties = new List<RadzenDataFilterProperty<TItem>>();
internal void AddProperty(RadzenDataFilterProperty<TItem> property)
{
if (!properties.Contains(property))
{
properties.Add(property);
}
StateHasChanged();
}
internal void RemoveProperty(RadzenDataFilterProperty<TItem> property)
{
if (properties.Contains(property))
{
properties.Remove(property);
}
if (!disposed)
{
try { InvokeAsync(StateHasChanged); } catch { }
}
}
/// <summary>
/// Recreates View using current Filters.
/// </summary>
public async Task Filter()
{
_view = null;
await ViewChanged.InvokeAsync(View);
}
// <summary>
/// Gets or sets the view changed callback.
/// </summary>
/// <value>The view changed callback.</value>
[Parameter]
public EventCallback<IQueryable<TItem>> ViewChanged { get; set; }
internal async Task ChangeState()
{
await InvokeAsync(StateHasChanged);
}
/// <summary>
/// Gets or sets the filter date format.
/// </summary>
/// <value>The filter date format.</value>
[Parameter]
public string FilterDateFormat { get; set; }
internal async Task AddFilter(bool isGroup)
{
if (isGroup)
{
Filters = Filters.Concat(new CompositeFilterDescriptor[]
{
new CompositeFilterDescriptor()
{
Filters = Enumerable.Empty<CompositeFilterDescriptor>()
}
}
);
}
else
{
Filters = Filters.Concat(new CompositeFilterDescriptor[] { new CompositeFilterDescriptor() });
}
if (Auto)
{
await Filter();
}
}
/// <summary>
/// Clear filters.
/// </summary>
public async Task ClearFilters()
{
Filters = Enumerable.Empty<CompositeFilterDescriptor>();
if (Auto)
{
await Filter();
}
}
/// <summary>
/// Add filter.
/// </summary>
public async Task AddFilter(CompositeFilterDescriptor filter)
{
Filters = Filters.Concat(new CompositeFilterDescriptor[] { filter });
if (Auto)
{
await Filter();
}
}
/// <summary>
/// Remove filter.
/// </summary>
public async Task RemoveFilter(CompositeFilterDescriptor filter)
{
Filters = Filters.Where(f => f != filter);
if (Auto)
{
await Filter();
}
}
}
}

View File

@@ -0,0 +1,262 @@
@typeparam TItem
@if (Filter.Filters != null)
{
<RadzenSelectBar @bind-Value=Filter.LogicalFilterOperator Change="@((LogicalFilterOperator args) => { InvokeAsync(ChangeState); InvokeAsync(ApplyFilter); })" Size="ButtonSize.Small">
<Items>
<RadzenSelectBarItem Text="@DataFilter.AndOperatorText" Value="LogicalFilterOperator.And" title="@DataFilter.AndOperatorText" />
<RadzenSelectBarItem Text="@DataFilter.OrOperatorText" Value="LogicalFilterOperator.Or" title="@DataFilter.OrOperatorText" />
</Items>
</RadzenSelectBar>
<RadzenButton title="@DataFilter.RemoveFilterText" class="rz-datafilter-item-clear" Icon="clear" Click="@RemoveFilter" Variant="Variant.Text" Size="ButtonSize.Small" ButtonStyle="ButtonStyle.Dark"/>
<ul class="rz-datafilter-group">
@foreach(var filter in Filter.Filters)
{
<li class="rz-datafilter-item @(filter.Filters != null ? "rz-datafilter-group-item" : "")">
<RadzenDataFilterItem DataFilter="@this.DataFilter" Filter="@filter" Parent=@this />
</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">
<RadzenSplitButtonItem Icon="add" Text="@DataFilter.AddFilterText" />
<RadzenSplitButtonItem Icon="playlist_add" Value="group" Text="@DataFilter.AddFilterGroupText" />
</RadzenSplitButton>
</li>
</ul>
}
else
{
<RadzenDropDown @bind-Value="@Filter.Property" Data="@(DataFilter?.properties)" ValueProperty="Property" TValue="string" Change="@OnPropertyChange">
<Template>
@{
var property = (RadzenDataFilterProperty<TItem>)context;
}
@(property.Title ?? property.Property)
</Template>
</RadzenDropDown>
if (property != null)
{
<RadzenDropDown @onclick:preventDefault="true" Data="@(property.GetFilterOperators().Select(t => new { Value = property.GetFilterOperatorText(t), Key = t }))"
TextProperty="Value" ValueProperty="Key" TValue="FilterOperator" @bind-Value="@Filter.FilterOperator" Change="@OnOperatorChange" />
@if (property.FilterTemplate != null)
{
<div class="rz-datafilter-editor" style="display:flex">
@property.FilterTemplate(property)
</div>
}
else if (PropertyAccess.IsNullableEnum(property.FilterPropertyType) || PropertyAccess.IsEnum(property.FilterPropertyType))
{
<RadzenDropDown AllowClear="false" AllowFiltering="false" TValue="@object" class="rz-datafilter-editor"
@bind-Value=@Filter.FilterValue Multiple="false" Placeholder="@DataFilter.EnumFilterSelectText" TextProperty="Text" ValueProperty="Value"
Data=@EnumExtensions.EnumAsKeyValuePair(Nullable.GetUnderlyingType(property.FilterPropertyType) ?? property.FilterPropertyType) Change=@(args => InvokeAsync(ApplyFilter))/>
}
else if (PropertyAccess.IsNumeric(property.FilterPropertyType))
{
@(DrawNumericFilter())
}
else if (PropertyAccess.IsDate(property.FilterPropertyType))
{
<RadzenDatePicker @bind-Value=@Filter.FilterValue TValue="@object" ShowTime="true" class="rz-datafilter-editor"
ShowTimeOkButton="true" DateFormat="@getFilterDateFormat()" Change=@(args => InvokeAsync(ApplyFilter)) />
}
else if (property.FilterPropertyType == typeof(bool) || property.FilterPropertyType == typeof(bool?))
{
<RadzenCheckBox TriState="true" TValue="@object" @bind-Value=@Filter.FilterValue Change=@(args => InvokeAsync(ApplyFilter)) class="rz-datafilter-check" />
}
else
{
<RadzenTextBox class="rz-datafilter-editor" Value="@($"{Filter.FilterValue}")" Change=@(args => { Filter.FilterValue = args; InvokeAsync(ApplyFilter); }) />
}
<RadzenButton title="@DataFilter.RemoveFilterText" class="rz-datafilter-item-clear" Icon="clear" Click="@RemoveFilter" Variant="Variant.Text" Size="ButtonSize.Small" ButtonStyle="ButtonStyle.Dark"/>
}
}
@code {
[Parameter]
public RadzenDataFilter<TItem> DataFilter { get; set; }
[Parameter]
public RadzenDataFilterItem<TItem> Parent { get; set; }
CompositeFilterDescriptor _filter;
[Parameter]
public CompositeFilterDescriptor Filter
{
get
{
return _filter;
}
set
{
_filter = value;
if (property == null && Filter.Filters == null)
{
property = (Filter.Property != null ? DataFilter.properties
.Where(c => object.Equals(c.Property, Filter.Property)) : DataFilter.properties).FirstOrDefault();
if (property != null)
{
property.FilterValueChange -= OnFilterValueChange;
property.FilterValueChange += OnFilterValueChange;
Filter.Property = property.Property;
Filter.FilterOperator = property.GetFilterOperator();
var v = property.GetFilterValue();
if (v != null)
{
Filter.FilterValue = v;
}
}
}
}
}
void OnFilterValueChange(object value)
{
if (property != null)
{
Filter.FilterValue = property.GetFilterValue();
}
}
RadzenDataFilterProperty<TItem> property;
async Task ApplyFilter()
{
if (DataFilter.Auto)
{
await DataFilter.Filter();
}
}
async Task OnPropertyChange(object p)
{
property.FilterValueChange -= OnFilterValueChange;
property = DataFilter.properties.Where(c => object.Equals(c.Property, p)).FirstOrDefault();
property.FilterValueChange += OnFilterValueChange;
Filter.FilterValue = null;
var defaultOperator = typeof(System.Collections.IEnumerable).IsAssignableFrom(property.FilterPropertyType) ? FilterOperator.Contains : default(FilterOperator);
Filter.FilterOperator = property.GetFilterOperators().Contains(defaultOperator) ? defaultOperator : property.GetFilterOperators().FirstOrDefault();
await ApplyFilter();
}
async Task OnOperatorChange(object p)
{
await ApplyFilter();
}
async Task AddFilter(bool isGroup)
{
if (isGroup)
{
Filter.Filters = Filter.Filters.Concat(new CompositeFilterDescriptor[]
{
new CompositeFilterDescriptor()
{
Filters = Enumerable.Empty<CompositeFilterDescriptor>()
}
}
);
}
else
{
Filter.Filters = Filter.Filters.Concat(new CompositeFilterDescriptor[] { new CompositeFilterDescriptor() });
}
if (DataFilter.Auto)
{
await DataFilter.Filter();
}
}
async Task RemoveFilter()
{
property = null;
if (Parent != null)
{
Parent.Filter.Filters = Parent.Filter.Filters.Where(f => f != Filter).ToList();
await Parent.ChangeState();
}
else
{
DataFilter.Filters = DataFilter.Filters.Where(f => f != Filter).ToList();
await DataFilter.ChangeState();
}
await ApplyFilter();
}
internal async Task ChangeState()
{
await InvokeAsync(StateHasChanged);
}
RenderFragment DrawNumericFilter()
{
return new RenderFragment(builder =>
{
var type = Nullable.GetUnderlyingType(property.FilterPropertyType) != null ?
property.FilterPropertyType : typeof(Nullable<>).MakeGenericType(property.FilterPropertyType);
var numericType = typeof(RadzenNumeric<>).MakeGenericType(type);
builder.OpenComponent(0, numericType);
builder.AddAttribute(1, "Value", Filter.FilterValue);
builder.AddAttribute(2, "class", "rz-datafilter-editor");
Action<object> action = args =>
{
Filter.FilterValue = args; InvokeAsync(ApplyFilter);
};
var eventCallbackGenericCreate = typeof(NumericFilterEventCallback).GetMethod("Create").MakeGenericMethod(type);
var eventCallbackGenericAction = typeof(NumericFilterEventCallback).GetMethod("Action").MakeGenericMethod(type);
builder.AddAttribute(3, "Change", eventCallbackGenericCreate.Invoke(this,
new object[] { this, eventCallbackGenericAction.Invoke(this, new object[] { action }) }));
builder.CloseComponent();
});
}
internal class NumericFilterEventCallback
{
public static EventCallback<T> Create<T>(object receiver, Action<T> action)
{
return EventCallback.Factory.Create<T>(receiver, action);
}
public static Action<T> Action<T>(Action<object> action)
{
return args => action(args);
}
}
internal string getFilterDateFormat()
{
if (property != null && !string.IsNullOrEmpty(property.FormatString))
{
var formats = property.FormatString.Split(new char[] { '{', '}' }, StringSplitOptions.RemoveEmptyEntries);
if (formats.Length > 0)
{
var format = formats[0].Trim().Split(':');
if (format.Length > 1)
{
return format[1].Trim();
}
}
}
return DataFilter.FilterDateFormat;
}
}

View File

@@ -0,0 +1,389 @@
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.Common;
using System.Globalization;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading.Tasks;
namespace Radzen.Blazor
{
/// <summary>
/// RadzenDataFilterProperty component.
/// Must be placed inside a <see cref="RadzenDataFilter{TItem}" />
/// </summary>
/// <typeparam name="TItem">The type of the DataFilter item.</typeparam>
public partial class RadzenDataFilterProperty<TItem> : ComponentBase, IDisposable
{
internal event Action<object> FilterValueChange;
/// <summary>
/// Gets or sets the DataFilter.
/// </summary>
/// <value>The DataFilter.</value>
[CascadingParameter]
public RadzenDataFilter<TItem> DataFilter { get; set; }
/// <summary>
/// Gets or sets the format string.
/// </summary>
/// <value>The format string.</value>
[Parameter]
public string FormatString { get; set; }
internal void RemoveColumn(RadzenDataFilterProperty<TItem> property)
{
if (DataFilter.properties.Contains(property))
{
DataFilter.properties.Remove(property);
if (!DataFilter.disposed)
{
try { InvokeAsync(StateHasChanged); } catch { }
}
}
}
/// <summary>
/// Called when initialized.
/// </summary>
protected override void OnInitialized()
{
if (DataFilter != null)
{
DataFilter.AddProperty(this);
var property = GetFilterProperty();
if (!string.IsNullOrEmpty(property) && Type == null)
{
if (!string.IsNullOrEmpty(property))
{
_filterPropertyType = PropertyAccess.GetPropertyType(typeof(TItem), property);
}
}
if (_filterPropertyType == null)
{
_filterPropertyType = Type;
}
else
{
propertyValueGetter = PropertyAccess.Getter<TItem, object>(Property);
}
if (_filterPropertyType == typeof(string))
{
FilterOperator = FilterOperator.Contains;
}
}
}
/// <summary>
/// Gets or sets a value indicating whether this <see cref="RadzenDataGridColumn{TItem}"/> is visible.
/// </summary>
/// <value><c>true</c> if visible; otherwise, <c>false</c>.</value>
[Parameter]
public bool Visible { get; set; } = true;
bool? _visible;
/// <summary>
/// Gets if the property is visible or not.
/// </summary>
/// <returns>System.Boolean.</returns>
public bool GetVisible()
{
return _visible ?? Visible;
}
internal void SetVisible(bool? value)
{
_visible = value;
}
/// <summary>
/// Gets or sets the title.
/// </summary>
/// <value>The title.</value>
[Parameter]
public string Title { get; set; }
/// <summary>
/// Gets or sets the property name.
/// </summary>
/// <value>The property name.</value>
[Parameter]
public string Property { get; set; }
/// <summary>
/// Gets or sets the filter value.
/// </summary>
/// <value>The filter value.</value>
[Parameter]
public object FilterValue { get; set; }
/// <summary>
/// Gets or sets the filter template.
/// </summary>
/// <value>The filter template.</value>
[Parameter]
public RenderFragment<RadzenDataFilterProperty<TItem>> FilterTemplate { get; set; }
/// <summary>
/// Gets or sets the data type.
/// </summary>
/// <value>The data type.</value>
[Parameter]
public Type Type { get; set; }
Func<TItem, object> propertyValueGetter;
internal object GetHeader()
{
if (!string.IsNullOrEmpty(Title))
{
return Title;
}
else
{
return Property;
}
}
/// <summary>
/// Gets the filter property.
/// </summary>
/// <returns>System.String.</returns>
public string GetFilterProperty()
{
return Property;
}
Type _filterPropertyType;
/// <summary>
/// Gets the filter property type.
/// </summary>
public Type FilterPropertyType
{
get
{
return _filterPropertyType;
}
}
object filterValue;
FilterOperator? filterOperator;
LogicalFilterOperator? logicalFilterOperator;
/// <summary>
/// Set parameters as an asynchronous operation.
/// </summary>
/// <param name="parameters">The parameters.</param>
/// <returns>A Task representing the asynchronous operation.</returns>
public override async Task SetParametersAsync(ParameterView parameters)
{
if (parameters.DidParameterChange(nameof(FilterValue), FilterValue))
{
var value = parameters.GetValueOrDefault<object>(nameof(FilterValue));
if (filterValue != value)
{
filterValue = value;
if (FilterTemplate != null)
{
if (FilterValueChange != null)
{
FilterValueChange(filterValue);
}
await DataFilter.Filter();
return;
}
}
}
await base.SetParametersAsync(parameters);
}
/// <summary>
/// Get property filter value.
/// </summary>
public object GetFilterValue()
{
return filterValue ?? FilterValue;
}
/// <summary>
/// Get property filter operator.
/// </summary>
public FilterOperator GetFilterOperator()
{
return filterOperator ?? FilterOperator;
}
/// <summary>
/// Set property filter value.
/// </summary>
public void SetFilterValue(object value)
{
if ((FilterPropertyType == typeof(DateTimeOffset) || FilterPropertyType == typeof(DateTimeOffset?)) && value != null && value is DateTime?)
{
DateTimeOffset? offset = DateTime.SpecifyKind((DateTime)value, DateTimeKind.Utc);
value = offset;
}
filterValue = value;
}
internal bool CanSetFilterValue()
{
return GetFilterOperator() == FilterOperator.IsNull
|| GetFilterOperator() == FilterOperator.IsNotNull
|| GetFilterOperator() == FilterOperator.IsEmpty
|| GetFilterOperator() == FilterOperator.IsNotEmpty;
}
/// <summary>
/// Sets to default property filter values and operators.
/// </summary>
public void ClearFilters()
{
SetFilterValue(null);
SetFilterOperator(null);
FilterValue = null;
var defaultOperator = typeof(System.Collections.IEnumerable).IsAssignableFrom(FilterPropertyType) ? FilterOperator.Contains : default(FilterOperator);
FilterOperator = GetFilterOperators().Contains(defaultOperator) ? defaultOperator : GetFilterOperators().FirstOrDefault();
}
/// <summary>
/// Gets or sets the filter operator.
/// </summary>
/// <value>The filter operator.</value>
[Parameter]
public FilterOperator FilterOperator { get; set; }
/// <summary>
/// Set property filter operator.
/// </summary>
public void SetFilterOperator(FilterOperator? value)
{
if (value == FilterOperator.IsEmpty || value == FilterOperator.IsNotEmpty || value == FilterOperator.IsNull || value == FilterOperator.IsNotNull)
{
filterValue = value == FilterOperator.IsEmpty || value == FilterOperator.IsNotEmpty ? string.Empty : null;
}
filterOperator = value;
}
/// <summary>
/// Get possible property filter operators.
/// </summary>
public virtual IEnumerable<FilterOperator> GetFilterOperators()
{
if (PropertyAccess.IsEnum(FilterPropertyType))
return new FilterOperator[] { FilterOperator.Equals, FilterOperator.NotEquals };
if (PropertyAccess.IsNullableEnum(FilterPropertyType))
return new FilterOperator[] { FilterOperator.Equals, FilterOperator.NotEquals, FilterOperator.IsNull, FilterOperator.IsNotNull };
return Enum.GetValues(typeof(FilterOperator)).Cast<FilterOperator>().Where(o => {
var isStringOperator = o == FilterOperator.Contains || o == FilterOperator.DoesNotContain
|| o == FilterOperator.StartsWith || o == FilterOperator.EndsWith || o == FilterOperator.IsEmpty || o == FilterOperator.IsNotEmpty;
return FilterPropertyType == typeof(string) || typeof(IEnumerable).IsAssignableFrom(FilterPropertyType) || typeof(IEnumerable<>).IsAssignableFrom(FilterPropertyType) ? isStringOperator
|| o == FilterOperator.Equals || o == FilterOperator.NotEquals
|| o == FilterOperator.IsNull || o == FilterOperator.IsNotNull
: !isStringOperator;
});
}
internal string GetFilterOperatorText(FilterOperator filterOperator)
{
switch (filterOperator)
{
case FilterOperator.Contains:
return DataFilter?.ContainsText;
case FilterOperator.DoesNotContain:
return DataFilter?.DoesNotContainText;
case FilterOperator.EndsWith:
return DataFilter?.EndsWithText;
case FilterOperator.Equals:
return DataFilter?.EqualsText;
case FilterOperator.GreaterThan:
return DataFilter?.GreaterThanText;
case FilterOperator.GreaterThanOrEquals:
return DataFilter?.GreaterThanOrEqualsText;
case FilterOperator.LessThan:
return DataFilter?.LessThanText;
case FilterOperator.LessThanOrEquals:
return DataFilter?.LessThanOrEqualsText;
case FilterOperator.StartsWith:
return DataFilter?.StartsWithText;
case FilterOperator.NotEquals:
return DataFilter?.NotEqualsText;
case FilterOperator.IsNull:
return DataFilter?.IsNullText;
case FilterOperator.IsEmpty:
return DataFilter?.IsEmptyText;
case FilterOperator.IsNotNull:
return DataFilter?.IsNotNullText;
case FilterOperator.IsNotEmpty:
return DataFilter?.IsNotEmptyText;
default:
return $"{filterOperator}";
}
}
internal string GetFilterOperatorSymbol(FilterOperator filterOperator)
{
var symbol = DataFilter.FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ? "a" : "A";
switch (filterOperator)
{
case FilterOperator.Contains:
return $"*{symbol}*";
case FilterOperator.DoesNotContain:
return $"*{symbol}*";
case FilterOperator.StartsWith:
return $"{symbol}**";
case FilterOperator.EndsWith:
return $"**{symbol}";
case FilterOperator.Equals:
return "=";
case FilterOperator.GreaterThan:
return ">";
case FilterOperator.GreaterThanOrEquals:
return "≥";
case FilterOperator.LessThan:
return "<";
case FilterOperator.LessThanOrEquals:
return "≤";
case FilterOperator.NotEquals:
return "≠";
case FilterOperator.IsNull:
return "∅";
case FilterOperator.IsNotNull:
return "!∅";
case FilterOperator.IsEmpty:
return "= ''";
case FilterOperator.IsNotEmpty:
return "≠ ''";
default:
return $"{filterOperator}";
}
}
/// <summary>
/// Disposes this instance.
/// </summary>
public void Dispose()
{
DataFilter?.RemoveProperty(this);
}
}
}

View File

@@ -29,7 +29,7 @@
{
<div class="rz-group-header-item">
<span class="rz-group-header-item-title">@gd.GetTitle()</span>
<a href="javascript:void(0)" @onclick=@(args => RemoveGroup(gd)) role="button" class="rz-dialog-titlebar-icon rz-dialog-titlebar-close">
<a href="javascript:void(0)" @onclick=@(async args => await RemoveGroupAsync(gd)) role="button" class="rz-dialog-titlebar-icon rz-dialog-titlebar-close">
<span class="rzi rzi-times"></span>
</a>
</div>
@@ -45,7 +45,7 @@
@if(AllowColumnPicking)
{
<div class="rz-column-picker">
<RadzenDropDown SelectAllText="@AllColumnsText"
<RadzenDropDown SelectAllText="@AllColumnsText" AllowSelectAll="@AllowPickAllColumns"
MaxSelectedLabels="2"
SelectedItemsText="@ColumnsShowingText" Change=@ToggleColumns
@bind-Value="@selectedColumns"
@@ -60,11 +60,11 @@
@if (AllowPaging && (PagerPosition == PagerPosition.Top || PagerPosition == PagerPosition.TopAndBottom))
{
<RadzenPager HorizontalAlign="@PagerHorizontalAlign" AlwaysVisible="@PagerAlwaysVisible" @ref="topPager" Count="@Count" PageSize="@PageSize" PageNumbersCount="@PageNumbersCount" PageChanged="@OnPageChanged" PageSizeChanged="@OnPageSizeChanged" PageSizeOptions="@PageSizeOptions" ShowPagingSummary="@ShowPagingSummary" PagingSummaryFormat="@PagingSummaryFormat" PageSizeText="@PageSizeText" />
<RadzenPager HorizontalAlign="@PagerHorizontalAlign" AlwaysVisible="@PagerAlwaysVisible" @ref="topPager" Count="@Count" PageSize="@PageSize" PageNumbersCount="@PageNumbersCount" PageChanged="@ChangePage" PageSizeChanged="@OnPageSizeChanged" PageSizeOptions="@PageSizeOptions" ShowPagingSummary="@ShowPagingSummary" PagingSummaryFormat="@PagingSummaryFormat" PageSizeText="@PageSizeText" />
}
<div class="rz-data-grid-data">
<table class="rz-grid-table rz-grid-table-fixed">
<table class="rz-grid-table rz-grid-table-fixed @(AllowAlternatingRows ? "rz-grid-table-striped" : "") @(allColumns.Any(c => c.Parent != null) ? "rz-grid-table-composite" : "")">
<colgroup>
@foreach(var g in Groups)
{
@@ -112,7 +112,7 @@
var columnIndex = visibleColumns.IndexOf(column);
var sortableClass = AllowSorting && column.Sortable ? "rz-sortable-column" : "";
<RadzenDataGridHeaderCell RowIndex="@i" Grid="@this" Column="@column" ColumnIndex="@columnIndex" CssClass="@($"rz-unselectable-text {sortableClass} {column.HeaderCssClass} {getFrozenColumnClass(column, visibleColumns)} {(column.Columns != null || column.Parent != null ? "rz-composite-cell" : "")}".Trim())" Attributes="@(cellAttr)" />
<RadzenDataGridHeaderCell RowIndex="@i" Grid="@this" Column="@column" ColumnIndex="@columnIndex" CssClass="@($"rz-unselectable-text {sortableClass} {column.HeaderCssClass} {getFrozenColumnClass(column, visibleColumns)} {(column.Columns != null || column.Parent != null ? "rz-composite-cell" : "")} {getColumnAlignClass(column)}".Trim())" Attributes="@(cellAttr)" />
}
</tr>
}
@@ -133,7 +133,7 @@
}
@foreach (var column in visibleColumns)
{
<th colspan="@column.GetColSpan()" class="@($" rz-unselectable-text")" scope="col" style="@column.GetStyle(true, true)">
<th colspan="@column.GetColSpan()" class="@($"rz-unselectable-text {getFrozenColumnClass(column, visibleColumns)}")" scope="col" style="@column.GetStyle(true, true)">
@if (AllowFiltering && column.Filterable && column.Columns == null && (!string.IsNullOrEmpty(column.GetFilterProperty()) || column.FilterTemplate != null))
{
<div class="rz-cell-filter">
@@ -149,7 +149,7 @@
{
if (FilterMode == FilterMode.Simple)
{
<button class="rz-button rz-button-md rz-button-icon-only btn-light" onclick="@($"Radzen.togglePopup(this.parentNode, '{PopupID}{column.GetFilterProperty()}')")">
<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>
var filterValue = column.GetFilterValue();
@@ -167,43 +167,73 @@
<div class="rz-listbox rz-inputtext ">
<div class="rz-listbox-list-wrapper">
<ul class="rz-listbox-list">
<li class="@(DateFilterOperatorStyle(column, FilterOperator.Equals))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.Equals))" style="display: block;">
<span>@EqualsText</span>
</li>
<li class="@(DateFilterOperatorStyle(column, FilterOperator.NotEquals))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.NotEquals))" style="display: block;">
<span>@NotEqualsText</span>
</li>
<li class="@(DateFilterOperatorStyle(column, FilterOperator.LessThan))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.LessThan))" style="display: block;">
<span>@LessThanText</span>
</li>
<li class="@(DateFilterOperatorStyle(column, FilterOperator.LessThanOrEquals))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.LessThanOrEquals))" style="display: block;">
<span>@LessThanOrEqualsText</span>
</li>
<li class="@(DateFilterOperatorStyle(column, FilterOperator.GreaterThan))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.GreaterThan))" style="display: block;">
<span>@GreaterThanText</span>
</li>
<li class="@(DateFilterOperatorStyle(column, FilterOperator.GreaterThanOrEquals))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.GreaterThanOrEquals))" style="display: block;">
<span>@GreaterThanOrEqualsText</span>
</li>
<li class="@(DateFilterOperatorStyle(column, FilterOperator.IsNull))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.IsNull))" style="display: block;">
<span>@IsNullText</span>
</li>
<li class="@(DateFilterOperatorStyle(column, FilterOperator.IsEmpty))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.IsEmpty))" style="display: block;">
<span>@IsEmptyText</span>
</li>
<li class="@(DateFilterOperatorStyle(column, FilterOperator.IsNotEmpty))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.IsNotEmpty))" style="display: block;">
<span>@IsNotEmptyText</span>
</li>
<li class="@(DateFilterOperatorStyle(column, FilterOperator.IsNotNull))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.IsNotNull))" style="display: block;">
<span>@IsNotNullText</span>
</li>
@if (column.GetFilterOperators().Contains(FilterOperator.Equals))
{
<li class="@(DateFilterOperatorStyle(column, FilterOperator.Equals))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.Equals))" style="display: block;">
<span>@EqualsText</span>
</li>
}
@if (column.GetFilterOperators().Contains(FilterOperator.NotEquals))
{
<li class="@(DateFilterOperatorStyle(column, FilterOperator.NotEquals))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.NotEquals))" style="display: block;">
<span>@NotEqualsText</span>
</li>
}
@if (column.GetFilterOperators().Contains(FilterOperator.LessThan))
{
<li class="@(DateFilterOperatorStyle(column, FilterOperator.LessThan))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.LessThan))" style="display: block;">
<span>@LessThanText</span>
</li>
}
@if (column.GetFilterOperators().Contains(FilterOperator.LessThanOrEquals))
{
<li class="@(DateFilterOperatorStyle(column, FilterOperator.LessThanOrEquals))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.LessThanOrEquals))" style="display: block;">
<span>@LessThanOrEqualsText</span>
</li>
}
@if (column.GetFilterOperators().Contains(FilterOperator.GreaterThan))
{
<li class="@(DateFilterOperatorStyle(column, FilterOperator.GreaterThan))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.GreaterThan))" style="display: block;">
<span>@GreaterThanText</span>
</li>
}
@if (column.GetFilterOperators().Contains(FilterOperator.GreaterThanOrEquals))
{
<li class="@(DateFilterOperatorStyle(column, FilterOperator.GreaterThanOrEquals))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.GreaterThanOrEquals))" style="display: block;">
<span>@GreaterThanOrEqualsText</span>
</li>
}
@if (column.GetFilterOperators().Contains(FilterOperator.IsEmpty))
{
<li class="@(DateFilterOperatorStyle(column, FilterOperator.IsEmpty))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.IsEmpty))" style="display: block;">
<span>@IsEmptyText</span>
</li>
}
@if (column.GetFilterOperators().Contains(FilterOperator.IsNotEmpty))
{
<li class="@(DateFilterOperatorStyle(column, FilterOperator.IsNotEmpty))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.IsNotEmpty))" style="display: block;">
<span>@IsNotEmptyText</span>
</li>
}
@if (column.GetFilterOperators().Contains(FilterOperator.IsNull))
{
<li class="@(DateFilterOperatorStyle(column, FilterOperator.IsNull))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.IsNull))" style="display: block;">
<span>@IsNullText</span>
</li>
}
@if (column.GetFilterOperators().Contains(FilterOperator.IsNotNull))
{
<li class="@(DateFilterOperatorStyle(column, FilterOperator.IsNotNull))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.IsNotNull))" style="display: block;">
<span>@IsNotNullText</span>
</li>
}
</ul>
</div>
</div>
<RadzenDatePicker TValue="@object"
ShowTime="true" ShowTimeOkButton="false" Inline="true" DateFormat="@getFilterDateFormat(column)"
Value="@column.GetFilterValue()" Change="@(args => column.SetFilterValue(args.Value))" />
ShowTime="@column.ShowTimeForDateTimeFilter()" ShowTimeOkButton="false" Inline="true" DateFormat="@getFilterDateFormat(column)"
Value="@column.GetFilterValue()" Change="@(args => { column.SetFilterValue(args.Value); SaveSettings(); })" />
</div>
<div class="rz-date-filter-buttons">
@@ -230,8 +260,8 @@
{
<RadzenDropDown Style="width:100%" AllowClear="true" AllowFiltering="false" TValue="@object"
Value=@column.GetFilterValue() Multiple="false" Placeholder="@EnumFilterSelectText" TextProperty="Text" ValueProperty="Value"
Data=@EnumExtensions.EnumAsKeyValuePair(Nullable.GetUnderlyingType(column.FilterPropertyType) ?? column.FilterPropertyType)
Change="@(args => {column.SetFilterValue(args);ApplyFilter(column, true);})" />
Data=@((PropertyAccess.IsNullableEnum(column.FilterPropertyType) ? new object[]{ new { Value = -1, Text = "<null>"}} : 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);ApplyFilter(column, true);})" />
}
else if (PropertyAccess.IsNumeric(column.FilterPropertyType))
{
@@ -254,6 +284,10 @@
<RadzenDataGridFilterMenu Grid="@this" Column="@column" />
}
<input disabled=@column.CanSetFilterValue() id="@(getFilterInputId(column))" @onchange="@((args) => OnFilter(args, column))" @onkeydown="@((args) => OnFilterKeyPress(args, column))" value="@column.GetFilterValue()" type="text" 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>
}
}
</label>
}
@@ -344,7 +378,7 @@
@if (AllowPaging && (PagerPosition == PagerPosition.Bottom || PagerPosition == PagerPosition.TopAndBottom))
{
<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" />
<RadzenPager HorizontalAlign="@PagerHorizontalAlign" AlwaysVisible="@PagerAlwaysVisible" @ref="bottomPager" Count="@Count" PageSize="@PageSize" PageNumbersCount="@PageNumbersCount" PageChanged="@ChangePage" PageSizeChanged="@OnPageSizeChanged" PageSizeOptions="@PageSizeOptions" ShowPagingSummary="@ShowPagingSummary" PagingSummaryFormat="@PagingSummaryFormat" PageSizeText="@PageSizeText" />
}
</div>
}

View File

@@ -6,8 +6,10 @@ using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Data.Common;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Text.Json;
using System.Threading.Tasks;
namespace Radzen.Blazor
@@ -196,6 +198,13 @@ namespace Radzen.Blazor
}
}
/// <summary>
/// Gets or sets the load child data callback.
/// </summary>
/// <value>The load child data callback.</value>
[Parameter]
public EventCallback<Radzen.DataGridLoadChildDataEventArgs<TItem>> LoadChildData { get; set; }
/// <summary>
/// Gets or sets a value indicating whether DataGrid data cells will follow the header cells structure in composite columns.
/// </summary>
@@ -214,6 +223,12 @@ namespace Radzen.Blazor
[Parameter]
public bool Responsive { get; set; }
/// <summary>
/// Gets or sets a value indicating DataGrid density.
/// </summary>
[Parameter]
public Density Density { get; set; }
/// <summary>
/// The grouped and paged View
/// </summary>
@@ -237,7 +252,7 @@ namespace Radzen.Blazor
}
}
internal void RemoveGroup(GroupDescriptor gd)
internal async Task RemoveGroupAsync(GroupDescriptor gd)
{
Groups.Remove(gd);
_groupedPagedView = null;
@@ -245,7 +260,11 @@ namespace Radzen.Blazor
var column = columns.Where(c => c.GetGroupProperty() == gd.Property).FirstOrDefault();
if (column != null)
{
Group.InvokeAsync(new DataGridColumnGroupEventArgs<TItem>() { Column = column, GroupDescriptor = null });
await Group.InvokeAsync(new DataGridColumnGroupEventArgs<TItem>() { Column = column, GroupDescriptor = null });
}
if (IsVirtualizationAllowed())
{
await InvokeAsync(Reload);
}
}
@@ -261,6 +280,11 @@ namespace Radzen.Blazor
return column.IsFrozen() ? "rz-frozen-cell" : "";
}
internal string getColumnAlignClass(RadzenDataGridColumn<TItem> column)
{
return $"rz-text-align-{column.TextAlign.ToString().ToLower()}";
}
/// <summary>
/// The filter operator style for dates.
/// </summary>
@@ -301,6 +325,7 @@ namespace Radzen.Blazor
protected void ApplyDateFilterByFilterOperator(RadzenDataGridColumn<TItem> column, FilterOperator filterOperator)
{
column.SetFilterOperator(filterOperator);
SaveSettings();
}
internal IJSRuntime GetJSRuntime()
@@ -386,7 +411,7 @@ namespace Radzen.Blazor
if (selectedColumns == null)
return;
var columnsList = (IList<RadzenDataGridColumn<TItem>>)selectedColumns;
var columnsList = ((IEnumerable<object>)selectedColumns).ToList();
if (visible)
{
if (!columnsList.Contains(column))
@@ -440,6 +465,7 @@ namespace Radzen.Blazor
}
PickedColumnsChanged.InvokeAsync(new DataGridPickedColumnsChangedEventArgs<TItem>() { Columns = selected });
SaveSettings();
}
/// <summary>
@@ -493,7 +519,7 @@ namespace Radzen.Blazor
}
else
{
action = args => column.SetFilterValue(args, isFirst);
action = args => { column.SetFilterValue(args, isFirst); SaveSettings(); };
}
var eventCallbackGenericCreate = typeof(NumericFilterEventCallback).GetMethod("Create").MakeGenericMethod(type);
@@ -522,6 +548,7 @@ namespace Radzen.Blazor
}
column.SetFilterValue(filterValue, isFirst);
SaveSettings();
}));
}
else if (FilterMode == FilterMode.SimpleWithMenu)
@@ -561,6 +588,8 @@ namespace Radzen.Blazor
LogicalFilterOperator = column.GetLogicalFilterOperator()
});
SaveSettings();
if (LoadData.HasDelegate && IsVirtualizationAllowed())
{
Data = null;
@@ -610,6 +639,7 @@ namespace Radzen.Blazor
SetColumnSortOrder(column);
Sort.InvokeAsync(new DataGridColumnSortEventArgs<TItem>() { Column = column, SortOrder = column.GetSortOrder() });
SaveSettings();
if (LoadData.HasDelegate && IsVirtualizationAllowed())
{
@@ -647,6 +677,8 @@ namespace Radzen.Blazor
skip = 0;
CurrentPage = 0;
SaveSettings();
await FilterCleared.InvokeAsync(new DataGridColumnFilterEventArgs<TItem>()
{
Column = column,
@@ -1048,6 +1080,13 @@ namespace Radzen.Blazor
[Parameter]
public string ColumnsText { get; set; } = "Columns";
/// <summary>
/// Gets or sets a value indicating whether user can pick all columns in column picker.
/// </summary>
/// <value><c>true</c> if pick of all columns is allowed; otherwise, <c>false</c>.</value>
[Parameter]
public bool AllowPickAllColumns { get; set; } = true;
/// <summary>
/// Gets or sets a value indicating whether grouping is allowed.
/// </summary>
@@ -1128,6 +1167,8 @@ namespace Radzen.Blazor
NewIndex = actualColumnIndexTo
});
SaveSettings();
StateHasChanged();
}
@@ -1150,6 +1191,7 @@ namespace Radzen.Blazor
Column = column,
Width = value,
});
SaveSettings();
}
internal string GetOrderBy()
@@ -1184,22 +1226,80 @@ namespace Radzen.Blazor
return base.View;
}
var view = base.View.Where<TItem>(allColumns);
IQueryable<TItem> view;
var orderBy = GetOrderBy();
if (!string.IsNullOrEmpty(orderBy))
if (childData.Any())
{
if (typeof(TItem) == typeof(object))
view = base.View;//.Where<TItem>(allColumns);
if (!string.IsNullOrEmpty(orderBy))
{
var firstItem = view.FirstOrDefault();
if (firstItem != null)
if (typeof(TItem) == typeof(object))
{
view = view.Cast(firstItem.GetType()).AsQueryable().OrderBy(orderBy).Cast<TItem>();
var firstItem = view.FirstOrDefault();
if (firstItem != null)
{
view = view.Cast(firstItem.GetType()).AsQueryable().OrderBy(orderBy).Cast<TItem>();
}
}
else
{
view = view.OrderBy(orderBy);
}
}
else
var viewList = view.ToList();
var countWithChildren = viewList.Count + childData.SelectMany(d => d.Value.Data).Count();
for (int i = 0; i < countWithChildren; i++)
{
view = view.OrderBy(orderBy);
var item = viewList.ElementAtOrDefault(i);
if (item != null && childData.ContainsKey(item))
{
var level = 1;
var parentChildData = childData[item].ParentChildData;
while (parentChildData != null)
{
parentChildData = parentChildData.ParentChildData;
level++;
}
childData[item].Level = level;
var cd = childData[item].Data.AsQueryable();
if (!string.IsNullOrEmpty(orderBy))
{
cd = cd.OrderBy(orderBy);
}
viewList.InsertRange(viewList.IndexOf(item) + 1, cd);
}
}
view = viewList.AsQueryable()
.Where(i => childData.ContainsKey(i) && childData[i].Data.AsQueryable().Where<TItem>(allColumns).Any()
|| viewList.AsQueryable().Where<TItem>(allColumns).Contains(i));
}
else
{
view = base.View.Where<TItem>(allColumns);
if (!string.IsNullOrEmpty(orderBy))
{
if (typeof(TItem) == typeof(object))
{
var firstItem = view.FirstOrDefault();
if (firstItem != null)
{
view = view.Cast(firstItem.GetType()).AsQueryable().OrderBy(orderBy).Cast<TItem>();
}
}
else
{
view = view.OrderBy(orderBy);
}
}
}
@@ -1221,6 +1321,8 @@ namespace Radzen.Blazor
CurrentPage = 0;
}
CalculatePager();
StateHasChanged();
}
}
@@ -1292,6 +1394,20 @@ namespace Radzen.Blazor
[Parameter]
public EventCallback<DataGridRowMouseEventArgs<TItem>> RowDoubleClick { get; set; }
/// <summary>
/// Gets or sets the cell click callback.
/// </summary>
/// <value>The cell click callback.</value>
[Parameter]
public EventCallback<DataGridCellMouseEventArgs<TItem>> CellClick { get; set; }
/// <summary>
/// Gets or sets the cell double click callback.
/// </summary>
/// <value>The cell double click callback.</value>
[Parameter]
public EventCallback<DataGridCellMouseEventArgs<TItem>> CellDoubleClick { get; set; }
/// <summary>
/// Gets or sets the row click callback.
/// </summary>
@@ -1375,6 +1491,13 @@ namespace Radzen.Blazor
protected override void OnDataChanged()
{
Reset(!IsOData() && !LoadData.HasDelegate);
if (!IsOData() && !LoadData.HasDelegate && !Page.HasDelegate)
{
skip = 0;
CurrentPage = 0;
CalculatePager();
}
}
/// <summary>
@@ -1392,12 +1515,18 @@ namespace Radzen.Blazor
{
selectedItems.Clear();
expandedItems.Clear();
collapsedGroupItems.Clear();
}
if (resetColumnState)
{
allColumns.ToList().ForEach(c => c.ClearFilters());
allColumns.ToList().ForEach(c => { c.ResetSortOrder(); });
allColumns.ToList().ForEach(c =>
{
c.ClearFilters();
c.ResetSortOrder();
c.SetOrderIndex(null);
c.SetWidth(null);
});
sorts.Clear();
}
}
@@ -1451,6 +1580,7 @@ namespace Radzen.Blazor
if(virtualize != null)
{
await virtualize.RefreshDataAsync();
await virtualize.RefreshDataAsync();
}
if(groupVirtualize != null)
@@ -1560,22 +1690,21 @@ namespace Radzen.Blazor
internal string ExpandedItemStyle(TItem item)
{
return expandedItems.Keys.Contains(item) ? "rz-row-toggler rzi-grid-sort rzi-chevron-circle-down" : "rz-row-toggler rzi-grid-sort rzi-chevron-circle-right";
return expandedItems.Keys.Contains(item) ? "rz-row-toggler rzi-chevron-circle-down" : "rz-row-toggler rzi-chevron-circle-right";
}
internal Dictionary<TItem, bool> selectedItems = new Dictionary<TItem, bool>();
internal string RowStyle(TItem item, int index)
{
var evenOrOdd = index % 2 == 0 ? "rz-datatable-even" : "rz-datatable-odd";
var isInEditMode = IsRowInEditMode(item) ? "rz-datatable-edit" : "";
return (RowSelect.HasDelegate || ValueChanged.HasDelegate || SelectionMode == DataGridSelectionMode.Multiple) && selectedItems.Keys.Contains(item) ? $"rz-state-highlight {evenOrOdd} {isInEditMode} " : $"{evenOrOdd} {isInEditMode} ";
return (RowSelect.HasDelegate || ValueChanged.HasDelegate || SelectionMode == DataGridSelectionMode.Multiple) && selectedItems.Keys.Contains(item) ? $"rz-state-highlight rz-data-row {isInEditMode} " : $"rz-data-row {isInEditMode} ";
}
internal Tuple<Radzen.RowRenderEventArgs<TItem>, IReadOnlyDictionary<string, object>> RowAttributes(TItem item)
{
var args = new Radzen.RowRenderEventArgs<TItem>() { Data = item, Expandable = Template != null };
var args = new Radzen.RowRenderEventArgs<TItem>() { Data = item, Expandable = Template != null || LoadChildData.HasDelegate };
if (RowRender != null)
{
@@ -1653,6 +1782,11 @@ namespace Radzen.Blazor
if (Visible)
{
if (settings != null)
{
await LoadSettings(settings);
}
var args = new Radzen.DataGridRenderEventArgs<TItem>() { Grid = this, FirstRender = firstRender };
if (Render != null)
@@ -1680,7 +1814,7 @@ namespace Radzen.Blazor
internal async System.Threading.Tasks.Task ExpandItem(TItem item)
{
if (ExpandMode == DataGridExpandMode.Single && expandedItems.Keys.Any())
if (ExpandMode == DataGridExpandMode.Single && expandedItems.Keys.Any() && !LoadChildData.HasDelegate)
{
var itemToCollapse = expandedItems.Keys.FirstOrDefault();
if (itemToCollapse != null)
@@ -1700,16 +1834,33 @@ namespace Radzen.Blazor
{
expandedItems.Add(item, true);
await RowExpand.InvokeAsync(item);
var args = new DataGridLoadChildDataEventArgs<TItem>() { Item = item };
await LoadChildData.InvokeAsync(args);
if (args.Data != null && !childData.ContainsKey(item))
{
childData.Add(item, new DataGridChildData<TItem>() { Data = args.Data, ParentChildData = childData.Where(c => c.Value.Data.Contains(item)).Select(c => c.Value).FirstOrDefault() });
_view = null;
}
}
else
{
expandedItems.Remove(item);
await RowCollapse.InvokeAsync(item);
if (childData.ContainsKey(item))
{
childData.Remove(item);
_view = null;
}
}
await InvokeAsync(StateHasChanged);
}
internal Dictionary<TItem, DataGridChildData<TItem>> childData = new Dictionary<TItem, DataGridChildData<TItem>>();
/// <summary>
/// Gets or sets a value indicating whether DataGrid row can be selected on row click.
/// </summary>
@@ -1717,6 +1868,13 @@ namespace Radzen.Blazor
[Parameter]
public bool AllowRowSelectOnRowClick { get; set; } = true;
/// <summary>
/// Gets or sets a value indicating whether DataGrid should use alternating row styles.
/// </summary>
/// <value><c>true</c> if DataGrid is using alternating row styles; otherwise, <c>false</c>.</value>
[Parameter]
public bool AllowAlternatingRows { get; set; } = true;
/// <summary>
/// Gets or sets the selection mode.
/// </summary>
@@ -1729,6 +1887,16 @@ namespace Radzen.Blazor
await CellContextMenu.InvokeAsync(args);
}
internal async Task OnCellClick(DataGridCellMouseEventArgs<TItem> args)
{
await CellClick.InvokeAsync(args);
}
internal async Task OnCellDblClick(DataGridCellMouseEventArgs<TItem> args)
{
await CellDoubleClick.InvokeAsync(args);
}
internal async Task OnRowClick(DataGridRowMouseEventArgs<TItem> args)
{
await RowClick.InvokeAsync(args);
@@ -2014,7 +2182,7 @@ namespace Radzen.Blazor
{
foreach (var c in allColumns.ToList().Where(c => c != column))
{
c.SetSortOrder(null);
c.SetSortOrderInternal(null);
}
sorts.Clear();
}
@@ -2027,17 +2195,17 @@ namespace Radzen.Blazor
if (column.GetSortOrder() == null)
{
column.SetSortOrder(SortOrder.Ascending);
column.SetSortOrderInternal(SortOrder.Ascending);
descriptor.SortOrder = SortOrder.Ascending;
}
else if (column.GetSortOrder() == SortOrder.Ascending)
{
column.SetSortOrder(SortOrder.Descending);
column.SetSortOrderInternal(SortOrder.Descending);
descriptor.SortOrder = SortOrder.Descending;
}
else if (column.GetSortOrder() == SortOrder.Descending)
{
column.SetSortOrder(null);
column.SetSortOrderInternal(null);
if (sorts.Where(d => d.Property == column?.GetSortProperty()).Any())
{
sorts.Remove(descriptor);
@@ -2051,6 +2219,48 @@ namespace Radzen.Blazor
}
}
void GroupsCollectionChanged(object sender, NotifyCollectionChangedEventArgs args)
{
if (args.Action == NotifyCollectionChangedAction.Add)
{
var column = columns.Where(c => c.GetGroupProperty() == ((GroupDescriptor)args.NewItems[0]).Property).FirstOrDefault();
if (HideGroupedColumn)
{
column.SetVisible(false);
if (!groupedColumns.Contains(column))
{
groupedColumns.Add(column);
}
}
}
else if (args.Action == NotifyCollectionChangedAction.Remove)
{
var column = columns.Where(c => c.GetGroupProperty() == ((GroupDescriptor)args.OldItems[0]).Property).FirstOrDefault();
if (HideGroupedColumn)
{
column.SetVisible(true);
if (groupedColumns.Contains(column))
{
groupedColumns.Remove(column);
}
}
}
else if (args.Action == NotifyCollectionChangedAction.Reset)
{
foreach (var column in groupedColumns)
{
if (HideGroupedColumn)
{
column.SetVisible(true);
}
}
}
SaveSettings();
}
List<RadzenDataGridColumn<TItem>> groupedColumns = new List<RadzenDataGridColumn<TItem>>();
/// <summary>
/// Gets or sets the group descriptors.
@@ -2063,45 +2273,8 @@ namespace Radzen.Blazor
if (groups == null)
{
groups = new ObservableCollection<GroupDescriptor>();
groups.CollectionChanged += (object sender, NotifyCollectionChangedEventArgs args) =>
{
if (args.Action == NotifyCollectionChangedAction.Add)
{
var column = columns.Where(c => c.GetGroupProperty() == ((GroupDescriptor)args.NewItems[0]).Property).FirstOrDefault();
if (HideGroupedColumn)
{
column.SetVisible(false);
if (!groupedColumns.Contains(column))
{
groupedColumns.Add(column);
}
}
}
else if (args.Action == NotifyCollectionChangedAction.Remove)
{
var column = columns.Where(c => c.GetGroupProperty() == ((GroupDescriptor)args.OldItems[0]).Property).FirstOrDefault();
if (HideGroupedColumn)
{
column.SetVisible(true);
if (groupedColumns.Contains(column))
{
groupedColumns.Remove(column);
}
}
}
else if (args.Action == NotifyCollectionChangedAction.Reset)
{
foreach (var column in groupedColumns)
{
if (HideGroupedColumn)
{
column.SetVisible(true);
}
}
}
};
groups.CollectionChanged -= GroupsCollectionChanged;
groups.CollectionChanged += GroupsCollectionChanged;
}
return groups;
@@ -2156,6 +2329,7 @@ namespace Radzen.Blazor
{
SetColumnSortOrder(column);
Sort.InvokeAsync(new DataGridColumnSortEventArgs<TItem>() { Column = column, SortOrder = column.GetSortOrder() });
SaveSettings();
}
if (LoadData.HasDelegate && IsVirtualizationAllowed())
@@ -2178,10 +2352,11 @@ namespace Radzen.Blazor
if (column != null)
{
column.SetSortOrder(SortOrder.Ascending);
column.SetSortOrderInternal(SortOrder.Ascending);
SetColumnSortOrder(column);
Sort.InvokeAsync(new DataGridColumnSortEventArgs<TItem>() { Column = column, SortOrder = column.GetSortOrder() });
SaveSettings();
}
if (LoadData.HasDelegate && IsVirtualizationAllowed())
@@ -2212,6 +2387,11 @@ namespace Radzen.Blazor
additionalClasses.Add("rz-datatable-reflow");
}
if (Density == Density.Compact)
{
additionalClasses.Add("rz-density-compact");
}
return $"rz-has-paginator rz-datatable rz-datatable-scrollable {String.Join(" ", additionalClasses)}";
}
@@ -2240,6 +2420,11 @@ namespace Radzen.Blazor
{
base.Dispose();
if (groups != null)
{
groups.CollectionChanged -= GroupsCollectionChanged;
}
if (IsJSRuntimeAvailable)
{
foreach (var column in allColumns.ToList().Where(c => c.GetVisible()))
@@ -2250,5 +2435,265 @@ namespace Radzen.Blazor
}
internal int deepestChildColumnLevel;
/// <inheritdoc />
protected override async Task OnPageSizeChanged(int value)
{
pageSize = value;
SaveSettings();
await PageSizeChanged.InvokeAsync(value);
await base.OnPageSizeChanged(value);
}
/// <summary>
/// Gets or sets the page size changed callback.
/// </summary>
/// <value>The page size changed callback.</value>
[Parameter]
public EventCallback<int> PageSizeChanged { get; set; }
/// <summary>
/// Gets DataGrid settings as JSON string.
/// </summary>
internal void SaveSettings()
{
if (SettingsChanged.HasDelegate && canSaveSettings)
{
settings = new DataGridSettings()
{
Columns = ColumnsCollection.ToList().Select(c => new DataGridColumnSettings()
{
Property = c.Property,
Width = c.GetWidth(),
Visible = c.GetVisible(),
OrderIndex = c.GetOrderIndex(),
SortOrder = c.GetSortOrder(),
FilterValue = c.GetFilterValue(),
FilterOperator = c.GetFilterOperator(),
SecondFilterValue = c.GetSecondFilterValue(),
SecondFilterOperator = c.GetSecondFilterOperator(),
}).ToList(),
CurrentPage = CurrentPage,
PageSize = PageSize,
Groups = Groups
};
SettingsChanged.InvokeAsync(settings);
}
}
/// <summary>
/// Load DataGrid settings saved from GetSettings() method.
/// </summary>
internal async Task LoadSettings(DataGridSettings settings)
{
if (SettingsChanged.HasDelegate)
{
var shouldUpdateState = false;
if (settings.Columns != null)
{
foreach (var column in settings.Columns)
{
var gridColumn = ColumnsCollection.Where(c => c.Property == column.Property).FirstOrDefault();
if (gridColumn != null)
{
// Visibility
if (gridColumn.GetVisible() != column.Visible)
{
gridColumn.SetVisible(column.Visible);
shouldUpdateState = true;
}
// Width
if (gridColumn.GetWidth() != column.Width)
{
gridColumn.SetWidth(column.Width);
shouldUpdateState = true;
}
// OrderIndex
if (gridColumn.GetOrderIndex() != column.OrderIndex)
{
gridColumn.SetOrderIndex(column.OrderIndex);
shouldUpdateState = true;
}
// Sorting
if (gridColumn.GetSortOrder() != column.SortOrder)
{
gridColumn.SetSortOrder(column.SortOrder);
shouldUpdateState = true;
}
// Filtering
if (!object.Equals(gridColumn.GetFilterValue(), GetFilterValue(column.FilterValue, gridColumn.FilterPropertyType)))
{
gridColumn.SetFilterValue(GetFilterValue(column.FilterValue, gridColumn.FilterPropertyType));
shouldUpdateState = true;
}
if (gridColumn.GetFilterOperator() != column.FilterOperator)
{
gridColumn.SetFilterOperator(column.FilterOperator);
shouldUpdateState = true;
}
if (!object.Equals(gridColumn.GetSecondFilterValue(), GetFilterValue(column.SecondFilterValue, gridColumn.FilterPropertyType)))
{
gridColumn.SetFilterValue(GetFilterValue(column.SecondFilterValue, gridColumn.FilterPropertyType), false);
shouldUpdateState = true;
}
}
}
}
if (settings.Groups != null && !settings.Groups.SequenceEqual(Groups))
{
groups.CollectionChanged -= GroupsCollectionChanged;
Groups.Clear();
settings.Groups.ToList().ForEach(Groups.Add);
shouldUpdateState = true;
groups.CollectionChanged += GroupsCollectionChanged;
}
if (settings.CurrentPage != null && settings.CurrentPage != CurrentPage)
{
CurrentPage = settings.CurrentPage.Value;
shouldUpdateState = true;
}
if (settings.PageSize != null && settings.PageSize != PageSize)
{
PageSize = settings.PageSize.Value;
shouldUpdateState = true;
}
if (shouldUpdateState)
{
skip = CurrentPage * PageSize;
CalculatePager();
UpdateColumnsOrder();
await Reload();
}
}
}
object GetFilterValue(object value, Type type)
{
if (value != null && value is JsonElement)
{
var element = (JsonElement)value;
if (type == typeof(Int16) || type == typeof(Int16?))
{
return element.GetInt16();
}
else if (type == typeof(Int32) || type == typeof(Int32?))
{
return element.GetInt32();
}
else if (type == typeof(Int64) || type == typeof(Int64?))
{
return element.GetInt64();
}
else if (type == typeof(double) || type == typeof(double?))
{
return element.GetDouble();
}
else if (type == typeof(bool) || type == typeof(bool?))
{
return element.GetBoolean();
}
else if (type == typeof(DateTime) || type == typeof(DateTime?))
{
return element.GetDateTime();
}
else if (type == typeof(DateTime) || type == typeof(DateTime?))
{
return element.GetDateTime();
}
else if (type.IsEnum)
{
return element.GetInt32();
}
else
{
if (element.ValueKind == JsonValueKind.Number)
{
return element.GetDouble();
}
else if (element.ValueKind == JsonValueKind.True || element.ValueKind == JsonValueKind.False)
{
return element.GetBoolean();
}
else
{
return element.GetRawText().Replace("\"", "");
}
}
}
else
{
return value;
}
}
bool canSaveSettings = true;
DataGridSettings settings;
/// <summary>
/// Gets or sets DataGrid settings.
/// </summary>
[Parameter]
public DataGridSettings Settings
{
get
{
return settings;
}
set
{
if (settings != value)
{
settings = value;
if (settings == null)
{
canSaveSettings = false;
Groups.Clear();
CurrentPage = 0;
skip = 0;
Reset(true);
allColumns.ToList().ForEach(c =>
{
c.SetVisible(true);
});
InvokeAsync(Reload);
canSaveSettings = true;
}
}
}
}
/// <summary>
/// Gets or sets the settings changed callback.
/// </summary>
/// <value>The settings callback.</value>
[Parameter]
public EventCallback<DataGridSettings> SettingsChanged { get; set; }
async Task ChangePage(PagerEventArgs args)
{
CurrentPage = args.PageIndex;
SaveSettings();
await OnPageChanged(args);
}
}
}

View File

@@ -128,11 +128,57 @@ else
}
}
bool clicking;
async Task OnClick(MouseEventArgs args)
{
if (clicking)
{
return;
}
try
{
clicking = true;
if (Grid != null)
{
#if NET5_0_OR_GREATER
await Grid.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,
OffsetX = args.OffsetX,
OffsetY = args.OffsetY,
ScreenX = args.ScreenX,
ScreenY = args.ScreenY,
ShiftKey = args.ShiftKey,
Type = args.Type,
Column = Column
});
#else
await Grid.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 Grid.OnRowClick(new DataGridRowMouseEventArgs<TItem>
{
@@ -170,6 +216,11 @@ else
Type = args.Type
});
#endif
}
}
finally
{
clicking = false;
}
}
@@ -177,6 +228,45 @@ else
{
if (Grid != null)
{
#if NET5_0_OR_GREATER
await Grid.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,
OffsetX = args.OffsetX,
OffsetY = args.OffsetY,
ScreenX = args.ScreenX,
ScreenY = args.ScreenY,
ShiftKey = args.ShiftKey,
Type = args.Type,
Column = Column
});
#else
await Grid.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 Grid.OnRowDblClick(new DataGridRowMouseEventArgs<TItem>
{

View File

@@ -152,12 +152,32 @@ namespace Radzen.Blazor
[Parameter]
public SortOrder? SortOrder { get; set; }
bool visible = true;
/// <summary>
/// Gets or sets a value indicating whether this <see cref="RadzenDataGridColumn{TItem}"/> is visible.
/// </summary>
/// <value><c>true</c> if visible; otherwise, <c>false</c>.</value>
[Parameter]
public bool Visible { get; set; } = true;
public bool Visible
{
get
{
return visible;
}
set
{
if (visible != value)
{
visible = value;
if (Grid != null)
{
Grid.UpdatePickableColumn(this, visible);
InvokeAsync(Grid.ChangeState);
}
}
}
}
bool? _visible;
@@ -173,6 +193,11 @@ namespace Radzen.Blazor
internal void SetVisible(bool? value)
{
_visible = value;
if (Grid != null)
{
Grid.UpdatePickableColumn(this, _visible == true);
}
}
/// <summary>
@@ -445,7 +470,7 @@ namespace Radzen.Blazor
{
var visibleColumns = Grid.ColumnsCollection.Where(c => c.GetVisible()).ToList();
var left = visibleColumns
.TakeWhile((c, i) => visibleColumns.IndexOf(this) > i && c.IsFrozen())
.Where((c, i) => visibleColumns.IndexOf(this) > i && c.IsFrozen())
.Sum(c => {
var w = !string.IsNullOrEmpty(c.GetWidth()) ? c.GetWidth() : Grid.ColumnWidth;
var cw = 200;
@@ -503,6 +528,42 @@ namespace Radzen.Blazor
}
internal void SetSortOrder(SortOrder? order)
{
var descriptor = Grid.sorts.Where(d => d.Property == GetSortProperty()).FirstOrDefault();
if (descriptor == null)
{
descriptor = new SortDescriptor() { Property = GetSortProperty() };
}
if (GetSortOrder() == null)
{
SetSortOrderInternal(Radzen.SortOrder.Ascending);
descriptor.SortOrder = Radzen.SortOrder.Ascending;
}
else if (GetSortOrder() == Radzen.SortOrder.Ascending)
{
SetSortOrderInternal(Radzen.SortOrder.Descending);
descriptor.SortOrder = Radzen.SortOrder.Descending;
}
else if (GetSortOrder() == Radzen.SortOrder.Descending)
{
SetSortOrderInternal(null);
if (Grid.sorts.Where(d => d.Property == GetSortProperty()).Any())
{
Grid.sorts.Remove(descriptor);
}
descriptor = null;
}
if (descriptor != null && !Grid.sorts.Where(d => d.Property == GetSortProperty()).Any())
{
Grid.sorts.Add(descriptor);
}
sortOrder = new SortOrder?[] { order };
}
internal void SetSortOrderInternal(SortOrder? order)
{
sortOrder = new SortOrder?[] { order };
}
@@ -546,7 +607,10 @@ namespace Radzen.Blazor
Type _filterPropertyType;
internal Type FilterPropertyType
/// <summary>
/// Gets the filter property type.
/// </summary>
public Type FilterPropertyType
{
get
{
@@ -596,6 +660,16 @@ namespace Radzen.Blazor
if (parameters.DidParameterChange(nameof(SortOrder), SortOrder))
{
sortOrder = new SortOrder?[] { parameters.GetValueOrDefault<SortOrder?>(nameof(SortOrder)) };
if (Grid != null)
{
var descriptor = Grid.sorts.Where(d => d.Property == GetSortProperty()).FirstOrDefault();
if (descriptor == null)
{
Grid.sorts.Add(new SortDescriptor() { Property = GetSortProperty(), SortOrder = sortOrder.FirstOrDefault() });
Grid._view = null;
}
}
}
if (parameters.DidParameterChange(nameof(FilterValue), FilterValue))
@@ -605,6 +679,7 @@ namespace Radzen.Blazor
if (FilterTemplate != null)
{
FilterValue = filterValue;
Grid.SaveSettings();
if (Grid.IsVirtualizationAllowed())
{
#if NET5_0_OR_GREATER
@@ -818,7 +893,7 @@ namespace Radzen.Blazor
/// <summary>
/// Get possible column filter operators.
/// </summary>
public IEnumerable<FilterOperator> GetFilterOperators()
public virtual IEnumerable<FilterOperator> GetFilterOperators()
{
if (PropertyAccess.IsEnum(FilterPropertyType))
return new FilterOperator[] { FilterOperator.Equals, FilterOperator.NotEquals };
@@ -911,6 +986,15 @@ namespace Radzen.Blazor
}
}
/// <summary>
/// Gets value indicating if the user can specify time in DateTime column filter.
/// </summary>
public virtual bool ShowTimeForDateTimeFilter()
{
return true;
}
/// <summary>
/// Disposes this instance.
/// </summary>
@@ -919,4 +1003,4 @@ namespace Radzen.Blazor
Grid?.RemoveColumn(this);
}
}
}
}

View File

@@ -16,52 +16,94 @@
<div id="@($"{Grid.PopupID}{Column.GetFilterProperty()}")" class="rz-overlaypanel"
style="display:none;" tabindex="0">
<div class="rz-overlaypanel-content">
<ul class="rz-listbox-list" style="margin:5px">
<ul class="rz-listbox-list">
@if (Column.FilterPropertyType == typeof(string))
{
@if (Column.GetFilterOperators().Contains(FilterOperator.Contains))
{
<li class="@(FilterOperatorStyle(Column, FilterOperator.Contains))" @onclick="@(args => ApplyFilter(FilterOperator.Contains))" style="display: block;">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.Contains)</span><span>@Grid.ContainsText</span>
</li>
}
@if (Column.GetFilterOperators().Contains(FilterOperator.DoesNotContain))
{
<li class="@(FilterOperatorStyle(Column, FilterOperator.DoesNotContain))" @onclick="@(args => ApplyFilter(FilterOperator.DoesNotContain))" style="display: block;">
<span class="rz-filter-menu-symbol"><s>@Column.GetFilterOperatorSymbol(FilterOperator.DoesNotContain)</s></span><span>@Grid.DoesNotContainText</span>
</li>
}
@if (Column.GetFilterOperators().Contains(FilterOperator.StartsWith))
{
<li class="@(FilterOperatorStyle(Column, FilterOperator.StartsWith))" @onclick="@(args => ApplyFilter(FilterOperator.StartsWith))" style="display: block;">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.StartsWith)</span><span>@Grid.StartsWithText</span>
</li>
}
@if (Column.GetFilterOperators().Contains(FilterOperator.EndsWith))
{
<li class="@(FilterOperatorStyle(Column, FilterOperator.EndsWith))" @onclick="@(args => ApplyFilter(FilterOperator.EndsWith))" style="display: block;">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.EndsWith)</span><span>@Grid.EndsWithText</span>
</li>
}
@if (Column.GetFilterOperators().Contains(FilterOperator.IsEmpty))
{
<li class="@(FilterOperatorStyle(Column, FilterOperator.IsEmpty))" @onclick="@(args => ApplyFilter(FilterOperator.IsEmpty))" style="display: block;">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.IsEmpty)</span><span>@Grid.IsEmptyText</span>
</li>
}
@if (Column.GetFilterOperators().Contains(FilterOperator.IsNotEmpty))
{
<li class="@(FilterOperatorStyle(Column, FilterOperator.IsNotEmpty))" @onclick="@(args => ApplyFilter(FilterOperator.IsNotEmpty))" style="display: block;">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.IsNotEmpty)</span><span>@Grid.IsNotEmptyText</span>
</li>
}
}
@if (Column.GetFilterOperators().Contains(FilterOperator.Equals))
{
<li class="@(FilterOperatorStyle(Column, FilterOperator.Equals))" @onclick="@(args => ApplyFilter(FilterOperator.Equals))" style="display: block;">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.Equals)</span><span>@Grid.EqualsText</span>
</li>
}
@if (Column.GetFilterOperators().Contains(FilterOperator.NotEquals))
{
<li class="@(FilterOperatorStyle(Column, FilterOperator.NotEquals))" @onclick="@(args => ApplyFilter(FilterOperator.NotEquals))" style="display: block;">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.NotEquals)</span><span>@Grid.NotEqualsText</span>
</li>
}
@if (Column.GetFilterOperators().Contains(FilterOperator.LessThan))
{
<li class="@(FilterOperatorStyle(Column, FilterOperator.LessThan))" @onclick="@(args => ApplyFilter(FilterOperator.LessThan))" style="display: block;">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.LessThan)</span><span>@Grid.LessThanText</span>
</li>
}
@if (Column.GetFilterOperators().Contains(FilterOperator.LessThanOrEquals))
{
<li class="@(FilterOperatorStyle(Column, FilterOperator.LessThanOrEquals))" @onclick="@(args => ApplyFilter(FilterOperator.LessThanOrEquals))" style="display: block;">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.LessThanOrEquals)</span><span>@Grid.LessThanOrEqualsText</span>
</li>
}
@if (Column.GetFilterOperators().Contains(FilterOperator.GreaterThan))
{
<li class="@(FilterOperatorStyle(Column, FilterOperator.GreaterThan))" @onclick="@(args => ApplyFilter(FilterOperator.GreaterThan))" style="display: block;">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.GreaterThan)</span><span>@Grid.GreaterThanText</span>
</li>
}
@if (Column.GetFilterOperators().Contains(FilterOperator.GreaterThanOrEquals))
{
<li class="@(FilterOperatorStyle(Column, FilterOperator.GreaterThanOrEquals))" @onclick="@(args => ApplyFilter(FilterOperator.GreaterThanOrEquals))" style="display: block;">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.GreaterThanOrEquals)</span><span>@Grid.GreaterThanOrEqualsText</span>
</li>
}
@if (Column.GetFilterOperators().Contains(FilterOperator.IsNull))
{
<li class="@(FilterOperatorStyle(Column, FilterOperator.IsNull))" @onclick="@(args => ApplyFilter(FilterOperator.IsNull))" style="display: block;">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.IsNull)</span><span>@Grid.IsNullText</span>
</li>
}
@if (Column.GetFilterOperators().Contains(FilterOperator.IsNotNull))
{
<li class="@(FilterOperatorStyle(Column, FilterOperator.IsNotNull))" @onclick="@(args => ApplyFilter(FilterOperator.IsNotNull))" style="display: block;">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.IsNotNull)</span><span>@Grid.IsNotNullText</span>
</li>
}
<li class="rz-multiselect-item" @onclick="@(args => ClearFilter())" style="display:block;">
<span class="rz-filter-menu-symbol">x</span><span>@Grid.ClearFilterText</span>
</li>
@@ -88,7 +130,7 @@
Column.GetFilterOperator() == FilterOperator.IsNotNull || Column.GetFilterOperator() == FilterOperator.IsNull
|| Column.GetFilterOperator() == FilterOperator.IsEmpty || Column.GetFilterOperator() == FilterOperator.IsNotEmpty
? "rz-grid-filter-active" : "";
return $"rz-filter-button rz-button rz-button-md rz-button-icon-only btn-light {additionalStyle}";
return $"rz-filter-button rz-button rz-button-md rz-button-icon-only rz-variant-flat rz-light {additionalStyle}";
}
protected async Task ApplyFilter(FilterOperator value)
@@ -97,7 +139,7 @@
|| value == FilterOperator.IsEmpty || value == FilterOperator.IsNotEmpty)
{
Column.SetFilterValue(value == FilterOperator.IsEmpty || value == FilterOperator.IsNotEmpty ? string.Empty : null);
Column.SetFilterValue(value == FilterOperator.IsEmpty || value == FilterOperator.IsNotEmpty ? string.Empty : null, false);
Column.SetFilterValue(null, false);
}
Column.SetFilterOperator(value);

View File

@@ -2,23 +2,23 @@
@if (RowIndex == Column.GetLevel())
{
<th rowspan="@(Column.GetRowSpan())" colspan="@(Column.GetColSpan())" @attributes="@Attributes" class="@CssClass" scope="col" style="@Column.GetStyle(true, true)" @onmouseup=@(args => Grid.EndColumnReorder(args, ColumnIndex)) >
<div @onclick='@((args) => Grid.OnSort(args, Column))' style="width:100%;outline:none;" tabindex="@SortingTabIndex" @onkeydown="OnSortKeyPressed">
<div @onclick='@((args) => Grid.OnSort(args, Column))' tabindex="@SortingTabIndex" @onkeydown="OnSortKeyPressed">
@if (Column.Parent == null && Column.Columns == null && (Grid.AllowColumnReorder && Column.Reorderable || Grid.AllowGrouping && Column.Groupable))
{
<span id="@Grid.getColumnResizerId(ColumnIndex)" class="rz-column-drag"
@onclick:preventDefault="true" @onclick:stopPropagation="true"
@onmousedown=@(args => Grid.StartColumnReorder(args, ColumnIndex))>&nbsp;</span>
@onmousedown=@(args => Grid.StartColumnReorder(args, ColumnIndex))></span>
}
<span class="rz-column-title">
<span class="rz-column-title" title="@Column.Title">
@if (Column.HeaderTemplate != null)
{
@Column.HeaderTemplate
<span class="rz-column-title-content">@Column.HeaderTemplate</span>
}
else
{
@Column.Title
<span class="rz-column-title-content">@Column.Title</span>
}
</span>
@if (Grid.AllowSorting && Column.Sortable)
{
@if (Column.GetSortOrder() == SortOrder.Ascending)
@@ -26,7 +26,7 @@
<span class="rz-sortable-column-icon rzi-grid-sort rzi-sort rzi-sort-asc"></span>
@if(Grid.ShowMultiColumnSortingIndex)
{
<span class="rz-column-title" style="padding-left:0px">@getSortIndex()</span>
<RadzenBadge BadgeStyle="BadgeStyle.Info" Shade="Shade.Lighter" IsPill=true Text="@getSortIndex()" />
}
}
else if (Column.GetSortOrder() == SortOrder.Descending)
@@ -34,7 +34,7 @@
<span class="rz-sortable-column-icon rzi-grid-sort rzi-sort rzi-sort-desc"></span>
@if(Grid.ShowMultiColumnSortingIndex)
{
<span class="rz-column-title" style="padding-left:0px">@getSortIndex()</span>
<RadzenBadge BadgeStyle="BadgeStyle.Info" Shade="Shade.Lighter" IsPill=true Text="@getSortIndex()" />
}
}
else
@@ -42,6 +42,7 @@
<span class="rz-sortable-column-icon rzi-grid-sort rzi-sort"></span>
}
}
</span>
@if (Grid.AllowColumnResize && Column.Resizable && Column.Parent == null)
{
<div id="@Grid.getColumnResizerId(ColumnIndex)" style="cursor:col-resize;float:right;"
@@ -82,14 +83,14 @@
}
else if (Column.FilterPropertyType == typeof(bool) || Column.FilterPropertyType == typeof(bool?))
{
<RadzenCheckBox TriState="true" TValue="@object" Value="@Column.GetFilterValue()" Change="@(args => { Column.FilterValue = null; Column.SetFilterValue(args); Grid.Reload(); })" />
<RadzenCheckBox TriState="true" TValue="@object" Value="@Column.GetFilterValue()" Change="@(args => { Column.FilterValue = null; Column.SetFilterValue(args); Grid.SaveSettings(); Grid.Reload(); })" />
}
else
{
<RadzenTextBox Value="@($"{Column.GetFilterValue()}")" Change="@(args => Column.SetFilterValue(args))" />
}
<RadzenDropDown @onclick:preventDefault="true" TextProperty="Text" ValueProperty="Value" Style="width: 80px"
<RadzenDropDown @onclick:preventDefault="true" TextProperty="Text" ValueProperty="Value" Style="width: 90px"
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 @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))" />
@@ -106,13 +107,13 @@
else if (PropertyAccess.IsDate(Column.FilterPropertyType))
{
<RadzenDatePicker TValue="@object"
ShowTime="true" ShowTimeOkButton="true" DateFormat="@Grid.getFilterDateFormat(Column)"
ShowTime="@Column.ShowTimeForDateTimeFilter()" ShowTimeOkButton="true" DateFormat="@Grid.getFilterDateFormat(Column)"
Value="@Column.GetSecondFilterValue()" Change="@(args => Column.SetFilterValue(args.Value, false))" />
}
else if (Column.FilterPropertyType == typeof(bool) || Column.FilterPropertyType == typeof(bool?))
{
<RadzenCheckBox TriState="true" TValue="@object" Value="@Column.GetSecondFilterValue()" Change="@(args => Column.SetFilterValue(args, false))"/>
<RadzenCheckBox TriState="true" TValue="@object" Value="@Column.GetSecondFilterValue()" Change="@(args => { Column.SetFilterValue(args, false); Grid.SaveSettings(); })" />
}
else
{
@@ -137,7 +138,7 @@ else
@foreach(var column in Grid.childColumns.Where(c => c.GetVisible() && c.Parent == Column))
{
<RadzenDataGridHeaderCell RowIndex="@RowIndex" Grid="@Grid" Column="@column" ColumnIndex="@ColumnIndex"
CssClass="@($"rz-unselectable-text {(Grid.AllowSorting && column.Sortable ? "rz-sortable-column" : "")} {column.HeaderCssClass} {Grid.getFrozenColumnClass(column, Grid.ColumnsCollection.Where(c => c.GetVisible()).ToList())} {(column.Columns != null || column.Parent != null ? "rz-composite-cell" : "")}".Trim())" />
CssClass="@($"rz-unselectable-text {(Grid.AllowSorting && column.Sortable ? "rz-sortable-column" : "")} {column.HeaderCssClass} {Grid.getFrozenColumnClass(column, Grid.ColumnsCollection.Where(c => c.GetVisible()).ToList())} {(column.Columns != null || column.Parent != null ? "rz-composite-cell" : "")} {Grid.getColumnAlignClass(column)}".Trim())" />
}
}
@code {
@@ -182,7 +183,7 @@ else
string getSortIndex()
{
var descriptor = Grid.sorts.Where(s => s.Property == Column.GetSortProperty()).FirstOrDefault();
return descriptor != null ? $"({Grid.sorts.IndexOf(descriptor) + 1})" : "";
return descriptor != null ? $"{Grid.sorts.IndexOf(descriptor) + 1}" : "";
}
string getColumnPopupID()

View File

@@ -75,6 +75,33 @@
}
</span>
}
@if (Grid.LoadChildData.HasDelegate && Grid.ShowExpandColumn && Grid.allColumns.IndexOf(column) == 0)
{
<span class="rz-cell-toggle">
<a style="@(getExpandIconStyle(rowArgs.Item1.Expandable))" href="javascript:void(0)" @onclick="@(_ => Grid.ExpandItem(Item))">
<span class="@(Grid.ExpandedItemStyle(Item))"></span>
</a>
<span class="rz-cell-data" title="@(column.Template == null ? column.GetValue(Item) : "")">
@if (Item != null)
{
@if (Grid.IsRowInEditMode(Item) && column.EditTemplate != null)
{
@column.EditTemplate(Item)
}
else if (column.Template != null)
{
@column.Template(Item)
}
else
{
@column.GetValue(Item)
}
}
</span>
</span>
}
else
{
<span class="rz-cell-data" title="@(column.Template == null ? column.GetValue(Item) : "")">
@if (Item != null)
{
@@ -92,6 +119,7 @@
}
}
</span>
}
</RadzenDataGridCell>
}
@@ -167,4 +195,25 @@
{
return components.Where(component => component.Name == name).FirstOrDefault();
}
internal string getExpandIconStyle(bool expandable)
{
var rules = new List<string>();
if (!expandable)
{
rules.Add("visibility:hidden");
}
var child = Grid.childData.Any() ? Grid.childData.Where(c => c.Value?.Data?.Contains(Item) == true).FirstOrDefault() :
default(KeyValuePair<TItem, DataGridChildData<TItem>>);
var level = !object.Equals(child, default(KeyValuePair<TItem, DataGridChildData<TItem>>)) ? child.Value.Level : 0;
if (level > 0)
{
rules.Add($"margin-left: {level}rem");
}
return string.Join(';', rules);
}
}

View File

@@ -14,10 +14,10 @@
@if (!Inline)
{
<span class="@($"rz-calendar rz-calendar-w-btn{(Disabled ? " rz-state-disabled" : "")}")" style="width:100%">
<input @ref="@input" disabled="@Disabled" readonly="@IsReadonly" value="@FormattedValue" tabindex="@TabIndex"
<input @ref="@input" disabled="@Disabled" readonly="@IsReadonly" value="@FormattedValue" tabindex="@(Disabled ? "-1" : $"{TabIndex}")"
@onchange="@ParseDate" autocomplete="off" type="text" name="@Name"
class="rz-inputtext @InputClass @(IsReadonly ? "rz-readonly" : "")" id="@Name" placeholder="@Placeholder" onclick="@getOpenPopupForInput()"/>
<button onclick="@getOpenPopup()" class="@($"rz-datepicker-trigger rz-calendar-button rz-button rz-button-icon-only{(Disabled ? " rz-state-disabled" : "")}")" tabindex="-1" type="button">
<button @onmousedown=@OnToggle onclick="@getOpenPopup()" 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="rz-button-icon-left rzi rzi-calendar"></span><span class="rz-button-text"></span>
</button>
@if (AllowClear && HasValue)
@@ -27,7 +27,7 @@
</span>
}
<div id="@PopupID" style=@PopupStyle class="@($"{(Inline ? "rz-datepicker-inline " : "")}rz-datepicker")" @onclick:preventDefault="true">
<Popup id="@PopupID" Lazy=@(PopupRenderMode == PopupRenderMode.OnDemand) @ref=@popup style=@PopupStyle class="@($"{(Inline ? "rz-datepicker-inline " : "")}rz-datepicker")">
<div class="rz-datepicker-group">
@if (!TimeOnly)
{
@@ -80,7 +80,7 @@
{
<td @attributes="@(dateArgs.Attributes)" onmouseup=@(Inline || ShowTime || dateArgs.Disabled ? "" : $"Radzen.closePopup('{PopupID}')")
@onclick="@(async () => { if (!Disabled && !dateArgs.Disabled) { await SetDay(date); } })">
<span class=@($"rz-state-default{(DateTimeValue.HasValue && DateTimeValue.Value.Year == date.Year && DateTimeValue.Value.Month == date.Month && DateTimeValue.Value.Day == date.Day ? " rz-state-active" : "")}{(!dateArgs.Disabled ? "" : " rz-state-disabled")}")>@date.Day</span>
<span class=@($"rz-state-default{(DateTimeValue.HasValue && DateTimeValue.Value.Date.CompareTo(date.Date)== 0 ? " rz-state-active" : "")}{(DateTime.Now.Date.CompareTo(date.Date) == 0 ? " rz-datepicker-currentday" : "")}{(!dateArgs.Disabled ? "" : " rz-state-disabled")}")>@date.Day</span>
</td>
}
else
@@ -106,7 +106,7 @@
</div>
@if (ShowTime)
{
<div class="rz-timepicker">
<div class="rz-timepicker" @onmousedown:stopPropagation>
<RadzenNumeric TValue="int" Disabled="@Disabled" Value="@(HourFormat == "12" ? ((CurrentDate.Hour + 11) % 12) + 1 : CurrentDate.Hour)"
Min="@(HourFormat == "12" ? 1 : -1)" Max="@(HourFormat == "12" ? 12 : 24)" TValue="double" Step="@HoursStep"
Change="@UpdateHour" class="rz-hour-picker" @oninput=@OnUpdateHourInput Format="@(PadHours ? "00" : "")" />
@@ -137,7 +137,7 @@
}
@if (ShowTimeOkButton)
{
<button type="button" class="rz-button rz-button-md btn-secondary" style="width:60px;padding:0px;margin-left:10px;"
<button type="button" class="rz-button rz-button-md rz-secondary"
@onclick="@OkClick"
onmouseup="@($"Radzen.closePopup('{PopupID}')")">
<span class="rz-button-text">Ok</span>
@@ -145,7 +145,7 @@
}
</div>
}
</div>
</Popup>
</div>
}

View File

@@ -866,12 +866,12 @@ namespace Radzen.Blazor
private string getOpenPopup()
{
return !Disabled && !ReadOnly && !Inline ? $"Radzen.togglePopup(this.parentNode, '{PopupID}')" : "";
return PopupRenderMode == PopupRenderMode.Initial && !Disabled && !ReadOnly && !Inline ? $"Radzen.togglePopup(this.parentNode, '{PopupID}')" : "";
}
private string getOpenPopupForInput()
{
return !Disabled && !ReadOnly && !Inline && !AllowInput ? $"Radzen.togglePopup(this.parentNode, '{PopupID}')" : "";
return PopupRenderMode == PopupRenderMode.Initial && !Disabled && !ReadOnly && !Inline && !AllowInput ? $"Radzen.togglePopup(this.parentNode, '{PopupID}')" : "";
}
/// <summary>
@@ -978,5 +978,22 @@ namespace Radzen.Blazor
return base.OnAfterRenderAsync(firstRender);
}
Popup popup;
/// <summary>
/// Gets or sets the render mode.
/// </summary>
/// <value>The render mode.</value>
[Parameter]
public PopupRenderMode PopupRenderMode { get; set; } = PopupRenderMode.Initial;
async Task OnToggle()
{
if (PopupRenderMode == PopupRenderMode.OnDemand && !Disabled && !ReadOnly && !Inline)
{
await popup.ToggleAsync(Element);
}
}
}
}

View File

@@ -9,12 +9,12 @@
@if (Visible)
{
<div @ref="@Element" @attributes="Attributes" class="@GetCssClass()" onmousedown="Radzen.activeElement = null" @onclick="@(args => OpenPopup("ArrowDown", false, true))" style="@Style" tabindex="@TabIndex"
<div @ref="@Element" @attributes="Attributes" class="@GetCssClass()" onmousedown="Radzen.activeElement = null" @onclick="@(args => OpenPopup("ArrowDown", false, true))" @onclick:preventDefault @onclick:stopPropagation style="@Style" tabindex="@(Disabled ? "-1" : $"{TabIndex}")"
@onkeydown="@((args) => OnKeyPress(args))" id="@GetId()" @onfocus="@((args) => OnFocus(args))">
<div class="rz-helper-hidden-accessible">
<input disabled="@Disabled" style="width:100%" aria-haspopup="listbox" readonly="" type="text" tabindex="-1"
<input disabled="@Disabled" aria-haspopup="listbox" readonly="" type="text" tabindex="-1"
name="@Name" value="@(internalValue != null ? internalValue : "")"
aria-label="@(!Multiple && internalValue != null ? PropertyAccess.GetItemOrValueFromProperty(internalValue, TextProperty) : "")" />
aria-label="@(!Multiple && internalValue != null ? internalValue : "")" />
</div>
@if (ValueTemplate != null && selectedItem != null)
@@ -32,9 +32,23 @@
else if (selectedItem != null && !Multiple)
{
<label class="rz-dropdown-label rz-inputtext ">
@PropertyAccess.GetItemOrValueFromProperty(selectedItem, TextProperty)
@GetItemOrValueFromProperty(selectedItem, TextProperty)
</label>
}
else if (Chips && selectedItems.Count > 0 && selectedItems.Count < MaxSelectedLabels)
{
<div class="rz-dropdown-chips-wrapper">
@foreach (var item in selectedItems)
{
<div class="rz-chip">
<span class="rz-chip-text">
@GetItemOrValueFromProperty(item, TextProperty)
</span>
<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>
</div>
}
</div>
}
else if (selectedItems.Count > 0)
{
<label class="rz-dropdown-label rz-inputtext ">
@@ -42,13 +56,13 @@
{
@if (Template == null)
{
@(string.Join(",", selectedItems.Select(i => PropertyAccess.GetItemOrValueFromProperty(i, TextProperty))))
@(string.Join(Separator, selectedItems.Select(i => GetItemOrValueFromProperty(i, TextProperty))))
}
else
{
foreach (var item in selectedItems)
{
@Template(item)@(",")
@Template(item)@(Separator)
}
}
}
@@ -80,14 +94,16 @@
@if (AllowFiltering && !Multiple)
{
<div class="rz-dropdown-filter-container">
<input id="@SearchID" @ref="@search" tabindex="@TabIndex" class="rz-dropdown-filter rz-inputtext " autocomplete="off" type="text"
<input id="@SearchID" @ref="@search" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" class="rz-dropdown-filter rz-inputtext " autocomplete="off" type="text"
@onchange="@((ChangeEventArgs args) => OnFilter(args))" @onkeydown="@((args) => OnFilterKeyPress(args))" value="@searchText" />
<span class="rz-dropdown-filter-icon rzi rzi-search"></span>
</div>
}
@if (Multiple)
@if (Multiple && (AllowSelectAll || AllowFiltering))
{
<div class=" rz-multiselect-header rz-helper-clearfix" @onclick:preventDefault>
@if(AllowSelectAll)
{
<div class="rz-chkbox" title="@(!AllowFiltering ? "" : SelectAllText)" @onclick="@SelectAll">
<div class="rz-helper-hidden-accessible">
<input readonly="readonly" type="checkbox">
@@ -96,14 +112,15 @@
<span class="@(IsAllSelected() ? "rz-chkbox-icon rzi rzi-check" : "rz-chkbox-icon ")"></span>
</div>
</div>
@if (!AllowFiltering && !string.IsNullOrEmpty(SelectAllText))
}
@if (AllowSelectAll && !AllowFiltering && !string.IsNullOrEmpty(SelectAllText))
{
<span style="cursor:pointer" @onclick="@SelectAll">@SelectAllText</span>
}
@if (AllowFiltering)
{
<div class="rz-multiselect-filter-container">
<input id="@SearchID" tabindex="@TabIndex" class="rz-inputtext" role="textbox" type="text"
<input id="@SearchID" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" class="rz-inputtext" role="textbox" type="text"
onclick="Radzen.preventDefaultAndStopPropagation(event)"
@ref="@search"
@onchange="@((args) => OnFilter(args))" @onkeydown="@((args) => OnFilterKeyPress(args))" value="@searchText" />
@@ -115,8 +132,8 @@
</a>
</div>
}
<div class="@(Multiple ? "rz-multiselect-items-wrapper" : "rz-dropdown-items-wrapper")" style="max-height: 200px;overflow-x: hidden">
<ul @ref="list" class="@(Multiple ? "rz-multiselect-items rz-multiselect-list " : "rz-dropdown-items rz-dropdown-list ")" role="listbox">
<div class="@(Multiple ? "rz-multiselect-items-wrapper" : "rz-dropdown-items-wrapper")" style="@PopupStyle">
<ul @ref="list" class="@(Multiple ? "rz-multiselect-items rz-multiselect-list" : "rz-dropdown-items rz-dropdown-list")" role="listbox">
@if (View != null)
{
@RenderItems()

View File

@@ -2,6 +2,7 @@
using Microsoft.AspNetCore.Components.Rendering;
using Microsoft.JSInterop;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.Web;
namespace Radzen.Blazor
{
@@ -52,7 +53,7 @@ namespace Radzen.Blazor
/// <param name="key">The key.</param>
/// <param name="isFilter">if set to <c>true</c> [is filter].</param>
/// <param name="isFromClick">if set to <c>true</c> [is from click].</param>
protected override async System.Threading.Tasks.Task OpenPopup(string key = "ArrowDown", bool isFilter = false, bool isFromClick = false)
protected override async Task OpenPopup(string key = "ArrowDown", bool isFilter = false, bool isFromClick = false)
{
if (Disabled)
return;
@@ -71,8 +72,11 @@ namespace Radzen.Blazor
builder.OpenComponent(0, typeof(RadzenDropDownItem<TValue>));
builder.AddAttribute(1, "DropDown", this);
builder.AddAttribute(2, "Item", item);
if (DisabledProperty!=null)
builder.AddAttribute(3, "Disabled", PropertyAccess.GetItemOrValueFromProperty(item, DisabledProperty));
if (DisabledProperty != null)
{
builder.AddAttribute(3, "Disabled", GetItemOrValueFromProperty(item, DisabledProperty));
}
builder.SetKey(GetKey(item));
builder.CloseComponent();
@@ -85,6 +89,21 @@ namespace Radzen.Blazor
[Parameter]
public int MaxSelectedLabels { get; set; } = 4;
/// <summary>
/// Gets or sets the Popup height.
/// </summary>
/// <value>The number Popup height.</value>
[Parameter]
public string PopupStyle { get; set; } = "max-height:200px;overflow-x:hidden";
/// <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>.
/// </summary>
/// <value><c>true</c> to display the selected items as chips; otherwise, <c>false</c>.</value>
[Parameter]
public bool Chips { get; set; }
/// <summary>
/// Gets or sets the selected items text.
/// </summary>
@@ -120,6 +139,8 @@ namespace Radzen.Blazor
}
}
private bool shouldReposition;
/// <inheritdoc />
protected override async Task OnAfterRenderAsync(bool firstRender)
{
@@ -144,7 +165,6 @@ namespace Radzen.Blazor
if (!Disabled)
{
await JSRuntime.InvokeVoidAsync("Radzen.preventArrows", Element);
reload = true;
}
if (reload)
@@ -153,6 +173,13 @@ namespace Radzen.Blazor
}
}
}
if (shouldReposition)
{
shouldReposition = false;
await JSRuntime.InvokeVoidAsync("Radzen.repositionPopup", Element, PopupID);
}
}
/// <summary>
@@ -160,7 +187,7 @@ namespace Radzen.Blazor
/// </summary>
/// <param name="item">The item.</param>
/// <param name="isFromKey">if set to <c>true</c> [is from key].</param>
protected override async System.Threading.Tasks.Task OnSelectItem(object item, bool isFromKey = false)
protected override async Task OnSelectItem(object item, bool isFromKey = false)
{
if (!ReadOnly)
{
@@ -173,15 +200,31 @@ namespace Radzen.Blazor
}
}
internal async System.Threading.Tasks.Task OnSelectItemInternal(object item, bool isFromKey = false)
private async Task OnChipRemove(object item)
{
if (!Disabled)
{
await OnSelectItemInternal(item);
}
}
internal async Task OnSelectItemInternal(object item, bool isFromKey = false)
{
await OnSelectItem(item, isFromKey);
if (Chips)
{
shouldReposition = true;
}
}
/// <inheritdoc />
protected override string GetComponentCssClass()
{
return GetClassList("rz-dropdown").Add("rz-clear", AllowClear).ToString();
return GetClassList("rz-dropdown")
.Add("rz-clear", AllowClear)
.Add("rz-dropdown-chips", Chips && selectedItems.Count > 0)
.ToString();
}
/// <inheritdoc />
@@ -195,9 +238,9 @@ namespace Radzen.Blazor
}
}
internal async System.Threading.Tasks.Task ClosePopup()
internal async Task ClosePopup()
{
await JSRuntime.InvokeVoidAsync("Radzen.closePopup", PopupID);
}
}
}
}

View File

@@ -10,7 +10,8 @@
@if (Visible)
{
<div @ref="@Element" @attributes="Attributes" class="@GetCssClass()" @onfocus="@((args) => OnFocus(args))"
style="@Style" tabindex="@TabIndex" id="@GetId()" @onclick="@(args => OpenPopup("ArrowDown", false, true))" @onkeydown="@((args) => OnKeyPress(args))">
style="@Style" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" id="@GetId()" @onclick="@(args => OpenPopup("ArrowDown", false, true))" @onclick:preventDefault @onclick:stopPropagation
@onkeydown="@((args) => OnKeyPress(args))">
<div class="rz-helper-hidden-accessible">
<input tabindex="-1" disabled="@Disabled" style="width:100%" aria-haspopup="listbox" readonly="" type="text"
name="@Name" aria-label="@(!Multiple && internalValue != null ? PropertyAccess.GetItemOrValueFromProperty(internalValue, TextProperty) : "")" />
@@ -38,26 +39,43 @@
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;
<label class="rz-dropdown-label rz-inputtext " style="width:100%;">
@if (itemsToUse.Count < MaxSelectedLabels)
{
@if (Template == null)
@if (itemsToUse.Count < MaxSelectedLabels && Template == null && Chips)
{
<div class="rz-dropdown-chips-wrapper">
@foreach (var item in itemsToUse)
{
@(string.Join(",", itemsToUse.Select(i => PropertyAccess.GetItemOrValueFromProperty(i, TextProperty))))
<div class="rz-chip">
<span class="rz-chip-text">
@PropertyAccess.GetItemOrValueFromProperty(item, TextProperty)
</span>
<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>
</div>
}
</div>
}
else
{
<label class="rz-dropdown-label rz-inputtext " style="width:100%;">
@if (itemsToUse.Count < MaxSelectedLabels)
{
@if (Template == null)
{
@(string.Join(",", itemsToUse.Select(i => PropertyAccess.GetItemOrValueFromProperty(i, TextProperty))))
}
else
{
foreach (var item in itemsToUse)
{
@Template(item)@(",")
}
}
}
else
{
foreach (var item in itemsToUse)
{
@Template(item)@(",")
}
@($"{itemsToUse.Count} {SelectedItemsText}")
}
}
else
{
@($"{itemsToUse.Count} {SelectedItemsText}")
}
</label>
</label>
}
}
else if (SelectedValue != null && !(SelectedValue is IEnumerable && !(SelectedValue is string)))
{
@@ -83,7 +101,7 @@
</div>
<div id="@PopupID" class="@(Multiple ? "rz-multiselect-panel" : "rz-dropdown-panel")"
style="display:none;min-width:320px;padding:0px;">
style="display:none;min-width:400px;padding:0px;">
<div class="rz-lookup-panel">
@if (AllowFiltering)
{
@@ -92,7 +110,7 @@
@onchange="@((args) => OnFilter(args))" @onkeydown="@((args) => OnFilterKeyPress(args))" value="@searchText" style="@(ShowSearch ? "" : "margin-right:0px;")" />
@if (ShowSearch)
{
<button class="rz-button rz-button-md btn-primary rz-button-icon-only" type="button" title="">
<button class="rz-button rz-button-md rz-button-icon-only rz-primary" type="button" title="">
<i class="rz-button-icon-left rzi">search</i>
</button>
}
@@ -100,7 +118,7 @@
}
@if (Template != null)
{
<RadzenDataGrid AllowRowSelectOnRowClick="@AllowRowSelectOnRowClick" @bind-Value=@selectedItems 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 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" : "")">
<Columns>
<RadzenDataGridColumn TItem="object" Property="@TextProperty" Title="@TextProperty" Type="typeof(string)">
@@ -118,7 +136,7 @@
{
if (!string.IsNullOrEmpty(TextProperty) || Columns != null)
{
<RadzenDataGrid AllowRowSelectOnRowClick="@AllowRowSelectOnRowClick" @bind-Value=@selectedItems 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 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" : "")">
<Columns>
@if (Columns != null)
@@ -137,7 +155,7 @@
}
else
{
<RadzenDataGrid AllowRowSelectOnRowClick="@AllowRowSelectOnRowClick" @bind-Value=@selectedItems 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 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" : "")">
<Columns>
<RadzenDataGridColumn TItem="object" Property="it" Title="Item" Type="typeof(string)">
@@ -157,7 +175,7 @@
@if (AllowClear && (!Multiple && HasValue || Multiple && (selectedItems.Count > 0 || SelectedValue is IEnumerable)))
{
<i class="rz-dropdown-clear-icon rzi rzi-times" @onclick="@Clear"></i>
<i class="rz-dropdown-clear-icon rzi rzi-times" @onclick="@Clear" @onclick:stopPropagation="true"></i>
}
</div>
}

View File

@@ -35,6 +35,14 @@ namespace Radzen.Blazor
[Parameter]
public Action<DataGridCellRenderEventArgs<object>> CellRender { 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>.
/// </summary>
/// <value><c>true</c> to display the selected items as chips; otherwise, <c>false</c>.</value>
[Parameter]
public bool Chips { get; set; }
/// <summary>
/// Executes CellRender callback.
/// </summary>
@@ -417,7 +425,13 @@ namespace Radzen.Blazor
}
else
{
((List<object>)selectedItems).AddRange(values);
foreach (object v in values)
{
if (selectedItems.IndexOf(v) == -1)
{
selectedItems.Add(v);
}
}
}
}
@@ -542,7 +556,11 @@ namespace Radzen.Blazor
}
#endif
StateHasChanged();
await grid.FirstPage(true);
if (!IsVirtualizationAllowed())
{
await grid.FirstPage(true);
}
await JSRuntime.InvokeAsync<string>("Radzen.repositionPopup", Element, PopupID);
}
@@ -598,10 +616,18 @@ namespace Radzen.Blazor
}
private async Task OnChipRemove(object item)
{
if (!Disabled)
{
await SelectItem(item);
}
}
/// <inheritdoc />
protected override string GetComponentCssClass()
{
return GetClassList("rz-dropdown").Add("rz-clear", AllowClear).ToString();
return GetClassList("rz-dropdown").Add("rz-dropdown-chips", Chips && selectedItems.Count > 0).Add("rz-clear", AllowClear).ToString();
}
/// <inheritdoc />

View File

@@ -7,12 +7,12 @@
@if (DropDown.Multiple)
{
<li class="@GetComponentCssClass("rz-multiselect")"
aria-label="@PropertyAccess.GetItemOrValueFromProperty(Item, DropDown.TextProperty)" style="display: block;white-space: nowrap;"
aria-label="@DropDown.GetItemOrValueFromProperty(Item, DropDown.TextProperty)" style="display: block;white-space: nowrap;"
@onmousedown:preventDefault @onmousedown="args=>SelectItem(args,false)"
@onclick:preventDefault @onclick="args=>SelectItem(args,true)">
<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) ? "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>
</div>
<span>
@@ -22,14 +22,14 @@
}
else
{
@PropertyAccess.GetItemOrValueFromProperty(Item, DropDown.TextProperty)
@DropDown.GetItemOrValueFromProperty(Item, DropDown.TextProperty)
}
</span>
</li>
}
else
{
<li role="option" class="@GetComponentCssClass("rz-dropdown")" aria-label="@PropertyAccess.GetItemOrValueFromProperty(Item, DropDown.TextProperty)"
<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)">
<span>
@@ -39,7 +39,7 @@ else
}
else
{
@PropertyAccess.GetItemOrValueFromProperty(Item, DropDown.TextProperty)
@DropDown.GetItemOrValueFromProperty(Item, DropDown.TextProperty)
}
</span>
</li>

View File

@@ -9,7 +9,7 @@
{
<div @ref="@Element" style="@Style" @attributes="Attributes" class="@GetCssClass()" id="@GetId()">
<div class="rz-fileupload-buttonbar">
<span class="@ChooseClassList" tabindex="@TabIndex" onkeydown="if(event.keyCode == 32 || event.keyCode == 13){event.preventDefault();this.firstElementChild.click();}">
<span class="@ChooseClassList" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" onkeydown="if(event.keyCode == 32 || event.keyCode == 13){event.preventDefault();this.firstElementChild.click();}">
<input tabindex="-1" disabled="@Disabled" @ref="@fileUpload" name="@Name" type="file" accept="@Accept" onkeydown="event.stopPropagation()"
onchange="Radzen.uploadInputChange(event, null, false, false, true)" id="@Id" />
<span class="rz-button-text">@ChooseText</span>
@@ -42,9 +42,9 @@
<span>@FileSize</span>
}
</div>
<div tabindex="@TabIndex">
<button disabled="@Disabled" type="button" class="@ButtonClassList">
<span class="rz-button-icon-left rz-icon-trash" style="display:block" @onclick="@Remove"></span>
<div tabindex="@(Disabled ? "-1" : $"{TabIndex}")">
<button disabled="@Disabled" type="button" class="@ButtonClassList" @onclick="@Remove">
<span class="rz-button-icon-left rz-icon-trash" style="display:block"></span>
</button>
</div>
</div>

View File

@@ -39,13 +39,13 @@ namespace Radzen.Blazor
/// Gets the choose class list.
/// </summary>
/// <value>The choose class list.</value>
ClassList ChooseClassList => ClassList.Create("rz-fileupload-choose rz-button btn-secondary")
ClassList ChooseClassList => ClassList.Create("rz-fileupload-choose rz-button rz-secondary")
.AddDisabled(Disabled);
/// <summary>
/// Gets the button class list.
/// </summary>
/// <value>The button class list.</value>
ClassList ButtonClassList => ClassList.Create("rz-button rz-button-icon-only btn-light")
ClassList ButtonClassList => ClassList.Create("rz-button rz-button-icon-only rz-light")
.AddDisabled(Disabled);
/// <inheritdoc />

View File

@@ -60,19 +60,66 @@ namespace Radzen.Blazor
[Parameter]
public string ApiKey { get; set; }
/// <summary>
/// Gets or sets the Google map options: https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions.
/// </summary>
/// <value>The Google map options.</value>
[Parameter]
public Dictionary<string, object> Options { get; set; }
double zoom = 8;
/// <summary>
/// Gets or sets the zoom.
/// </summary>
/// <value>The zoom.</value>
[Parameter]
public double Zoom { get; set; } = 8;
public double Zoom
{
get
{
return zoom;
}
set
{
if (zoom != value)
{
zoom = value;
InvokeAsync(UpdateMap);
}
}
}
GoogleMapPosition center = new GoogleMapPosition() { Lat = 0, Lng = 0 };
/// <summary>
/// Gets or sets the center map position.
/// </summary>
/// <value>The center.</value>
[Parameter]
public GoogleMapPosition Center { get; set; } = new GoogleMapPosition() { Lat = 0, Lng = 0 };
public GoogleMapPosition Center
{
get
{
return center;
}
set
{
if (!object.Equals(center, value))
{
center = value;
InvokeAsync(UpdateMap);
}
}
}
async Task UpdateMap()
{
if (!firstRender)
{
await JSRuntime.InvokeVoidAsync("Radzen.updateMap", UniqueID, Zoom, Center);
}
}
/// <summary>
/// Gets or sets the markers.
@@ -133,22 +180,26 @@ namespace Radzen.Blazor
await MarkerClick.InvokeAsync(marker);
}
bool firstRender = true;
/// <inheritdoc />
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await base.OnAfterRenderAsync(firstRender);
this.firstRender = firstRender;
var data = Data != null ? Data : markers;
if (firstRender)
{
await JSRuntime.InvokeVoidAsync("Radzen.createMap", Element, Reference, UniqueID, ApiKey, Zoom, Center,
data.Select(m => new { Title = m.Title, Label = m.Label, Position = m.Position }));
data.Select(m => new { Title = m.Title, Label = m.Label, Position = m.Position }), Options);
}
else
{
await JSRuntime.InvokeVoidAsync("Radzen.updateMap", UniqueID, Zoom, Center,
data.Select(m => new { Title = m.Title, Label = m.Label, Position = m.Position }));
await JSRuntime.InvokeVoidAsync("Radzen.updateMap", UniqueID, null, null,
data.Select(m => new { Title = m.Title, Label = m.Label, Position = m.Position }), Options);
}
}

View File

@@ -119,7 +119,7 @@
<RadzenTextBox Value="@($"{column.FilterValue}")" Change="@(args => column.SetFilterValue(args))" />
}
<RadzenDropDown @onclick:preventDefault="true" TextProperty="Text" ValueProperty="Value" Style="width: 80px"
<RadzenDropDown @onclick:preventDefault="true" TextProperty="Text" ValueProperty="Value" Style="width: 90px"
Data="@(Enum.GetValues(typeof(LogicalFilterOperator)).Cast<LogicalFilterOperator>().Select(t => new { Text = t == LogicalFilterOperator.And ? AndOperatorText : OrOperatorText, Value = t }))" TValue="LogicalFilterOperator" Value="@column.LogicalFilterOperator" Change="@(args => column.SetLogicalFilterOperator((LogicalFilterOperator)args))" />
<RadzenDropDown @onclick:preventDefault="true" Data="@(column.FilterOperators)" TextProperty="Value" ValueProperty="Key" TValue="string" Value="@column.SecondFilterOperator" Change="@(args => column.SetSecondFilterOperator($"{args}"))" />
@@ -182,7 +182,7 @@
<label class="rz-cell-filter-label" style="height:35px">
@if (column.Type == "string" && column.Format == "date-time")
{
<button class="rz-button rz-button-md rz-button-icon-only btn-light" onclick="@($"Radzen.togglePopup(this.parentNode, '{PopupID}{column.GetFilterProperty()}')")">
<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>
@if (column.FilterValue != null)

View File

@@ -28,7 +28,7 @@ namespace Radzen.Blazor
/// <inheritdoc />
protected override string GetComponentCssClass()
{
return $"rzi {(IconStyle.HasValue ? $"rzi-{IconStyle.Value.ToString().ToLowerInvariant()} " : "")}d-inline-flex justify-content-center align-items-center";
return $"rzi{(IconStyle.HasValue ? $" rzi-{IconStyle.Value.ToString().ToLowerInvariant()}" : "")}";
}
}
}

View File

@@ -7,15 +7,17 @@
@inherits DropDownBase<TValue>
@if (Visible)
{
<div @ref="@Element" style="@Style" @attributes="Attributes" class="@GetCssClass()" tabindex="@TabIndex" @onkeydown="@OnKeyDown" id="@GetId()">
<div @ref="@Element" style="@Style" @attributes="Attributes" class="@GetCssClass()" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" @onkeydown="@OnKeyDown" id="@GetId()">
<div class="rz-helper-hidden-accessible">
<input name="@Name" readonly="@ReadOnly" disabled="@Disabled" type="text" />
</div>
@if (AllowFiltering || Multiple)
@if (AllowFiltering || (Multiple && AllowSelectAll))
{
<div class=" rz-listbox-header rz-helper-clearfix rz-listbox-header-w-checkbox">
@if (Multiple)
{
@if (AllowSelectAll)
{
<div class="rz-chkbox " @onclick="@SelectAll">
<div class="rz-helper-hidden-accessible">
<input id="@($"{UniqueID}sa")" readonly="readonly" type="checkbox">
@@ -24,7 +26,8 @@
<span class="@(IsAllSelected() ? "rz-chkbox-icon rzi rzi-check" : "rz-chkbox-icon")"></span>
</div>
</div>
@if (!AllowFiltering && !string.IsNullOrEmpty(Placeholder))
}
@if (AllowSelectAll && !AllowFiltering && !string.IsNullOrEmpty(Placeholder))
{
<label for="@($"{UniqueID}sa")" class="rz-dropdown-label rz-inputtext" style="width:100%;">@Placeholder</label>
}

View File

@@ -4,7 +4,7 @@
@using Microsoft.JSInterop
@typeparam TValue
<li class="@(ListBox.isSelected(Item) ? "rz-multiselect-item rz-state-highlight" : "rz-multiselect-item ")" aria-label="@PropertyAccess.GetItemOrValueFromProperty(Item, ListBox.TextProperty)" style="display: block;" @onclick="@(async () => { if (!ListBox.Disabled) { await ListBox.SelectItemInternal(Item); } })">
<li class="@(ListBox.isSelected(Item) ? "rz-multiselect-item rz-state-highlight" : "rz-multiselect-item ")" aria-label="@PropertyAccess.GetItemOrValueFromProperty(Item, ListBox.TextProperty)" @onclick="@(async () => { if (!ListBox.Disabled) { await ListBox.SelectItemInternal(Item); } })">
@if (ListBox.Multiple)
{
<div class="rz-chkbox ">

View File

@@ -4,35 +4,46 @@
{
<div @ref="@Element" @attributes="Attributes" class="@GetCssClass()" style="@Style" id="@GetId()">
<div class="rz-form">
<div class="row form-group">
<label class="col-sm-3 col-form-label" for="username">@UserText</label>
<div class="col">
<RadzenTextBox AutoComplete=@AutoComplete style="display: block" Name="Username" @bind-Value=@Username />
<RadzenRequiredValidator Component="Username" Text=@UserRequired style="position: absolute" />
<div class="rz-form-row">
<label class="rz-label" for=@Id("username")>@UserText</label>
<div class="rz-form-input-wrapper">
<RadzenTextBox AutoComplete=@AutoComplete id=@Id("username") Name="Username" @bind-Value=@username />
<RadzenRequiredValidator Component="Username" Text=@UserRequired />
</div>
</div>
<div class="row form-group">
<label class="col-sm-3 col-form-label" for="password">@PasswordText</label>
<div class="col">
<RadzenPassword AutoComplete=@AutoComplete style="display: block" Name="Password" @bind-Value=@Password />
<RadzenRequiredValidator Component="Password" Text=@PasswordRequired style="position: absolute" />
<div class="rz-form-row">
<label class="rz-label" for=@Id("password")>@PasswordText</label>
<div class="rz-form-input-wrapper">
<RadzenPassword id=@Id("password") AutoComplete=@AutoComplete Name="Password" @bind-Value=@password />
<RadzenRequiredValidator Component="Password" Text=@PasswordRequired />
</div>
</div>
<div class="row form-group">
<div class="offset-sm-3 col login-buttons">
@if (AllowRememberMe)
{
<div class="rz-form-row">
<label class="rz-label"></label>
<div class="rz-form-input-wrapper">
<RadzenSwitch @bind-Value="@rememberMe" id=@Id("rememberMe") />
<label class="rz-label" for=@Id("rememberme")>@RememberMeText</label>
</div>
</div>
}
<div class="rz-form-row">
<label class="rz-label"></label>
<div class="rz-form-input-wrapper rz-login-buttons">
<RadzenButton ButtonStyle="ButtonStyle.Primary" ButtonType="ButtonType.Submit" Text=@LoginText Click=@OnLogin />
@if (AllowResetPassword)
{
<a @onclick=@OnReset>@ResetPasswordText</a>
<a class="rz-link" @onclick=@OnReset>@ResetPasswordText</a>
}
</div>
</div>
</div>
@if (AllowRegister)
{
<div class="register">
<div class="rz-register">
@RegisterMessageText
<RadzenButton ButtonType="ButtonType.Button" ButtonStyle="ButtonStyle.Secondary" Text=@RegisterText Click=@OnRegister />
<RadzenButton ButtonType="ButtonType.Button" Variant="Variant.Flat" ButtonStyle="ButtonStyle.Secondary" Shade="Shade.Lighter" Text=@RegisterText Click=@OnRegister />
</div>
}
</div>

View File

@@ -20,12 +20,12 @@ namespace Radzen.Blazor
/// {
/// Console.WriteLine($"{name} -> Username: {args.Username} and password: {args.Password}");
/// }
///
///
/// void OnRegister(string name)
/// {
/// Console.WriteLine($"{name} -> Register");
/// }
///
///
/// void OnResetPassword(string value, string name)
/// {
/// Console.WriteLine($"{name} -> ResetPassword for user: {value}");
@@ -45,57 +45,36 @@ namespace Radzen.Blazor
/// <inheritdoc />
protected override string GetComponentCssClass()
{
return "login";
return "rz-login";
}
string _username;
string username;
/// <summary>
/// Gets or sets the username.
/// </summary>
/// <value>The username.</value>
[Parameter]
public string Username
{
get
{
return _username;
}
set
{
if (_username != value)
{
_username = value;
}
}
}
public string Username { get; set; }
string _password;
string password;
/// <summary>
/// Gets or sets the password.
/// </summary>
/// <value>The password.</value>
[Parameter]
public string Password
{
get
{
return _password;
}
set
{
if (_password != value)
{
_password = value;
}
}
}
public string Password { get; set; }
private bool rememberMe;
/// <summary> Sets the initial value of the remember me switch.</summary>
[Parameter]
public bool RememberMe { get; set; }
/// <summary>
/// Gets or sets the login callback.
/// </summary>
/// <value>The login callback.</value>
[Parameter]
public EventCallback<Radzen.LoginArgs> Login { get; set; }
public EventCallback<LoginArgs> Login { get; set; }
/// <summary>
/// Gets or sets the register callback.
@@ -118,6 +97,12 @@ namespace Radzen.Blazor
[Parameter]
public bool AllowRegister { get; set; } = true;
/// <summary>
/// Asks the user whether to remember their credentials. Set to <c>false</c> by default.
/// </summary>
[Parameter]
public bool AllowRememberMe { get; set; }
/// <summary>
/// Gets or sets a value indicating whether reset password is allowed.
/// </summary>
@@ -139,6 +124,10 @@ namespace Radzen.Blazor
[Parameter]
public string RegisterText { get; set; } = "Sign up";
/// <summary> Gets or sets the remember me text.</summary>
[Parameter]
public string RememberMeText { get; set; } = "Remember me";
/// <summary>
/// Gets or sets the register message text.
/// </summary>
@@ -151,7 +140,7 @@ namespace Radzen.Blazor
/// </summary>
/// <value>The reset password text.</value>
[Parameter]
public string ResetPasswordText { get; set; } = "Forgot password";
public string ResetPasswordText { get; set; } = "Forgot password?";
/// <summary>
/// Gets or sets the user text.
@@ -186,12 +175,47 @@ namespace Radzen.Blazor
/// </summary>
protected async Task OnLogin()
{
if (!string.IsNullOrEmpty(Username) && !string.IsNullOrEmpty(Password))
if (!string.IsNullOrEmpty(username) && !string.IsNullOrEmpty(password))
{
await Login.InvokeAsync(new Radzen.LoginArgs { Username = Username, Password = Password });
await Login.InvokeAsync(new LoginArgs { Username = username, Password = password, RememberMe = rememberMe });
}
}
private string Id(string name)
{
return $"{GetId()}-{name}";
}
/// <inheritdoc />
protected override void OnInitialized()
{
username = Username;
password = Password;
rememberMe = RememberMe;
base.OnInitialized();
}
/// <inheritdoc />
public override async Task SetParametersAsync(ParameterView parameters)
{
if (parameters.DidParameterChange(nameof(Username), Username))
{
username = Username;
}
if (parameters.DidParameterChange(nameof(Password), Password))
{
password = Password;
}
if (parameters.DidParameterChange(nameof(RememberMe), RememberMe))
{
rememberMe = RememberMe;
}
await base.SetParametersAsync(parameters);
}
/// <summary>
/// Handles the <see cref="E:Reset" /> event.
/// </summary>

View File

@@ -5,7 +5,7 @@
@inherits FormComponent<string>
@if (Visible)
{
<input @ref="@Element" disabled="@Disabled" readonly="@ReadOnly" name="@Name" style="@Style" @attributes="Attributes" class="@GetCssClass()" tabindex="@TabIndex"
<input @ref="@Element" disabled="@Disabled" readonly="@ReadOnly" name="@Name" style="@Style" @attributes="Attributes" class="@GetCssClass()" tabindex="@(Disabled ? "-1" : $"{TabIndex}")"
placeholder="@Placeholder" maxlength="@MaxLength" autocomplete="@(AutoComplete ? "on" : "off")" value="@Value" @onchange="@OnChange" id="@GetId()"
oninput="Radzen.mask('@GetId()', '@Mask', '@Pattern', '@CharacterPattern')"/>
}

View File

@@ -4,12 +4,12 @@
{
var classes = GetMessageCssClasses();
<div class="rz-notification-message rz-growl " style="width: 250px;z-index: 1002;position:static;@Style">
<div aria-live="polite" class="rz-growl-item-container rz-state-highlight @classes.Item1">
<div class="rz-notification-message rz-growl " style="width: 250px;z-index: 1002;position:static;@(Message.Click != null || Message.CloseOnClick ? "cursor: pointer;" : "") @Style">
<div aria-live="polite" class="rz-growl-item-container rz-state-highlight @classes.Item1">
<div class="rz-growl-item">
<div class="rz-growl-icon-close rzi rzi-times" @onclick="@Close" style="cursor:pointer"></div>
<span class="rz-growl-image rzi @classes.Item2"></span>
<div class="rz-growl-message">
<span class="rz-growl-image rzi @classes.Item2" @onclick="NotificationClicked"></span>
<div class="rz-growl-message" @onclick="NotificationClicked">
<span class="rz-growl-title">@((MarkupString)Message.Summary)</span>
<p>@((MarkupString)Message.Detail)</p>
</div>
@@ -19,46 +19,54 @@
</div>
}
@code {
Tuple<string, string> GetMessageCssClasses()
{
if (Message.Severity == NotificationSeverity.Error)
{
return new Tuple<string, string>("rz-growl-message-error", "rzi-times");
}
else if (Message.Severity == NotificationSeverity.Info)
{
return new Tuple<string, string>("rz-growl-message-info", "rzi-info-circle");
}
else if (Message.Severity == NotificationSeverity.Success)
{
return new Tuple<string, string>("rz-growl-message-success", "rzi-check");
}
else if (Message.Severity == NotificationSeverity.Warning)
{
return new Tuple<string, string>("rz-growl-message-warn", "rzi-exclamation-triangle");
}
Tuple<string, string> GetMessageCssClasses()
{
if (Message.Severity == NotificationSeverity.Error)
{
return new Tuple<string, string>("rz-growl-message-error", "rzi-times");
}
else if (Message.Severity == NotificationSeverity.Info)
{
return new Tuple<string, string>("rz-growl-message-info", "rzi-info-circle");
}
else if (Message.Severity == NotificationSeverity.Success)
{
return new Tuple<string, string>("rz-growl-message-success", "rzi-check");
}
else if (Message.Severity == NotificationSeverity.Warning)
{
return new Tuple<string, string>("rz-growl-message-warn", "rzi-exclamation-triangle");
}
return new Tuple<string, string>("", "");
}
return new Tuple<string, string>("", "");
}
[Inject] private NotificationService Service { get; set; }
[Inject] private NotificationService Service { get; set; }
public bool Visible { get; set; } = true;
public bool Visible { get; set; } = true;
[Parameter]
public NotificationMessage Message { get; set; }
[Parameter]
public NotificationMessage Message { get; set; }
[Parameter]
public string Style { get; set; }
[Parameter]
public string Style { get; set; }
public void Close()
{
Service.Messages.Remove(Message);
System.Threading.Tasks.Task.Delay(0).ContinueWith(r => { Visible = false; });
}
public void Close()
{
Service.Messages.Remove(Message);
System.Threading.Tasks.Task.Delay(0).ContinueWith(r => { Visible = false; });
}
protected override void OnInitialized()
{
System.Threading.Tasks.Task.Delay(Convert.ToInt32(Message.Duration ?? 3000)).ContinueWith(r => InvokeAsync(Close));
}
protected override void OnInitialized()
{
System.Threading.Tasks.Task.Delay(Convert.ToInt32(Message.Duration ?? 3000)).ContinueWith(r => InvokeAsync(Close));
}
private void NotificationClicked()
{
if (Message.CloseOnClick)
Close();
Message?.Click?.Invoke(Message);
}
}

View File

@@ -8,7 +8,7 @@
{
<span @ref="@Element" style="@Style" @attributes="Attributes" class="@GetCssClass()" id="@GetId()">
<input @ref="@input" type="text" inputmode="decimal" name="@Name" disabled="@Disabled" readonly="@ReadOnly"
class="rz-spinner-input rz-inputtext" tabindex="@TabIndex"
class="@GetInputCssClass()" tabindex="@(Disabled ? "-1" : $"{TabIndex}")"
placeholder="@Placeholder" autocomplete="@(AutoComplete ? "on" : "off")" value="@FormattedValue" @onchange="@OnChange"
onkeypress="Radzen.numericKeyPress(event, @IsInteger().ToString().ToLower())"
onblur="@getOnInput()" onpaste="@getOnPaste()" />

View File

@@ -1,5 +1,6 @@
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using Radzen.Blazor.Rendering;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -26,7 +27,16 @@ namespace Radzen.Blazor
/// <inheritdoc />
protected override string GetComponentCssClass()
{
return GetClassList("rz-spinner").ToString();
return GetClassList("rz-spinner")
.Add($"rz-text-align-{Enum.GetName(typeof(TextAlign), TextAlign).ToLower()}")
.ToString();
}
string GetInputCssClass()
{
return GetClassList("rz-spinner-input")
.Add("rz-inputtext")
.ToString();
}
private string getOnInput()
@@ -178,7 +188,7 @@ namespace Radzen.Blazor
/// </summary>
/// <value><c>true</c> if input automatic complete is enabled; otherwise, <c>false</c>.</value>
[Parameter]
public bool AutoComplete { get; set; } = true;
public bool AutoComplete { get; set; } = false;
/// <summary>
/// Gets or sets a value indicating whether up down buttons are shown.
@@ -187,6 +197,13 @@ namespace Radzen.Blazor
[Parameter]
public bool ShowUpDown { get; set; } = true;
/// <summary>
/// Gets or sets the text align.
/// </summary>
/// <value>The text align.</value>
[Parameter]
public TextAlign TextAlign { get; set; } = TextAlign.Left;
/// <summary>
/// Handles the <see cref="E:Change" /> event.
/// </summary>
@@ -218,7 +235,15 @@ namespace Radzen.Blazor
newValue = default(TValue);
}
decimal? newValueAsDecimal = newValue == null ? default(decimal?) : (decimal)ConvertType.ChangeType(newValue, typeof(decimal));
decimal? newValueAsDecimal;
try
{
newValueAsDecimal = newValue == null ? default(decimal?) : (decimal)ConvertType.ChangeType(newValue, typeof(decimal));
}
catch
{
newValueAsDecimal = default(TValue) == null ? default(decimal?) : (decimal)ConvertType.ChangeType(default(TValue), typeof(decimal));
}
if (object.Equals(Value, newValue) && (!ValueChanged.HasDelegate || !string.IsNullOrEmpty(Format)))
{
@@ -288,7 +313,6 @@ namespace Radzen.Blazor
}
}
#if NET5_0_OR_GREATER
/// <summary>
/// Sets the focus on the input element.

View File

@@ -233,7 +233,7 @@ namespace Radzen.Blazor
/// <returns>System.Int32.</returns>
protected int GetPage()
{
return (int)Math.Floor((decimal)(skip / (PageSize > 0 ? PageSize : 10)));
return skip / (PageSize > 0 ? PageSize : 10);
}
/// <summary>

View File

@@ -96,7 +96,7 @@ namespace Radzen.Blazor
async System.Threading.Tasks.Task Toggle()
{
expanded = !expanded;
await ExpandedChanged.InvokeAsync(Expanded);
await ExpandedChanged.InvokeAsync(expanded);
StateHasChanged();
}

View File

@@ -5,5 +5,5 @@
@if (Visible)
{
<input @ref="@Element" name="@Name" disabled="@Disabled" readonly="@ReadOnly" style="@Style" type="password" @attributes="Attributes" class="@GetCssClass()"
placeholder="@Placeholder" autocomplete="@(AutoComplete ? "on" : "new-password")" value="@Value" @onchange="@OnChange" tabindex="@TabIndex" id="@GetId()"/>
placeholder="@Placeholder" autocomplete="@(AutoComplete ? "on" : "new-password")" value="@Value" @onchange="@OnChange" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" id="@GetId()"/>
}

View File

@@ -8,7 +8,16 @@
<div class="rz-progressbar-value rz-progressbar-value-animate" style="@($"width: {Math.Min(Value / Max * 100, 100).ToInvariantString()}%;")"></div>
@if (ShowValue)
{
<div class="rz-progressbar-label">@Value@Unit</div>
<div class="rz-progressbar-label">
@if(Template != null)
{
@Template
}
else
{
@Value@Unit
}
</div>
}
</div>
}

View File

@@ -37,6 +37,13 @@ namespace Radzen.Blazor
return string.Join(" ", classList);
}
/// <summary>
/// Gets or sets the template.
/// </summary>
/// <value>The template.</value>
[Parameter]
public RenderFragment Template { get; set; }
/// <summary>
/// Gets or sets the mode.
/// </summary>

View File

@@ -18,7 +18,7 @@
@foreach (var item in allItems.Where(i => i.Visible))
{
<div class="rz-radio-btn" @onclick="@(args => SelectItem(item))" @attributes="item.Attributes" style="@item.Style">
<div class="rz-radiobutton" @onkeypress="@(async args => { if (args.Code == "Space") { await SelectItem(item); } })" tabindex="@TabIndex">
<div class="rz-radiobutton" @onkeypress="@(async args => { if (args.Code == "Space") { await SelectItem(item); } })" tabindex="@(Disabled || item.Disabled ? "-1" : $"{TabIndex}")">
<div class="rz-helper-hidden-accessible">
<input type="radio" disabled="@Disabled" name="@Name" value="@item.Value" tabindex="-1">
</div>

View File

@@ -6,7 +6,7 @@
<div @ref="@Element" @attributes="Attributes" class="@GetCssClass()" id="@GetId()">
@if (!ReadOnly)
{
<a href="javascript:void(0)" class="rz-rating-cancel" tabindex="@TabIndex" @onclick="@(args => SetValue(0))" @onkeypress="@(async args => { if (args.Code == "Space") { await SetValue(0); } })">
<a href="javascript:void(0)" class="rz-rating-cancel" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" @onclick="@(args => SetValue(0))" @onkeypress="@(async args => { if (args.Code == "Space") { await SetValue(0); } })">
<span class="rz-rating-icon rzi rzi-ban"></span>
</a>
}
@@ -15,13 +15,13 @@
@if (index <= Value)
{
<a href="javascript:void(0)" tabindex="@TabIndex" @onclick="@(args => SetValue(index))" @onkeypress="@(async args => { if (args.Code == "Space") { await SetValue(index); } })">
<a href="javascript:void(0)" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" @onclick="@(args => SetValue(index))" @onkeypress="@(async args => { if (args.Code == "Space") { await SetValue(index); } })">
<span class="rz-rating-icon rzi rzi-star"></span>
</a>
}
else
{
<a href="javascript:void(0)" tabindex="@TabIndex" @onclick="@(args => SetValue(index))" @onkeypress="@(async args => { if (args.Code == "Space") { await SetValue(index); } })">
<a href="javascript:void(0)" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" @onclick="@(args => SetValue(index))" @onkeypress="@(async args => { if (args.Code == "Space") { await SetValue(index); } })">
<span class="rz-rating-icon rzi rzi-star-o"></span>
</a>
}

View File

@@ -10,6 +10,6 @@
@if (Visible)
{
<div @ref="@Element" style="@Style" @attributes="Attributes" class="@GetCssClass()" id="@GetId()">
<iframe frameborder="0" src="@ReportUrl"></iframe>
<iframe frameborder="0" src="@ReportUrl" @onload=OnLoad></iframe>
</div>
}

View File

@@ -1,6 +1,8 @@
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Radzen.Blazor
{
@@ -101,5 +103,17 @@ namespace Radzen.Blazor
{
return "ssrsviewer";
}
/// <summary>
/// Gets or sets the load callback.
/// </summary>
/// <value>The load callback.</value>
[Parameter]
public EventCallback<ProgressEventArgs> Load { get; set; }
async Task OnLoad(ProgressEventArgs args)
{
await Load.InvokeAsync(args);
}
}
}

View File

@@ -23,7 +23,7 @@
<div class="rz-scheduler-nav-views">
@foreach (var view in Views)
{
<button class="@($"rz-button{(IsSelected(view)? " rz-state-active" : "")}")" @onclick=@(args => OnChangeView(view))><RadzenIcon Icon=@view.Icon /><span>@view.Text</span></button>
<RadzenButton Click=@(args => OnChangeView(view)) Icon=@view.Icon Text=@view.Text class="@($"{(IsSelected(view)? " rz-state-active" : "")}")" />
}
</div>
</div>

View File

@@ -16,7 +16,7 @@
{
<div @ref="@Element" style="@Style" @attributes="Attributes" class="@GetCssClass()" id="@GetId()">
@foreach (var item in allItems.Where(i => i.Visible))
{<div @onclick="@(args => SelectItem(item))" @onkeypress="@(async args => { if (args.Code == "Space") { await SelectItem(item); } })" @attributes="item.Attributes" style="@item.Style"
class=@ButtonClassList(item) aria-label="@item.Text" tabindex="@TabIndex"><span class="rz-button-text">@item.Text</span></div>}
{<div @ref="@item.Element" id="@item.GetItemId()" @onclick="@(args => SelectItem(item))" @onkeypress="@(async args => { if (args.Code == "Space") { await SelectItem(item); } })" @attributes="item.Attributes" style="@item.Style"
class=@ButtonClassList(item) aria-label="@item.Text" tabindex="@(Disabled || item.Disabled ? "-1" : $"{TabIndex}")">@if(item.Template != null){ @item.Template(item)}else{@if (!string.IsNullOrEmpty(item.Icon)){<i class="rzi rz-navigation-item-icon" style="margin-right:2px;">@((MarkupString)item.Icon)</i>}@if (!string.IsNullOrEmpty(item.Image)){<img class="rz-navigation-item-icon" src="@item.Image" style="@item.ImageStyle"/>}<span class="rz-button-text">@item.Text</span>}</div>}
</div>
}

View File

@@ -27,9 +27,22 @@ namespace Radzen.Blazor
/// </example>
public partial class RadzenSelectBar<TValue> : FormComponent<TValue>, IRadzenSelectBar
{
ClassList ButtonClassList(RadzenSelectBarItem item) => ClassList.Create("rz-button rz-button-text-only")
private string getButtonSize()
{
return Size == ButtonSize.Medium ? "md" : Size == ButtonSize.Large ? "lg" : Size == ButtonSize.Small ? "sm" : "xs";
}
/// <summary>
/// Gets or sets the size.
/// </summary>
/// <value>The size.</value>
[Parameter]
public ButtonSize Size { get; set; } = ButtonSize.Medium;
ClassList ButtonClassList(RadzenSelectBarItem item) => ClassList.Create($"rz-button rz-button-{getButtonSize()} rz-button-text-only")
.Add("rz-state-active", IsSelected(item))
.AddDisabled(Disabled);
.AddDisabled(Disabled || item.Disabled);
/// <summary>
/// Gets or sets the value property.
@@ -168,7 +181,7 @@ namespace Radzen.Blazor
/// <param name="item">The item.</param>
protected async System.Threading.Tasks.Task SelectItem(RadzenSelectBarItem item)
{
if (Disabled)
if (Disabled || item.Disabled)
return;
if (Multiple)
@@ -200,4 +213,4 @@ namespace Radzen.Blazor
StateHasChanged();
}
}
}
}

View File

@@ -7,6 +7,34 @@ namespace Radzen.Blazor
/// </summary>
public class RadzenSelectBarItem : RadzenComponent
{
/// <summary>
/// Gets or sets the template.
/// </summary>
/// <value>The template.</value>
[Parameter]
public RenderFragment<RadzenSelectBarItem> Template { get; set; }
/// <summary>
/// Gets or sets the icon.
/// </summary>
/// <value>The icon.</value>
[Parameter]
public string Icon { get; set; }
/// <summary>
/// Gets or sets the image.
/// </summary>
/// <value>The image.</value>
[Parameter]
public string Image { get; set; }
/// <summary>
/// Gets or sets the image style.
/// </summary>
/// <value>The image style.</value>
[Parameter]
public string ImageStyle { get; set; }
/// <summary>
/// Gets or sets the text.
/// </summary>
@@ -21,6 +49,13 @@ namespace Radzen.Blazor
[Parameter]
public object Value { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this <see cref="RadzenSelectBarItem"/> is disabled.
/// </summary>
/// <value><c>true</c> if disabled; otherwise, <c>false</c>.</value>
[Parameter]
public bool Disabled { get; set; }
IRadzenSelectBar _selectBar;
/// <summary>
@@ -62,5 +97,10 @@ namespace Radzen.Blazor
{
Value = value;
}
internal string GetItemId()
{
return GetId();
}
}
}

View File

@@ -27,7 +27,7 @@ namespace Radzen.Blazor
/// <inheritdoc />
protected override string GetComponentCssClass()
{
return "sidebar-toggle";
return "rz-sidebar-toggle";
}
}
}

View File

@@ -1,6 +1,7 @@
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.JSInterop;
using System;
namespace Radzen.Blazor
{
@@ -20,6 +21,11 @@ namespace Radzen.Blazor
/// </example>
public partial class RadzenSplitButton : RadzenComponentWithChildren
{
private string getButtonSize()
{
return Size == ButtonSize.Medium ? "md" : Size == ButtonSize.Large ? "lg" : Size == ButtonSize.Small ? "sm" : "xs";
}
/// <summary>
/// Gets or sets the text.
/// </summary>
@@ -41,6 +47,34 @@ namespace Radzen.Blazor
[Parameter]
public string Image { get; set; }
/// <summary>
/// Gets or sets the button style.
/// </summary>
/// <value>The button style.</value>
[Parameter]
public ButtonStyle ButtonStyle { get; set; } = ButtonStyle.Primary;
/// <summary>
/// Gets or sets the design variant of the button.
/// </summary>
/// <value>The variant of the button.</value>
[Parameter]
public Variant Variant { get; set; } = Variant.Filled;
/// <summary>
/// Gets or sets the color shade of the button.
/// </summary>
/// <value>The color shade of the button.</value>
[Parameter]
public Shade Shade { get; set; } = Shade.Default;
/// <summary>
/// Gets or sets the size.
/// </summary>
/// <value>The size.</value>
[Parameter]
public ButtonSize Size { get; set; } = ButtonSize.Medium;
/// <summary>
/// Gets or sets a value indicating whether this <see cref="RadzenSplitButton"/> is disabled.
/// </summary>
@@ -63,6 +97,7 @@ namespace Radzen.Blazor
{
if (!Disabled)
{
await JSRuntime.InvokeVoidAsync("Radzen.closePopup", PopupID);
await Click.InvokeAsync(null);
}
}
@@ -89,12 +124,12 @@ namespace Radzen.Blazor
private string getButtonCss()
{
return $"rz-button rz-button-text-icon-left{(Disabled ? " rz-state-disabled" : "")}";
return $"rz-button rz-button-{getButtonSize()} rz-variant-{Enum.GetName(typeof(Variant), Variant).ToLowerInvariant()} rz-{Enum.GetName(typeof(ButtonStyle), ButtonStyle).ToLowerInvariant()} rz-shade-{Enum.GetName(typeof(Shade), Shade).ToLowerInvariant()} {(Disabled ? " rz-state-disabled" : "")}{(string.IsNullOrEmpty(Text) && !string.IsNullOrEmpty(Icon) ? " rz-button-icon-only" : "")}";
}
private string getPopupButtonCss()
{
return $"rz-splitbutton-menubutton rz-button rz-button-icon-only{(Disabled ? " rz-state-disabled" : "")}";
return $"rz-splitbutton-menubutton rz-button rz-button-icon-only rz-button-{getButtonSize()} rz-variant-{Enum.GetName(typeof(Variant), Variant).ToLowerInvariant()} rz-{Enum.GetName(typeof(ButtonStyle), ButtonStyle).ToLowerInvariant()} rz-shade-{Enum.GetName(typeof(Shade), Shade).ToLowerInvariant()}{(Disabled ? " rz-state-disabled" : "")}";
}
private string OpenPopupScript()

View File

@@ -4,7 +4,7 @@
@if (Visible)
{
<div id="@GetId()" class="@GetComponentCssClass()" style="flex-basis: @Size; @Style" data-index="@Index">
<div id="@GetId()" @attributes="Attributes" class="@GetComponentCssClass()" style="flex-basis: @Size; @Style" data-index="@Index">
@ChildContent
</div>

View File

@@ -4,7 +4,7 @@
@if (Visible)
{
<div @ref="@Element" @attributes="Attributes" class="@GetCssClass()" id="@GetId()"
@onclick="@Toggle" @onkeypress="@(async (args) => { if (args.Code == "Space") { await Toggle(); } })" style="outline: 0 none;@Style" tabindex="@TabIndex">
@onclick="@Toggle" @onkeypress="@(async (args) => { if (args.Code == "Space") { await Toggle(); } })" style="outline: 0 none;@Style" tabindex="@(Disabled ? "-1" : $"{TabIndex}")">
<div class="rz-helper-hidden-accessible">
<input type="checkbox" name="@Name" value="@Value" tabindex="-1">
</div>

View File

@@ -24,7 +24,7 @@ namespace Radzen.Blazor
/// {
/// public string Email { get; set; }
/// }
///
///
/// Model model = new Model();
/// }
/// </code>
@@ -74,12 +74,12 @@ namespace Radzen.Blazor
/// {
/// public string Email { get; set; }
/// }
///
///
/// Model model = new Model();
///
/// void OnSubmit(Model value)
/// {
///
///
/// }
/// }
/// </code>
@@ -118,12 +118,12 @@ namespace Radzen.Blazor
/// {
/// public string Email { get; set; }
/// }
///
///
/// Model model = new Model();
///
/// void OnInvalidSubmit(FormInvalidSubmitEventArgs args)
/// {
///
///
/// }
/// }
/// </code>
@@ -240,6 +240,12 @@ namespace Radzen.Blazor
}
}
/// <inheritdoc />
protected override string GetComponentCssClass()
{
return "rz-form";
}
/// <inheritdoc />
protected override void BuildRenderTree(RenderTreeBuilder builder)
{

264
Radzen.Blazor/RadzenText.cs Normal file
View File

@@ -0,0 +1,264 @@
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
using Radzen.Blazor.Rendering;
namespace Radzen.Blazor
{
public enum TextStyle
{
DisplayH1,
DisplayH2,
DisplayH3,
DisplayH4,
DisplayH5,
DisplayH6,
H1,
H2,
H3,
H4,
H5,
H6,
Subtitle1,
Subtitle2,
Body1,
Body2,
Button,
Caption,
Overline
}
public enum TagName
{
Div,
Span,
P,
H1,
H2,
H3,
H4,
H5,
H6,
A,
Button,
Pre,
Auto
}
/// <summary>
/// A component which displays text or makup with predefined styling.
/// </summary>
/// <example>
/// <code>
/// &lt;RadzenText TextStyle="TextStyle.H1"&gt;
/// Hello World
/// &lt;/RadzenText&gt;
/// </code>
/// </example>
public class RadzenText : RadzenComponent
{
/// <summary>
/// The text that will be displayed.
/// </summary>
[Parameter]
public string Text { get; set; }
/// <summary>
/// The child content (markup) that will be displayed. Setting the <see cref="Text"/> property will override it.
/// </summary>
[Parameter]
public RenderFragment ChildContent { get; set; }
/// <summary>
/// The style of the text. Set to <see cref="TextStyle.Body1"/> by default.
/// </summary>
[Parameter]
public TextStyle TextStyle { get; set; } = TextStyle.Body1;
/// <summary>
/// The horozontal alignment of the text.
/// </summary>
[Parameter]
public TextAlign TextAlign { get; set;} = TextAlign.Left;
/// <summary>
/// The tag name of the element that will be rendered. Set to <see cref="TagName.Auto"/> which uses a default tag name depending on the current <see cref="TextStyle" />.
/// </summary>
[Parameter]
public TagName TagName { get; set; } = TagName.Auto;
/// <inheritdoc />
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
var tagName = "span";
var className = "";
var alignClassName = "";
switch (TextStyle)
{
case TextStyle.DisplayH1:
tagName = "h1";
className = "rz-text-display-h1";
break;
case TextStyle.DisplayH2:
tagName = "h2";
className = "rz-text-display-h2";
break;
case TextStyle.DisplayH3:
tagName = "h3";
className = "rz-text-display-h3";
break;
case TextStyle.DisplayH4:
tagName = "h4";
className = "rz-text-display-h4";
break;
case TextStyle.DisplayH5:
tagName = "h5";
className = "rz-text-display-h5";
break;
case TextStyle.DisplayH6:
tagName = "h6";
className = "rz-text-display-h6";
break;
case TextStyle.H1:
tagName = "h1";
className = "rz-text-h1";
break;
case TextStyle.H2:
tagName = "h2";
className = "rz-text-h2";
break;
case TextStyle.H3:
tagName = "h3";
className = "rz-text-h3";
break;
case TextStyle.H4:
tagName = "h4";
className = "rz-text-h4";
break;
case TextStyle.H5:
tagName = "h5";
className = "rz-text-h5";
break;
case TextStyle.H6:
tagName = "h6";
className = "rz-text-h6";
break;
case TextStyle.Subtitle1:
tagName = "h6";
className = "rz-text-subtitle1";
break;
case TextStyle.Subtitle2:
tagName = "h6";
className = "rz-text-subtitle2";
break;
case TextStyle.Body1:
tagName = "p";
className = "rz-text-body1";
break;
case TextStyle.Body2:
tagName = "p";
className = "rz-text-body2";
break;
case TextStyle.Button:
tagName = "span";
className = "rz-text-button";
break;
case TextStyle.Caption:
tagName = "span";
className = "rz-text-caption";
break;
case TextStyle.Overline:
tagName = "span";
className = "rz-text-overline";
break;
}
switch (TextAlign)
{
case TextAlign.Center:
alignClassName = "rz-text-align-center";
break;
case TextAlign.End:
alignClassName = "rz-text-align-end";
break;
case TextAlign.Justify:
alignClassName = "rz-text-align-justify";
break;
case TextAlign.Start:
alignClassName = "rz-text-align-start";
break;
case TextAlign.Left:
alignClassName = "rz-text-align-left";
break;
case TextAlign.Right:
alignClassName = "rz-text-align-right";
break;
case TextAlign.JustifyAll:
alignClassName = "rz-text-align-justify-all";
break;
}
switch (TagName)
{
case TagName.Div:
tagName = "div";
break;
case TagName.Span:
tagName = "span";
break;
case TagName.P:
tagName = "p";
break;
case TagName.H1:
tagName = "h1";
break;
case TagName.H2:
tagName = "h2";
break;
case TagName.H3:
tagName = "h3";
break;
case TagName.H4:
tagName = "h4";
break;
case TagName.H5:
tagName = "h5";
break;
case TagName.H6:
tagName = "h6";
break;
case TagName.A:
tagName = "a";
break;
case TagName.Button:
tagName = "button";
break;
case TagName.Pre:
tagName = "pre";
break;
}
var classList = ClassList.Create(className)
.Add(Attributes)
.Add(alignClassName, TextAlign != TextAlign.Left);
if (Visible)
{
builder.OpenElement(0, tagName);
builder.AddAttribute(1, "style", Style);
builder.AddMultipleAttributes(2, Attributes);
builder.AddAttribute(3, "class", classList.ToString());
if (!string.IsNullOrEmpty(Text))
{
builder.AddContent(4, Text);
}
else
{
builder.AddContent(4, ChildContent);
}
builder.AddElementReferenceCapture(5, capture => Element = capture);
builder.CloseElement();
}
}
}
}

View File

@@ -4,5 +4,5 @@
@if (Visible)
{
<textarea @ref="@Element" disabled="@Disabled" readonly="@ReadOnly" name="@Name" rows="@Rows" cols="@Cols" style="@Style" @attributes="Attributes" class="@GetCssClass()"
placeholder="@Placeholder" maxlength="@MaxLength" value="@Value" @onchange="@OnChange" tabindex="@TabIndex" id="@GetId()"></textarea>
placeholder="@Placeholder" maxlength="@MaxLength" value="@Value" @onchange="@OnChange" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" id="@GetId()"></textarea>
}

View File

@@ -1,6 +1,6 @@
@inherits FormComponent<string>
@if (Visible)
{
<input @ref="@Element" disabled="@Disabled" readonly="@ReadOnly" name="@Name" style="@Style" @attributes="Attributes" class="@GetCssClass()" tabindex="@TabIndex"
<input @ref="@Element" disabled="@Disabled" readonly="@ReadOnly" name="@Name" style="@Style" @attributes="Attributes" class="@GetCssClass()" tabindex="@(Disabled ? "-1" : $"{TabIndex}")"
placeholder="@Placeholder" maxlength="@MaxLength" autocomplete="@(AutoComplete ? "on" : "off")" value="@Value" @onchange="@OnChange" id="@GetId()" />
}

View File

@@ -13,9 +13,9 @@
</div>
}
else if (tooltip.Options.ChildContent != null)
{
@tooltip.Options.ChildContent(Service)
}
{
@tooltip.Options.ChildContent(Service)
}
</div>
</div>
}
@@ -46,8 +46,10 @@
await JSRuntime.InvokeVoidAsync("Radzen.openTooltip",
tooltip.Element,
UniqueID,
tooltip.Options.Delay,
tooltip.Options.Duration,
Enum.GetName(typeof(TooltipPosition), tooltip.Options.Position).ToLowerInvariant());
Enum.GetName(typeof(TooltipPosition), tooltip.Options.Position).ToLowerInvariant(),
tooltip.Options.CloseTooltipOnDocumentClick);
}
}
@@ -56,6 +58,49 @@
protected override async Task OnAfterRenderAsync(bool firstRender)
{
IsJSRuntimeAvailable = true;
var tooltip = tooltips.LastOrDefault();
if (tooltip != null)
{
await JSRuntime.InvokeVoidAsync("Radzen.openTooltip",
tooltip.Element,
UniqueID,
tooltip.Options.Delay,
tooltip.Options.Duration,
Enum.GetName(typeof(TooltipPosition), tooltip.Options.Position).ToLowerInvariant(),
tooltip.Options.CloseTooltipOnDocumentClick,
Reference,
"RadzenTooltip.CloseTooltip");
}
}
private DotNetObjectReference<RadzenTooltip> reference;
/// <summary>
/// Gets the reference for the current component.
/// </summary>
/// <value>The reference.</value>
protected DotNetObjectReference<RadzenTooltip> Reference
{
get
{
if (reference == null)
{
reference = DotNetObjectReference.Create(this);
}
return reference;
}
}
/// <summary>
/// Closes this instance.
/// </summary>
[JSInvokable("RadzenTooltip.CloseTooltip")]
public void CloseTooltip()
{
Service.Close();
}
public async Task Close()
@@ -72,6 +117,9 @@
public void Dispose()
{
reference?.Dispose();
reference = null;
if (IsJSRuntimeAvailable)
{
try

View File

@@ -101,6 +101,12 @@ namespace Radzen.Blazor
[Parameter]
public EventCallback<TreeExpandEventArgs> Expand { get; set; }
/// <summary>
/// A callback that will be invoked when the user collapse an item.
/// </summary>
[Parameter]
public EventCallback<TreeEventArgs> Collapse { get; set; }
/// <summary>
/// Gets or sets the child content.
/// </summary>
@@ -235,6 +241,10 @@ namespace Radzen.Blazor
builder.AddAttribute(7, "ChildContent", RenderChildren(grandChildren, depth + 1));
builder.AddAttribute(8, nameof(RadzenTreeItem.Data), grandChildren);
}
else
{
builder.AddAttribute(7, "ChildContent", (RenderFragment)null);
}
}
builder.CloseComponent();

View File

@@ -9,7 +9,7 @@
}
@if(Tree != null && Tree.AllowCheckBoxes)
{
<RadzenCheckBox TValue="bool?" Value="@IsChecked()" Change="@CheckedChange" Style="@(ParentItem != null && !HasChildren ? "margin-left:25px;margin-right:5px;" : "margin-right:5px;")" />
<RadzenCheckBox TValue="bool?" Value="@IsChecked()" Change="@CheckedChange" />
}
@if (Template != null)
{

View File

@@ -120,6 +120,23 @@ namespace Radzen.Blazor
if (expanded)
{
clientExpanded = !clientExpanded;
if (clientExpanded)
{
await Expand();
}
else
{
if (Tree != null)
{
await Tree.Collapse.InvokeAsync(new TreeEventArgs()
{
Text = Text,
Value = Value
});
}
}
return;
}
@@ -128,20 +145,25 @@ namespace Radzen.Blazor
if (expanded)
{
if (Tree != null)
await Expand();
}
}
async Task Expand()
{
if (Tree != null)
{
await Tree.ExpandItem(this);
if (Tree.SingleExpand)
{
await Tree.ExpandItem(this);
var siblings = ParentItem?.items ?? Tree.items;
if (Tree.SingleExpand)
foreach (var sibling in siblings)
{
var siblings = ParentItem?.items ?? Tree.items;
foreach (var sibling in siblings)
if (sibling != this && sibling.expanded)
{
if (sibling != this && sibling.expanded)
{
await sibling.Toggle();
}
await sibling.Toggle();
}
}
}
@@ -202,9 +224,13 @@ namespace Radzen.Blazor
if (parameters.DidParameterChange(nameof(Expanded), Expanded))
{
// The Expanded property has changed - update the expanded state
expanded = parameters.GetValueOrDefault<bool>(nameof(Expanded));
clientExpanded = expanded;
shouldExpand = true;
var e = parameters.GetValueOrDefault<bool>(nameof(Expanded));
if (expanded != e)
{
expanded = e;
clientExpanded = expanded;
shouldExpand = expanded;
}
}
if (parameters.DidParameterChange(nameof(Value), Value))
@@ -236,20 +262,18 @@ namespace Radzen.Blazor
{
if (Tree != null)
{
var checkedValues = GetCheckedValues();
if (Tree.AllowCheckChildren)
{
if (value == true)
{
var valueAndChildren = GetValueAndAllChildValues();
checkedValues = checkedValues.Union(valueAndChildren);
await Tree.SetCheckedValues(GetCheckedValues().Union(valueAndChildren));
Tree.SetUncheckedValues(Tree.UncheckedValues.Except(valueAndChildren));
}
else
{
var valueAndChildren = GetValueAndAllChildValues();
checkedValues = checkedValues.Except(valueAndChildren);
await Tree.SetCheckedValues(GetCheckedValues().Except(valueAndChildren));
Tree.SetUncheckedValues(valueAndChildren.Union(Tree.UncheckedValues));
}
}
@@ -258,23 +282,21 @@ namespace Radzen.Blazor
if (value == true)
{
var valueWithoutChildren = new[] { Value };
checkedValues = checkedValues.Union(valueWithoutChildren);
await Tree.SetCheckedValues(GetCheckedValues().Union(valueWithoutChildren));
Tree.SetUncheckedValues(Tree.UncheckedValues.Except(valueWithoutChildren));
}
else
{
var valueWithoutChildren = new[] { Value };
checkedValues = checkedValues.Except(valueWithoutChildren);
await Tree.SetCheckedValues(GetCheckedValues().Except(valueWithoutChildren));
Tree.SetUncheckedValues(valueWithoutChildren.Union(Tree.UncheckedValues));
}
}
if (Tree.AllowCheckParents)
{
checkedValues = UpdateCheckedValuesWithParents(checkedValues, value);
await UpdateCheckedValuesWithParents(value);
}
await Tree.SetCheckedValues(checkedValues);
}
}
@@ -331,24 +353,22 @@ namespace Radzen.Blazor
return GetAllChildValues().Any(i => checkedValues.Contains(i));
}
IEnumerable<object> UpdateCheckedValuesWithParents(IEnumerable<object> checkedValues, bool? value)
async Task UpdateCheckedValuesWithParents(bool? value)
{
var p = ParentItem;
while (p != null)
{
if (value == false && p.AreAllChildrenUnchecked(i => !object.Equals(i, Value)))
{
checkedValues = checkedValues.Except(new object[] { p.Value });
await Tree.SetCheckedValues(GetCheckedValues().Except(new object[] { p.Value }));
}
else if (value == true && p.AreAllChildrenChecked(i => !object.Equals(i, Value)))
{
checkedValues = checkedValues.Union(new object[] { p.Value });
await Tree.SetCheckedValues(GetCheckedValues().Union(new object[] { p.Value }));
}
p = p.ParentItem;
}
return checkedValues;
}
internal bool Contains(RadzenTreeItem child)

View File

@@ -10,7 +10,7 @@
<div class="rz-fileupload-buttonbar">
<span class="@ChooseClassList">
<input id="@Id" @ref="@fileUpload" type="file" multiple="@Multiple" accept="@Accept" disabled="@Disabled"
onchange="Radzen.uploadInputChange(event, '@Url', @Auto.ToString().ToLower(), @Multiple.ToString().ToLower(), true)" />
onchange="Radzen.uploadInputChange(event, '@Url', @Auto.ToString().ToLower(), @Multiple.ToString().ToLower(), true, '@ParameterName')" />
@if (!string.IsNullOrEmpty(Icon))
{
<i class="rzi">@((MarkupString)Icon)</i>

View File

@@ -73,6 +73,13 @@ namespace Radzen.Blazor
[Parameter]
public string Url { get; set; }
/// <summary>
/// Gets or sets the parameter name. If not set 'file' parameter name will be used for single file and 'files' for multiple files.
/// </summary>
/// <value>The parameter name.</value>
[Parameter]
public string ParameterName { get; set; }
/// <summary>
/// Gets or sets the accepted MIME types.
/// </summary>
@@ -112,7 +119,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 btn-light")
ClassList ButtonClassList => ClassList.Create("rz-button rz-button-icon-only rz-light")
.AddDisabled(Disabled);
/// <summary>
@@ -127,7 +134,7 @@ namespace Radzen.Blazor
/// </summary>
public async Task Upload()
{
await JSRuntime.InvokeAsync<string>("Radzen.upload", fileUpload, Url, Multiple);
await JSRuntime.InvokeAsync<string>("Radzen.upload", fileUpload, Url, Multiple, false, ParameterName);
}
readonly IDictionary<string, string> headers = new Dictionary<string, string>();

View File

@@ -9,7 +9,7 @@
var appointments = Scheduler.GetAppointmentsInRange(StartDate, EndDate).ToList();
return @<CascadingValue Value=@Scheduler>
<WeekView MinutesPerSlot=@MinutesPerSlot StartDate=@StartDate EndDate=@EndDate StartTime=@StartTime EndTime=@EndTime Appointments=@appointments TimeFormat="@TimeFormat" />
<WeekView HeaderFormat=@HeaderFormat MinutesPerSlot=@MinutesPerSlot StartDate=@StartDate EndDate=@EndDate StartTime=@StartTime EndTime=@EndTime Appointments=@appointments TimeFormat="@TimeFormat" />
</CascadingValue>;
}
}

View File

@@ -28,6 +28,13 @@ namespace Radzen.Blazor
[Parameter]
public string TimeFormat { get; set; } = "h tt";
/// <summary>
/// Gets or sets the format used to display the header text.
/// </summary>
/// <value>The header text format. Set to <c>ddd</c> by default.</value>
[Parameter]
public string HeaderFormat { get; set; } = "ddd";
/// <summary>
/// Gets or sets the start time.
/// </summary>

View File

@@ -67,6 +67,21 @@ namespace Radzen.Blazor.Rendering
return this;
}
/// <summary>
/// Adds the specified attributes.
/// </summary>
/// <param name="attributes">The attributes.</param>
/// <returns>ClassList.</returns>
public ClassList Add(IReadOnlyDictionary<string, object> attributes)
{
if (attributes != null && attributes.TryGetValue("class", out var className) && className != null)
{
return Add(className.ToString());
}
return this;
}
/// <summary>
/// Adds the specified field.
/// </summary>

View File

@@ -3,7 +3,7 @@
@inject IJSRuntime JSRuntime
@implements IDisposable
<div class="rz-dialog-wrapper">
<div @ref="dialog" class="rz-dialog" role="dialog" aria-labelledby="rz-dialog-0-label" style=@Style>
<div @ref="dialog" class="@CssClass" role="dialog" aria-labelledby="rz-dialog-0-label" style=@Style>
@if (Dialog.Options.ShowTitle)
{
@if (Dialog.Options.Draggable)
@@ -49,11 +49,11 @@
{
@if (Dialog.Options.CloseDialogOnOverlayClick)
{
<div @onclick="@Close" class="rz-dialog-mask" style="z-index: 1000;"></div>
<div @onclick="@Close" class="rz-dialog-mask"></div>
}
else
{
<div class="rz-dialog-mask" style="z-index: 1000;"></div>
<div class="rz-dialog-mask"></div>
}
}
@@ -125,11 +125,20 @@
Service.Close();
}
string CssClass
{
get
{
var baseCss = "rz-dialog";
return string.IsNullOrEmpty(Dialog.Options.CssClass) ? baseCss : $"{baseCss} {Dialog.Options.CssClass}";
}
}
string Style
{
get
{
var baseStyle = "min-width: 150px; min-height: 150px; z-index: 1001; opacity: 1;position:absolute;";
var baseStyle = "";
var widthStyle = !string.IsNullOrEmpty(width) ? width : string.IsNullOrEmpty(Dialog.Options.Width) ? "" : $"width: {Dialog.Options.Width};";
var heightStyle = !string.IsNullOrEmpty(height) ? height : string.IsNullOrEmpty(Dialog.Options.Height) ? "" : $"height: {Dialog.Options.Height};";
var topStyle = !string.IsNullOrEmpty(top) ? top : string.IsNullOrEmpty(Dialog.Options.Top) ? "" : $"top: {Dialog.Options.Top};";

View File

@@ -65,7 +65,7 @@
var left = slotIndex * slotWidth;
var top = 1.5 * (MaxAppointmentsInSlot + 1);
var listDate = start;
<a class="rz-event-list-btn" style="top: @(top.ToInvariantString())em; left: @(left.ToInvariantString())%" @onclick=@(args => OnListClick(listDate, appointments))>@String.Format(MoreText, excessCount)</a>
<a class="rz-event-list-btn" style="top: @(top.ToInvariantString())rem; left: @(left.ToInvariantString())%" @onclick=@(args => OnListClick(listDate, appointments))>@String.Format(MoreText, excessCount)</a>
}
}
</div>

View File

@@ -1,8 +1,39 @@
<path class="@Class" d="@D" stroke-linecap="@StrokeLineCap" fill="@Fill" stroke="@Stroke" stroke-width="@StrokeWidth.ToInvariantString()" stroke-dasharray="@StrokeDashArray" style="@Style"></path>
@using System.Text
<path class="@Class" d="@D" stroke-linecap="@StrokeLineCap" stroke-dasharray="@StrokeDashArray" style="@CurrentStyle()"></path>
@code {
[Parameter]
public string Style { get; set; }
private string CurrentStyle()
{
var style = new StringBuilder();
if (Stroke != null)
{
style.Append($"stroke: {Stroke};");
}
if (Fill != null)
{
style.Append($"fill: {Fill};");
}
if (StrokeWidth != null)
{
style.Append($"stroke-width: {StrokeWidth.ToInvariantString()};");
}
if (Style != null)
{
foreach (var value in Style.Split(';'))
{
style.Append(value);
}
}
return style.ToString();
}
[Parameter]
public string D { get; set; }

Some files were not shown because too many files have changed in this diff Show More