Compare commits

...

247 Commits

Author SHA1 Message Date
Vladimir Enchev
c6ce339d40 DataGrid column MinWidth property added 2022-02-11 08:37:36 +02:00
Vladimir Enchev
5a90b00e19 Version updated 2022-02-11 08:27:34 +02:00
Atanas Korchev
e6bf8b5321 Add Responsive property to RadzenSidebar. 2022-02-10 16:35:20 +02:00
Atanas Korchev
156e493a90 Invoke own StateHasChanged when the Refresh method of DialogService is called. Fixes #363. 2022-02-10 15:43:35 +02:00
Vladimir Enchev
2cf073495c version updated 2022-02-10 14:33:11 +02:00
Vladimir Enchev
43b193e965 DropDown and DropDownDataGrid multiple selected items label fixed 2022-02-10 14:32:51 +02:00
yordanov
b4b8dfb217 Fix light button colors 2022-02-10 12:12:57 +02:00
Vladimir Enchev
99051af886 DataGrid Column Picker added
Based on https://github.com/radzenhq/radzen-blazor/pull/344
2022-02-10 10:58:09 +02:00
Vladimir Enchev
768926fec3 code fixed 2022-02-10 10:48:37 +02:00
yordanov
a73042abc1 Update RadzenGrid simple filtering UI 2022-02-09 18:29:48 +02:00
Vladimir Enchev
da36e3c1fa IJSRuntime param added 2022-02-09 13:59:17 +02:00
Vladimir Enchev
0024e3e74d Version updated 2022-02-09 10:58:30 +02:00
yordanov
9b14caf300 Delete commented styles 2022-02-09 10:55:16 +02:00
yordanov
adee153190 Update UI for simple mode filtering 2022-02-09 10:55:16 +02:00
Vladimir Enchev
c476cd7f25 Fixed #366 2022-02-09 10:30:00 +02:00
Vladimir Enchev
d4da6b02a8 LengthValidator not not notified when DropDownDataGrid value is selected 2022-02-08 11:10:41 +02:00
yordanov
1d3f651846 Add rz-body css class 2022-02-07 14:51:45 +02:00
yordanov
d6af0ffc95 Set translateZ to rz-body 2022-02-07 14:50:05 +02:00
yordanov
c1ba96d395 Add min-width to Pager's page buttons 2022-02-07 14:18:19 +02:00
Vladimir Enchev
52f53e3410 DropDownDataGrid EmptyTemplate added
Fix #359
2022-02-07 10:51:41 +02:00
Vladimir Enchev
aba4875cf3 version updated 2022-02-04 15:00:10 +02:00
Vladimir Enchev
f5057c2ac7 Revert fix for #339 2022-02-04 14:59:58 +02:00
Marc Mauri
cfd5558765 Reset Password shall throw event with an empty username (#360)
Co-authored-by: Marc Mauri <marc@kaizenforpharma.com>
2022-02-04 09:37:59 +02:00
Vladimir Enchev
77bbeb6de0 version updated 2022-02-03 13:32:25 +02:00
Vladimir Enchev
bf3e22bf4c DropDown, DropDownDataGrid and ListBox Value binding improved 2022-02-03 13:29:23 +02:00
Vladimir Enchev
a5596ac8f6 CheckBox typo fixed 2022-02-03 11:23:14 +02:00
Vladimir Enchev
a3dddfa7f8 DataGrid GroupRowExpand/GroupRowCollapse events added 2022-02-01 22:09:14 +02:00
Vladimir Enchev
922abe8ba3 DataGrid IsNull/IsNotNull filtering not working properly on columns bound to string property 2022-02-01 21:58:09 +02:00
Vladimir Enchev
9b85f8673c DialogService Confirm AutoFocusFirstElement support added 2022-02-01 21:46:01 +02:00
Vladimir Enchev
b8e0bf92c2 DataGrid simple filtering should respect column FormatString or DataGrid FilterDateFormat
Close #279
2022-02-01 09:59:07 +02:00
Vladimir Enchev
05c7adbfee Version updated 2022-01-31 14:51:36 +02:00
Benjamin Vertonghen
4081802dc8 FIX: Menu in DataGrid shows incorrectly due to z-index (#356)
* FIX: Menu in DataGrid

* rz-navigation-menu z-index lowered from 20 to 2

Co-authored-by: Vladimir Enchev <vladimir.enchev@gmail.com>
2022-01-31 14:50:54 +02:00
Benjamin Vertonghen
45fb1cd801 Click on MenuItem (#354) 2022-01-31 12:21:10 +02:00
Vladimir Enchev
50ed4a6988 DataGrid header cell sorting outline border removed
We will try to provide better focus styles in our themes
2022-01-31 09:46:37 +02:00
Carsten Heinrich
96997e95a0 Enable sorting on RadzenDataGrid by keyboard (#351)
to increase the accessibility it is necassary to sort the RadzenDataGrid by keyboard

Co-authored-by: Carsten Heinrich <carsten.heinrich@t-systems.com>
2022-01-31 09:45:06 +02:00
Carsten Heinrich
9029a64a19 Insert additional header-attribute "aria-sort" so that the screen reader recognizes the sorting. (#358)
Co-authored-by: Carsten Heinrich <carsten.heinrich@t-systems.com>
2022-01-31 09:28:28 +02:00
Vladimir Enchev
cb6c9dd374 DataGrid cells colspan made recursive 2022-01-30 12:44:40 +02:00
Vladimir Enchev
5b1e9d3f16 DataGrid colspan fixed with multiple composite columns 2022-01-29 09:18:06 +02:00
Vladimir Enchev
ceb1f954ff DataGrid SecondFIlterValue not set to null on Reset() 2022-01-28 19:18:30 +02:00
Atanas Korchev
f67e4f953f DataGrid has gaps on desktop browsers in responsive mode. 2022-01-28 12:49:35 +02:00
Vladimir Enchev
76c071da14 FileInput ImageClick event added 2022-01-28 10:00:53 +02:00
Vladimir Enchev
c8dafae31d Version updated 2022-01-27 09:28:17 +02:00
Vladimir Enchev
1924056c02 Sidebar expand logic improved (#352)
* Add Sidebar expand and collapse CSS classes

* Initialize Expanded on load.

* Introduce RadzenMediaQuery.

* Use addListener instead of addEventListener to support older browsers.

* Fix redraw under WebKit

Co-authored-by: yordanov <vasil@yordanov.info>
Co-authored-by: Atanas Korchev <akorchev@gmail.com>
2022-01-27 09:26:25 +02:00
Vladimir Enchev
257dd22345 DataGrid grouping will not apply sorting if GroupDescriptor SortOrder is null 2022-01-27 09:22:24 +02:00
Vladimir Enchev
4211259874 Dialog bottom option setting fixed 2022-01-26 19:59:44 +02:00
Vladimir Enchev
9fa7d0182d Menu and ProfileMenu items should be over DataGrid header 2022-01-26 15:00:45 +02:00
Vladimir Enchev
8a00736c8f Frozen composite columns disabled
until we find a way to calculate properly left for frozen cells in composite columns
2022-01-26 13:47:36 +02:00
Vladimir Enchev
f1fd6b6d8b DataGrid composite columns colspan logic fixed 2022-01-25 20:03:07 +02:00
Ben Gavin
b1adad5866 FIX: Close popup when 'Tab'ing from control (#349)
FIX: Styling/layout fixes for validated control

Co-authored-by: Ben Gavin <ben.gavin@corebts.com>
2022-01-25 09:37:27 +02:00
Vladimir Enchev
f8aaa21b39 categories marked as updated 2022-01-24 14:35:53 +02:00
Vladimir Enchev
6b207e29fc Various demos marked as updated 2022-01-24 14:27:39 +02:00
Vladimir Enchev
4effb7cfdd Merge branch 'master' of https://github.com/radzenhq/radzen-blazor 2022-01-24 13:53:33 +02:00
Vladimir Enchev
83f48ac009 version updated 2022-01-24 13:53:24 +02:00
acordts
6788612ab5 add tabnavigation tabindex depending on disabled flag (#347)
Co-authored-by: Albrecht Ziegler-Cordts <albrecht.ziegler-cordts@t-systems.com>
2022-01-24 13:52:12 +02:00
Vladimir Enchev
8329c38894 DataGrid GroupRowRender event added 2022-01-24 11:26:11 +02:00
Vladimir Enchev
5e96f69c52 FileInput keyboard navigation improved 2022-01-24 09:30:18 +02:00
Atanas Korchev
f4c6b4f08d Always build SASS. 2022-01-21 11:47:36 +02:00
Vladimir Enchev
95fef77042 DataGrid AllowRowSelectOnRowClick property added (#341)
* DataGrid AllowRowSelectOnRowClick property added

* AllowRowSelectOnRowClick comment fixed

* DataGridMultipleSelection demo improved
2022-01-21 09:41:08 +02:00
pigwing
9814f44ead added missing PageSizeText parameter (#340) 2022-01-21 09:34:48 +02:00
Vladimir Enchev
13189c6c6c DataGrid header not working properly with bootstrap modal
Fix #339
2022-01-21 09:33:17 +02:00
Vladimir Enchev
aed16dfec6 version and demo updated 2022-01-20 16:17:45 +02:00
Vladimir Enchev
3167399da9 DataGridPagerHorizontalAlign fixed 2022-01-20 15:59:12 +02:00
Vladimir Enchev
c6b77fe861 version updated 2022-01-20 15:38:36 +02:00
yordanov
aa1e4ecb7d Update pager horizontal align in demos 2022-01-20 15:35:17 +02:00
yordanov
1b677770b6 Add Datagrid pager horizontal align demo page 2022-01-20 15:35:17 +02:00
Vladimir Enchev
c707f20b3f DataGrid, DataList and DropDownDataGrid PagerHorizontalAlign and PagerAlwaysVisible properties added 2022-01-20 15:35:17 +02:00
Vladimir Enchev
c368e065b6 Pager HorizontalAlign property added 2022-01-20 15:35:17 +02:00
yordanov
90eab0573f Add page size description text to Pager 2022-01-20 15:35:17 +02:00
yordanov
35d7286eec Add styles for Pager horizontal alignment modes 2022-01-20 15:35:17 +02:00
Vladimir Enchev
b68fe58a23 Revert: Fixed DataGrid template row cell not spanned on all columns 2022-01-20 15:07:59 +02:00
Vladimir Enchev
ea133a96cd Fixed DataGrid template row cell not spanned on all columns 2022-01-20 15:02:24 +02:00
Vladimir Enchev
69e48c77a9 Composite Columns marked as new, Columns as updated 2022-01-20 14:46:21 +02:00
Vladimir Enchev
606fb38ae6 Version updated 2022-01-20 13:27:45 +02:00
Vladimir Enchev
b29955d191 DataGrid AllowCompositeDataCells property added 2022-01-20 13:27:10 +02:00
Vladimir Enchev
7539fb3699 DataGrid thead fixed to not scroll vertically 2022-01-20 12:48:05 +02:00
Vladimir Enchev
2d8911947a DataGrid composite column cells right border fixed 2022-01-20 12:05:41 +02:00
Vladimir Enchev
2044042973 DataGridCompositeColumns source fixed 2022-01-20 10:11:15 +02:00
Vladimir Enchev
dd02f890c2 Sorting and filtering disabled for DataGridConditionalTemplate 2022-01-20 09:23:55 +02:00
Vladimir Enchev
45ca2eaaca Version updated 2022-01-20 09:18:47 +02:00
Atanas Korchev
aaf535c33f RadzenPanelMenu always highlights an item with Path set to "/". 2022-01-20 08:57:35 +02:00
Vladimir Enchev
e9c6da2c11 DataGrid simple filter header cell tabindex="1" removed 2022-01-19 14:41:51 +02:00
Atanas Korchev
e2c8efe29f Do not dispose if the timer is null. 2022-01-19 14:28:35 +02:00
Vladimir Enchev
e76b789eb7 DataGrid composite columns support added (#334)
* composite columns

* headers cells render reworked

* composite columns render reworked again

* footer cells support added for composite columns

* code improved

* Row details template expand fixed

* Group, resize and reorder disabled for composite columns

* composite columns demo improved
2022-01-19 13:31:17 +02:00
Vladimir Enchev
75d1431e50 DataGrid GroupDescriptor SortOrder property added. Column SortOrder will be used when grouping. 2022-01-18 21:05:26 +02:00
yordanov
8a9da8a3ae Style badge for new and updated demos 2022-01-18 11:13:01 +02:00
Atanas Korchev
3b718b0461 Top level navigation items can have a badge too. 2022-01-18 10:24:16 +02:00
Atanas Korchev
65b0d1fc23 Navigation items support badges. 2022-01-18 10:13:13 +02:00
Atanas Korchev
c56ed37f7a Remove scrollToBottom. 2022-01-18 09:54:43 +02:00
Vladimir Enchev
340754d062 Merge branch 'master' of https://github.com/radzenhq/radzen-blazor 2022-01-18 09:50:21 +02:00
Vladimir Enchev
db85c34e61 DataGrid will render rows when binding using LoadData if paging is disabled and no Count set 2022-01-18 09:49:35 +02:00
Atanas Korchev
807995fe8b Use PageTitle and HeadContent. Find nested examples. 2022-01-18 09:41:22 +02:00
Atanas Korchev
111120edaa Allow the developer to set the slot size in day and week view of RadzenScheduler. 2022-01-17 09:11:07 +02:00
Vladimir Enchev
0bac8d6ae3 Pager AlwaysVisible and DataGrid PagerAlwaysVisible properties added
Close #319
2022-01-17 09:05:49 +02:00
yordanov
2ba17d8d5b Update copyright year 2022-01-14 11:38:44 +02:00
yordanov
a61633194d Update copyright year 2022-01-14 11:31:26 +02:00
yordanov
caa86bb931 Update copyright year 2022-01-14 11:27:52 +02:00
Vladimir Enchev
cfe08bc542 Version updated 2022-01-13 09:07:11 +02:00
yordanov
4e55742219 Separate Upload Choose button styles from btn-secondary styles 2022-01-12 17:23:41 +02:00
Vladimir Enchev
f98ed62045 Fix #330 2022-01-12 13:23:11 +02:00
Vladimir Enchev
03653fb653 Various components item remove improved to check if component is disposed 2022-01-12 11:11:10 +02:00
Vladimir Enchev
240a89da2c DatePicker input name attribute missing 2022-01-12 10:40:34 +02:00
Vladimir Enchev
cfacd05578 Themes SASS with LibSassBuilder instead WebCompiler (#332)
* Use LibSassBuilder instead of WebCompiler.

* Remove dotnet-tools.json.

* Remove logging.

* Build SASS only once.

Co-authored-by: Atanas Korchev <akorchev@gmail.com>
2022-01-12 10:23:32 +02:00
Vladimir Enchev
c0ab5f955d Fixed #322 2022-01-11 11:54:52 +02:00
Atanas Korchev
f2346c5709 HtmlEditor does not allow pasting of plain text. 2022-01-11 09:20:32 +02:00
Vladimir Enchev
798bfc964c Version updated 2022-01-10 10:32:46 +02:00
Marco Papst
2af9014962 Add IconStyle Property to RadzenIcon (#324) 2022-01-10 10:11:14 +02:00
GioeEng
f8759278bc Fixes (#315)
* New splitter component

* New Splitter component

* Fixed code style and naming conventions

* themes implemented

* Splitter: Error in icon representation. Incorrect design compromised panel behavior

* 0

* Rename variables

Co-authored-by: lorenzo <lorenzo.muccioli@car-tech.com>
Co-authored-by: Vladimir Enchev <vladimir.enchev@gmail.com>
Co-authored-by: Vasil Yordanov <vasil@yordanov.info>
2022-01-07 12:22:37 +02:00
Lukas Grützmacher
abed1b0645 Wrap EmptyText in DataGrid (#323) 2022-01-07 09:27:14 +02:00
Vladimir Enchev
8999fc8fd6 Fixed RadzenNumeric error with unsigned integer types 2022-01-07 09:26:15 +02:00
Vladimir Enchev
a1f9db4114 Allow MarkupString to be used in Dialog Title 2022-01-07 09:20:53 +02:00
Vladimir Enchev
2336f1dc79 version updated 2022-01-06 09:32:54 +02:00
Atanas Korchev
335e177578 CheckBox uses click instead of mouseup. 2022-01-05 19:27:44 +02:00
Vladimir Enchev
a4434b16de DataGrid grouping support when virtualizing IQueryable 2022-01-05 10:46:48 +02:00
Vladimir Enchev
9b3624e818 Click on disabled date should not close the DatePicker
Fix #320
2022-01-04 09:53:35 +02:00
Vladimir Enchev
120a95f94d DataGrid will sort by grouped column 2022-01-04 08:57:40 +02:00
Atanas Korchev
db0a658be2 Cannot set the width of RadzenSplitButton. 2022-01-04 08:43:56 +02:00
yordanov
822a8afcb1 Add responsive styles to documentation-link 2021-12-30 16:11:18 +02:00
yordanov
eed371130f Rename link to component's docs 2021-12-30 16:11:18 +02:00
Vladimir Enchev
dd19c1040c Version updated 2021-12-30 09:25:10 +02:00
yordanov
54130e5ee7 Add responsive styles and icons to Scheduler nav views 2021-12-29 12:34:11 +02:00
Vladimir Enchev
827128d048 Slider will not calculate step properly when Min is set 2021-12-28 13:11:21 +02:00
Atanas Korchev
26c18562c4 PanelMenu matches URL which contain "-". Fixes #317. 2021-12-28 12:21:38 +02:00
Vladimir Enchev
0a847c8427 Version updated 2021-12-27 09:51:00 +02:00
yordanov
27a976fc53 DatePicker add cursor pointer to choosable dates - resolves #253 2021-12-24 15:59:21 +02:00
Atanas Korchev
73a3a881ca RadzenPanelMenu supports prefix matching. 2021-12-24 15:17:44 +02:00
Atanas Korchev
f07545285b Render theme stylesheet only once. 2021-12-24 15:05:57 +02:00
Vladimir Enchev
4d02883a48 ContextMenu should not show toggle button 2021-12-24 11:34:54 +02:00
yordanov
4eb9f0a0a4 Fix validator top padding in standard theme 2021-12-24 10:40:15 +02:00
Vladimir Enchev
1f630181d7 DataGrid filtering API demo updated 2021-12-23 19:55:11 +02:00
Vladimir Enchev
71a9b79527 version updated 2021-12-23 19:47:14 +02:00
Vladimir Enchev
b32d098d3b DataGrid column filter cannot be cleared even if specified in code 2021-12-23 19:47:06 +02:00
Vladimir Enchev
9118c1d64f version updated 2021-12-23 09:24:57 +02:00
Vladimir Enchev
8e4f7b0f08 DataGrid PageSize is wrong when using PageSizeOptions and LoadData
Fix #316
2021-12-23 09:24:46 +02:00
Vladimir Enchev
3acc0592b4 DataGrid HeaderCellRender and FooterCellRender events added 2021-12-21 11:14:58 +02:00
yordanov
dc5e24201c Update DataGrid loading indicator color and animation 2021-12-21 10:21:43 +02:00
yordanov
eda8f9ac86 Set tab panel border-radius with respect to TabPosition 2021-12-20 19:53:22 +02:00
Vladimir Enchev
ed19c9c534 Version updated 2021-12-20 16:39:33 +02:00
yordanov
c0ee0195e9 Add TabPosition to Tabs demo 2021-12-20 16:33:02 +02:00
yordanov
ffa35bed94 Add TabPosition styles to Tab Component 2021-12-20 16:31:40 +02:00
yordanov
9442be13f1 Render navigation item link content wrapper when Path is null or empty 2021-12-20 15:10:14 +02:00
Vladimir Enchev
a017803429 Tree AllowCheckChildren will not work when tree children are populated from RadzenTreeLevel settings 2021-12-20 11:51:56 +02:00
Vladimir Enchev
951e88f1c8 Tab component TabPosition property added 2021-12-20 10:19:05 +02:00
Atanas Korchev
de93247c5c ProfileMenu opens behind DataGrid when RadzenLayout is used. 2021-12-19 09:40:00 +02:00
Atanas Korchev
06038bc105 Bar series render in the opposite order. 2021-12-19 09:40:00 +02:00
Vladimir Enchev
43c5975524 Fixed DatePicker will raise exception with chars in time part 2021-12-17 15:01:43 +02:00
Vladimir Enchev
891f183f80 Switch component Toggle method made public and executed on click 2021-12-17 14:51:06 +02:00
yordanov
c126c28fa3 Fix loading panel z-index in sample dashboard 2021-12-17 14:15:16 +02:00
yordanov
fc99e46e0f Update DataList demo 2021-12-17 14:03:22 +02:00
yordanov
9543e10241 Update styles in Tree demos 2021-12-16 18:39:44 +02:00
yordanov
327bc47017 Align icon in treenode label 2021-12-16 16:48:04 +02:00
Vladimir Enchev
96ccc5d4f5 Version updated 2021-12-16 08:49:19 +02:00
Atanas Korchev
eef2b4eb58 Dialog content does not always refresh when DialogService.Refresh is called. 2021-12-15 20:47:55 +02:00
yordanov
26346c8acb Fix boolean filter checkbox background in DataGird 2021-12-15 16:11:19 +02:00
yordanov
565e77ef6d Fix CheckBox tri-state icon 2021-12-15 16:10:13 +02:00
Vladimir Enchev
84506a9340 Fixed virtualized DataGrid will raise exception with FilterTemplate 2021-12-15 11:50:46 +02:00
Vladimir Enchev
25298012f9 DataGrid LoadData will not populate Filters properly 2021-12-15 11:18:05 +02:00
Atanas Korchev
236e2f6d48 Reset the scroll position of RadzenBody after navigation. 2021-12-14 16:11:10 +02:00
yordanov
483283fdd1 Add icons to component groups 2021-12-14 14:34:25 +02:00
Vladimir Enchev
776c2f38f8 Add RadzenLayout. (#312)
Co-authored-by: Atanas Korchev <akorchev@gmail.com>
2021-12-14 09:05:46 +02:00
yordanov
c20cc09959 Update layouts of feedback demos 2021-12-13 16:01:13 +02:00
yordanov
ce7d3f0324 Update layout of validator demos 2021-12-13 16:01:13 +02:00
Vladimir Enchev
55e85dbd74 version updated 2021-12-13 09:29:32 +02:00
Atanas Korchev
4c6f6d8b1c Fix typo in tree data-binding demo. 2021-12-13 08:35:16 +02:00
yordanov
651381c9d7 Style Charts configs 2021-12-10 15:53:34 +02:00
yordanov
146af5cf2d Update Upload demo layout 2021-12-10 15:40:49 +02:00
yordanov
49a7c80423 Update TextArea demo layout 2021-12-10 15:40:49 +02:00
yordanov
e770eb147a Update FileInput demo layout 2021-12-10 15:40:49 +02:00
yordanov
a08802df0a Update Fieldset demo layout 2021-12-10 15:40:49 +02:00
Atanas Korchev
61eba87de6 Do not try to parse null color. 2021-12-10 15:21:11 +02:00
Atanas Korchev
0e0a56ac38 Fixes in the tree guide. 2021-12-10 12:59:51 +02:00
Atanas Korchev
36e6c2fa25 Tree demo source tab fixes. 2021-12-10 12:59:51 +02:00
yordanov
0c157eee69 Update ColorPicker demo layout 2021-12-10 11:49:04 +02:00
yordanov
ba2ac37f6c Update DropDownDataGrid demo layout 2021-12-10 11:48:35 +02:00
yordanov
9a29db8c62 Update DropDown demo layout 2021-12-10 11:48:04 +02:00
yordanov
212ec834c8 Update DatePicker demo layout 2021-12-10 11:47:44 +02:00
Atanas Korchev
bd70d80f81 Do not add upload header without a name. 2021-12-10 09:57:30 +02:00
yordanov
55e2e3463d Format code 2021-12-09 16:46:51 +02:00
yordanov
2e16eba739 Remove typography styles for html elements from base themes 2021-12-09 16:46:51 +02:00
yordanov
35bf66ccf4 Add rz-label CSS class to RadzenLabel component 2021-12-09 16:46:51 +02:00
Vladimir Enchev
ec4679d85c Render optimizations of popups removed 2021-12-09 14:58:11 +02:00
Vladimir Enchev
15c4b0e5eb DropDownDataGrid rendering speed optimized by rendering popup on first click 2021-12-09 11:58:49 +02:00
Vladimir Enchev
5f170f0953 DataGrid rendering speed optimized by rendering advanced filter popups on first click 2021-12-09 11:40:13 +02:00
Vladimir Enchev
07a1e9311b DatePicker rendering speed optimized 2021-12-09 10:22:31 +02:00
Vladimir Enchev
7d1274af4b Version updated 2021-12-09 09:40:55 +02:00
Vladimir Enchev
9d096aed5d Tabs RenderMode.Client will cause exception on browser refresh
Fixed #309
2021-12-09 09:40:19 +02:00
yordanov
8477ad810a Update layouts in demos 2021-12-08 15:02:15 +02:00
Vladimir Enchev
60e3fb6f45 DatePicker will select wrong year when selecting days across years 2021-12-08 10:58:26 +02:00
yordanov
7efb9ec1de Update layouts in demos 2021-12-07 15:37:48 +02:00
Atanas Korchev
70c0a4b9e6 Fix smooth checkbox not working. 2021-12-07 15:26:11 +02:00
yordanov
d9b3474846 Move console below the demo 2021-12-07 10:19:31 +02:00
yordanov
97cb7fc2eb Update console styling 2021-12-07 10:19:31 +02:00
Vladimir Enchev
6394612630 xml comments warnings fixed 2021-12-06 11:35:27 +02:00
Vladimir Enchev
a78df50826 DropDownDataGrid AllowColumnResize property added 2021-12-06 11:21:42 +02:00
yordanov
59c1948e14 Update Steps demo layout 2021-12-06 11:01:47 +02:00
yordanov
e92fa3d615 Update Login page demo layout 2021-12-06 11:01:47 +02:00
Vladimir Enchev
faee5d0276 Version updated 2021-12-06 10:36:41 +02:00
Vladimir Enchev
f2b1e7becc DataGrid Responsive property added 2021-12-06 10:05:35 +02:00
yordanov
5352d55589 Update Tabs demo layout 2021-12-06 09:29:45 +02:00
yordanov
75386e55af Update Splitter demo layout 2021-12-06 09:29:45 +02:00
yordanov
fe2a28d013 Update panel demo layout 2021-12-06 09:29:45 +02:00
Vladimir Enchev
aa2e07d163 DataGrid grouping will check if the group key is null 2021-12-03 16:37:27 +02:00
yordanov
23c1c41415 Panel render text and icon wrapper only if Text or Icon are set 2021-12-03 15:50:59 +02:00
yordanov
8be6988e5b Update DataGrid demos 2021-12-03 14:57:40 +02:00
yordanov
262ccc2f11 Add instrucitons to ContextMenu demo 2021-12-03 14:57:40 +02:00
yordanov
09c3952a0a Update menu demo height 2021-12-03 14:57:40 +02:00
yordanov
ea9c4df4bc Update image demo 2021-12-03 14:57:40 +02:00
yordanov
43c95c24fe Update dialog demos 2021-12-03 14:57:40 +02:00
Vladimir Enchev
21a19dcf89 DataGrid will not go to the previous page if the last item is deleted 2021-12-03 10:45:26 +02:00
Vladimir Enchev
2b6cc3e52d DataGrid StateHasChanged will be executed after every column add 2021-12-02 16:21:59 +02:00
Vladimir Enchev
f639704d6d code removed temporary to avoid recursion 2021-12-02 16:21:37 +02:00
Vladimir Enchev
b93995081e DataGrid will not go to the first page if the last item is deleted on the second page 2021-12-02 16:11:00 +02:00
Atanas Korchev
0dc68b830c Show loading indicator in the LoadData demo. 2021-12-02 15:45:10 +02:00
Vladimir Enchev
5521b90aec DataGrid will show EmptyText/EmptyTemplate only if Count is 0 and Data is not null 2021-12-02 15:15:06 +02:00
yordanov
7f0a13b434 Make Scheduler full width 2021-12-02 13:23:49 +02:00
yordanov
c0e2445439 remove empty row in Pager demo 2021-12-02 13:23:49 +02:00
yordanov
6037b87b52 Update DataGrid column widths across demos 2021-12-02 13:23:49 +02:00
yordanov
b80c5d43e9 Update DataGrid export demo 2021-12-02 13:23:49 +02:00
yordanov
ed258e624d Update layout in cascading dropdowns DataGrid demo 2021-12-02 13:23:49 +02:00
yordanov
e1fd87b251 Update layout in DataGrid inline edit demo 2021-12-02 13:23:48 +02:00
yordanov
092cf6be4f Update DataGrid context menu demo 2021-12-02 13:19:09 +02:00
yordanov
a4286ea2de Update DataGrid master detail demos 2021-12-02 13:19:09 +02:00
yordanov
7ada2de54c Update empty DataGrid demo 2021-12-02 13:19:09 +02:00
yordanov
0f01f513eb Update DataGrid column demos 2021-12-02 13:19:09 +02:00
yordanov
4bebcec778 Reorder radzen banner buttons 2021-12-02 13:19:09 +02:00
Vladimir Enchev
6d2bf8402b demo updated 2021-12-02 09:23:47 +02:00
Vladimir Enchev
674f99d738 Firefox checks for virtualization removed 2021-12-02 09:06:41 +02:00
Roderick Micallef
f12c2d3a7c Update RadzenDataGrid.razor.cs (reordering columns issue) (#300)
* Update RadzenDataGrid.razor.cs

ColumnReorder returns oldIndex from only visible/JS columns, and newIndex from all columns. Proposal is to return indices from all columns for both cases.

* Update RadzenDataGrid.razor.cs

typo fix
2021-12-01 13:41:19 +02:00
Vladimir Enchev
8748b1e122 DataGrid and DropDown virtualization fixed to work properly in Firefox
Fix #275
2021-12-01 13:39:47 +02:00
Vladimir Enchev
b6e4206772 Merge branch 'master' of https://github.com/radzenhq/radzen-blazor 2021-12-01 10:47:22 +02:00
Vladimir Enchev
2c6224d45e Upload Disabled property added
Fix #299
2021-12-01 10:47:10 +02:00
emumanu
a0c764d87c Fixes Error: System.NotSupportedException: Unable to cast the type 'BlazorRadzenTests.Country' to type 'System.Object'. LINQ to Entities only supports casting EDM primitive or enumeration types. (#298)
In order to fix the problem, we convert the IQueryable to IEnumerable, we perform the cast to IEnumerable<object> and then we call ToList()
2021-12-01 10:38:50 +02:00
Vladimir Enchev
a1f6278711 Version updated 2021-12-01 09:18:35 +02:00
Vladimir Enchev
3ca45f4eef DataGrid IsNull/IsNotNull filtering support added 2021-11-30 11:31:52 +02:00
yordanov
07ff46b98e Update Material icons font 2021-11-29 17:19:13 +02:00
Vladimir Enchev
c73d3fd96b Fixed DataGrid simple filter popup for dates shown at wrong position 2021-11-29 13:17:17 +02:00
Vladimir Enchev
e8594d05cb DatePicker CurrentDateChanged event added 2021-11-29 10:47:11 +02:00
Vladimir Enchev
253db597bd missing articles added 2021-11-29 10:37:32 +02:00
Vladimir Enchev
8058276990 DataGrid column resizing will use integer values only 2021-11-29 10:25:27 +02:00
Vladimir Enchev
1e3f704ffd webcompiler executed directly without tool run 2021-11-29 10:06:35 +02:00
yordanov
871d470c71 Update Card template in DataList and Pager demos 2021-11-26 12:49:12 +02:00
yordanov
fd442bc08c Update spacing in icons demo 2021-11-26 12:49:12 +02:00
Vladimir Enchev
b93499e373 Version updated 2021-11-25 19:19:55 +02:00
yordanov
0a2ddc696b Update Card demo 2021-11-25 15:28:13 +02:00
Atanas Korchev
d8f4020fa8 Split Tree demos to multiple pages. 2021-11-25 12:50:45 +02:00
yordanov
cfbf2c3bed Move standard theme background gradient to <body> 2021-11-25 10:30:34 +02:00
beeterry
3aa41ed16f Added a Focus method on the RadzenNumeric control (#295)
* Added a flag to determine whether the expandable indicator column gets rendered or not.

* ShowExpandableIndicatorColumn renamed to ShowExpandColumn and RadzenDataGridRow fixed to work with the new property

* Added a focus method on the numeric control.

Co-authored-by: Vladimir Enchev <vladimir.enchev@gmail.com>
Co-authored-by: Brandon Terry <brandon@shipsilo.onmicrosoft.com>
2021-11-25 08:46:59 +02:00
Atanas Korchev
6dae186ed6 Prevent flicker on initial load. 2021-11-24 17:38:56 +02:00
232 changed files with 6167 additions and 3069 deletions

View File

@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2018-2021 Radzen Ltd
Copyright (c) 2018-2022 Radzen Ltd
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -45,5 +45,29 @@ namespace Radzen.Blazor.Tests
Assert.Contains(@$"autofocus", component.Markup);
}
[Fact]
public void Icon_Renders_IconStyleClass()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenIcon>();
component.SetParametersAndRender(parameters => parameters.Add(icon => icon.IconStyle, IconStyle.Primary));
Assert.Contains(@$"rzi-primary", component.Markup);
}
[Fact]
public void Icon_NotRenders_IconStyleClass_WhenNull()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenIcon>();
component.SetParametersAndRender(parameters => parameters.Add(icon => icon.IconStyle, null));
Assert.DoesNotContain(@$"rzi-primary", component.Markup);
}
}
}

View File

@@ -0,0 +1,98 @@
using Bunit;
using Bunit.TestDoubles;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Routing;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Xunit;
namespace Radzen.Blazor.Tests
{
public class PanelMenuTests
{
class TestNavigationManager : NavigationManager
{
public TestNavigationManager(string uri)
{
Initialize("http://www.example.com/", uri);
}
protected override void NavigateToCore(string uri, bool forceLoad)
{
}
}
private static string CreatePanelMenu(string currentAbsoluteUrl, NavLinkMatch match, params string[] urls)
{
using var ctx = new TestContext();
ctx.Services.RemoveAll<NavigationManager>();
ctx.Services.TryAddSingleton<NavigationManager>(new TestNavigationManager(currentAbsoluteUrl));
var component = ctx.RenderComponent<RadzenPanelMenu>();
component.SetParametersAndRender(parameters => parameters.Add(p => p.Match, match).AddChildContent(builder =>
{
foreach (var url in urls)
{
builder.OpenComponent<RadzenPanelMenuItem>(0);
builder.AddAttribute(1, nameof(RadzenPanelMenuItem.Path), url);
builder.CloseComponent();
}
}));
return component.Markup;
}
[Fact]
public void RadzenPanelMenu_SetsOneActiveMenuItem()
{
var component = CreatePanelMenu("http://www.example.com/datagrid-dynamic", NavLinkMatch.All, "/datagrid", "/datagrid-dynamic");
var firstIndex = component.IndexOf("rz-navigation-item-wrapper-active");
var lastIndex = component.LastIndexOf("rz-navigation-item-wrapper-active");
Assert.NotEqual(-1, firstIndex);
Assert.Equal(firstIndex, lastIndex);
}
[Fact]
public void RadzenPanelMenu_MatchesQueryStringParameters()
{
var component = CreatePanelMenu("http://www.example.com/foo?bar", NavLinkMatch.Prefix, "/foo");
Assert.Contains("rz-navigation-item-wrapper-active", component);
}
[Fact]
public void RadzenPanelMenu_DoesNotMatchQueryStringParametersWhenExactMatchIsSpecified()
{
var component = CreatePanelMenu("http://www.example.com/foo?bar", NavLinkMatch.All, "/foo");
Assert.DoesNotContain("rz-navigation-item-wrapper-active", component);
}
[Fact]
public void RadzenPanelMenu_DoesNotMatchRootWithEverything()
{
var component = CreatePanelMenu("http://www.example.com/foo", NavLinkMatch.Prefix, "/");
Assert.DoesNotContain("rz-navigation-item-wrapper-active", component);
}
[Fact]
public void RadzenPanelMenu_MatchesRoot()
{
var component = CreatePanelMenu("http://www.example.com/", NavLinkMatch.Prefix, "/");
Assert.Contains("rz-navigation-item-wrapper-active", component);
}
[Fact]
public void RadzenPanelMenu_MatchesRootWithoutTrailingSlash()
{
var component = CreatePanelMenu("http://www.example.com", NavLinkMatch.Prefix, "/");
Assert.Contains("rz-navigation-item-wrapper-active", component);
}
}
}

View File

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

View File

@@ -1,12 +0,0 @@
{
"version": 1,
"isRoot": true,
"tools": {
"excubo.webcompiler": {
"version": "2.6.0",
"commands": [
"webcompiler"
]
}
}
}

View File

@@ -217,6 +217,16 @@ namespace Radzen.Blazor
}
}
/// <summary>
/// Returns the category values
/// </summary>
protected virtual IList<object> GetCategories()
{
Func<TItem, object> category = String.IsNullOrEmpty(CategoryProperty) ? (item) => string.Empty : PropertyAccess.Getter<TItem, object>(CategoryProperty);
return Items.Select(category).ToList();
}
/// <inheritdoc />
public virtual ScaleBase TransformCategoryScale(ScaleBase scale)
{
@@ -243,10 +253,8 @@ namespace Radzen.Blazor
Output = scale.Output
};
}
Func<TItem, object> category = String.IsNullOrEmpty(CategoryProperty) ? (item) => string.Empty : PropertyAccess.Getter<TItem, object>(CategoryProperty);
var data = Items.Select(category).ToList();
var data = GetCategories();
if (scale is OrdinalScale ordinal)
{

View File

@@ -1,5 +1,6 @@
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.AspNetCore.Components.Web;
using Radzen.Blazor;
using System;
using System.Collections;
@@ -100,7 +101,7 @@ namespace Radzen
/// <summary>
/// Supplies information about a <see cref="RadzenMenu.Click" /> event that is being raised.
/// </summary>
public class MenuItemEventArgs
public class MenuItemEventArgs : MouseEventArgs
{
/// <summary>
/// Gets text of the clicked item.
@@ -150,6 +151,34 @@ namespace Radzen
public bool Expandable { get; set; }
}
/// <summary>
/// Supplies information about a <see cref="RadzenDataGrid{TItem}" /> event that is being raised.
/// </summary>
public class GroupRowRenderEventArgs
{
/// <summary>
/// Gets or sets the group row HTML attributes. They will apply to the table row (tr) element which RadzenDataGrid renders for every group row.
/// </summary>
public IDictionary<string, object> Attributes { get; private set; } = new Dictionary<string, object>();
/// <summary>
/// Gets the data item which the current row represents.
/// </summary>
public Group Group { get; internal set; }
/// <summary>
/// Gets or sets a value indicating whether this group row is expanded.
/// </summary>
/// <value><c>true</c> if expanded; otherwise, <c>false</c>.</value>
public bool? Expanded { get; set; }
/// <summary>
/// Gets a value indicating whether this is the first time the RadzenGrid has rendered.
/// </summary>
/// <value><c>true</c> if this is the first time; otherwise, <c>false</c>.</value>
public bool FirstRender { get; internal set; }
}
/// <summary>
/// Supplies information about a <see cref="RadzenGrid{TItem}.Render" /> event that is being raised.
/// </summary>
@@ -412,6 +441,29 @@ namespace Radzen
Client
}
/// <summary>
/// Specifies the ways a <see cref="RadzenTabs" /> component renders its titles.
/// </summary>
public enum TabPosition
{
/// <summary>
/// The RadzenTabs titles are displayed at the top of the component.
/// </summary>
Top,
/// <summary>
/// The RadzenTabs titles are displayed at the bottom of the component.
/// </summary>
Bottom,
/// <summary>
/// The RadzenTabs titles are displayed at the left side of the component.
/// </summary>
Left,
/// <summary>
/// The RadzenTabs titles are displayed at the right side of the component.
/// </summary>
Right
}
/// <summary>
/// Specifies the position at which a Radzen Blazor component renders its built-in <see cref="RadzenPager" />.
/// </summary>
@@ -721,7 +773,15 @@ namespace Radzen
/// <summary>
/// Satisfied if the current value does not contain the specified value.
/// </summary>
DoesNotContain
DoesNotContain,
/// <summary>
/// Satisfied if the current value is null.
/// </summary>
IsNull,
/// <summary>
/// Satisfied if the current value is not null.
/// </summary>
IsNotNull
}
/// <summary>
@@ -743,6 +803,29 @@ namespace Radzen
Center
}
/// <summary>
/// Specifies horizontal alignment.
/// </summary>
public enum HorizontalAlign
{
/// <summary>
/// Left horizontal alignment.
/// </summary>
Left,
/// <summary>
/// Right horizontal alignment.
/// </summary>
Right,
/// <summary>
/// Center horizontal alignment.
/// </summary>
Center,
/// <summary>
/// Justify horizontal alignment.
/// </summary>
Justify
}
/// <summary>
/// Specifies the display style of a <see cref="RadzenBadge" />. Affects the visual styling of RadzenBadge (background and text color).
/// </summary>
@@ -778,6 +861,41 @@ namespace Radzen
Info
}
/// <summary>
/// Specifies the display style of a <see cref="RadzenIcon" />. Affects the visual styling of RadzenIcon (Icon (text) color).
/// </summary>
public enum IconStyle
{
/// <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>
/// Success styling.
/// </summary>
Success,
/// <summary>
/// Danger styling.
/// </summary>
Danger,
/// <summary>
/// Warning styling.
/// </summary>
Warning,
/// <summary>
/// Informative styling.
/// </summary>
Info
}
/// <summary>
/// Supplies information about a <see cref="RadzenDataGrid{TItem}.ColumnResized" /> event that is being raised.
/// </summary>
@@ -894,6 +1012,13 @@ namespace Radzen
/// </summary>
/// <value>The property.</value>
public string Property { get; set; }
/// <summary>
/// Gets or sets the sort order.
/// </summary>
/// <value>The sort order.</value>
public SortOrder? SortOrder { get; set; }
/// <summary>
/// Gets or sets the title displayed in the group.
/// </summary>
@@ -1773,6 +1898,7 @@ namespace Radzen
public double NewSize { get; set; }
}
/// <inheritdoc />
public class MD5
{
/*
@@ -1807,12 +1933,14 @@ namespace Radzen
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
};
/// <inheritdoc />
public static uint leftRotate(uint x, int c)
{
return (x << c) | (x >> (32 - c));
}
// assumes whole bytes as input
/// <inheritdoc />
public static string Calculate(byte[] input)
{
uint a0 = 0x67452301; // A

View File

@@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -41,14 +42,17 @@ namespace Radzen
/// </summary>
/// <value>The URI helper.</value>
NavigationManager UriHelper { get; set; }
IJSRuntime JSRuntime { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="DialogService"/> class.
/// </summary>
/// <param name="uriHelper">The URI helper.</param>
public DialogService(NavigationManager uriHelper)
/// <param name="jsRuntime">IJSRuntime instance.</param>
public DialogService(NavigationManager uriHelper, IJSRuntime jsRuntime)
{
UriHelper = uriHelper;
JSRuntime = jsRuntime;
if (UriHelper != null)
{
@@ -171,6 +175,7 @@ namespace Radzen
Width = options != null && !string.IsNullOrEmpty(options.Width) ? options.Width : "600px",
Left = options != null && !string.IsNullOrEmpty(options.Left) ? options.Left : "",
Top = options != null && !string.IsNullOrEmpty(options.Top) ? options.Top : "",
Bottom = options != null && !string.IsNullOrEmpty(options.Bottom) ? options.Bottom : "",
Height = options != null && !string.IsNullOrEmpty(options.Height) ? options.Height : "",
ShowTitle = options != null ? options.ShowTitle : true,
ShowClose = options != null ? options.ShowClose : true,
@@ -218,53 +223,63 @@ namespace Radzen
/// <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?> Confirm(string message = "Confirm?", string title = "Confirm", ConfirmOptions options = null) => await OpenAsync(title, ds => {
RenderFragment content = b =>
{
var i = 0;
b.OpenElement(i++, "div");
b.OpenElement(i++, "p");
b.AddAttribute(i++, "style", "margin-bottom: 20px;");
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.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();
b.CloseElement();
b.CloseElement();
};
return content;
}, new DialogOptions()
public async Task<bool?> Confirm(string message = "Confirm?", string title = "Confirm", ConfirmOptions options = null)
{
Width = options != null ? !string.IsNullOrEmpty(options.Width) ? options.Width : "355px" : "355px",
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 : "",
});
var dialogOptions = new DialogOptions()
{
Width = options != null ? !string.IsNullOrEmpty(options.Width) ? options.Width : "355px" : "355px",
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,
};
await JSRuntime.InvokeAsync<string>("Radzen.openDialog", dialogOptions);
return await OpenAsync(title, ds =>
{
RenderFragment content = b =>
{
var i = 0;
b.OpenElement(i++, "div");
b.OpenElement(i++, "p");
b.AddAttribute(i++, "style", "margin-bottom: 20px;");
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.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();
b.CloseElement();
b.CloseElement();
};
return content;
}, dialogOptions);
}
}
/// <summary>

View File

@@ -35,7 +35,12 @@ namespace Radzen
var data = Data != null ? Data.Cast<object>() : Enumerable.Empty<object>();
var view = (LoadData.HasDelegate ? data : View).Cast<object>().AsQueryable();
var totalItemsCount = LoadData.HasDelegate ? Count : view.Count();
var top = Math.Min(request.Count, totalItemsCount - request.StartIndex);
var top = request.Count;
if(top <= 0)
{
top = PageSize;
}
if (LoadData.HasDelegate)
{
@@ -201,17 +206,17 @@ namespace Radzen
if (!string.IsNullOrEmpty(ValueProperty))
{
System.Reflection.PropertyInfo pi = PropertyAccess.GetElementType(Data.GetType()).GetProperty(ValueProperty);
Value = selectedItems.Select(i => PropertyAccess.GetItemOrValueFromProperty(i, ValueProperty)).AsQueryable().Cast(pi.PropertyType);
internalValue = selectedItems.Select(i => PropertyAccess.GetItemOrValueFromProperty(i, ValueProperty)).AsQueryable().Cast(pi.PropertyType);
}
else
{
var type = typeof(T).IsGenericType ? typeof(T).GetGenericArguments()[0] : typeof(T);
Value = selectedItems.AsQueryable().Cast(type);
internalValue = selectedItems.AsQueryable().Cast(type);
}
await ValueChanged.InvokeAsync((T)Value);
await ValueChanged.InvokeAsync((T)internalValue);
if (FieldIdentifier.FieldName != null) { EditContext?.NotifyFieldChanged(FieldIdentifier); }
await Change.InvokeAsync(Value);
await Change.InvokeAsync(internalValue);
StateHasChanged();
}
@@ -236,16 +241,16 @@ namespace Radzen
searchText = null;
await JSRuntime.InvokeAsync<string>("Radzen.setInputValue", search, "");
Value = default(T);
internalValue = default(T);
selectedItem = null;
selectedItems.Clear();
selectedIndex = -1;
await ValueChanged.InvokeAsync((T)Value);
await ValueChanged.InvokeAsync((T)internalValue);
if (FieldIdentifier.FieldName != null) { EditContext?.NotifyFieldChanged(FieldIdentifier); }
await Change.InvokeAsync(Value);
await Change.InvokeAsync(internalValue);
await OnFilter(new ChangeEventArgs());
@@ -281,7 +286,7 @@ namespace Radzen
selectedItems.Clear();
}
SelectItemFromValue(Value);
SelectItemFromValue(internalValue);
OnDataChanged();
@@ -571,6 +576,14 @@ namespace Radzen
return base.OnAfterRenderAsync(firstRender);
}
/// <inheritdoc />
protected override void OnInitialized()
{
internalValue = Value;
base.OnInitialized();
}
/// <summary>
/// Set parameters as an asynchronous operation.
/// </summary>
@@ -599,6 +612,11 @@ namespace Radzen
shouldClose = !visible;
}
if (parameters.DidParameterChange(nameof(Value), Value))
{
internalValue = parameters.GetValueOrDefault<object>(nameof(Value));
}
await base.SetParametersAsync(parameters);
if (shouldClose && !firstRender)
@@ -613,7 +631,7 @@ namespace Radzen
/// <returns>Task.</returns>
protected override Task OnParametersSetAsync()
{
var valueAsEnumerable = Value as IEnumerable;
var valueAsEnumerable = internalValue as IEnumerable;
if (valueAsEnumerable != null)
{
@@ -623,7 +641,7 @@ namespace Radzen
}
}
SelectItemFromValue(Value);
SelectItemFromValue(internalValue);
return base.OnParametersSetAsync();
}
@@ -634,7 +652,7 @@ namespace Radzen
/// <param name="args">The <see cref="ChangeEventArgs"/> instance containing the event data.</param>
protected void OnChange(ChangeEventArgs args)
{
Value = args.Value;
internalValue = args.Value;
}
/// <summary>
@@ -729,7 +747,7 @@ namespace Radzen
}
else
{
_view = (typeof(IQueryable).IsAssignableFrom(Data.GetType())) ? Query.Cast<object>().ToList().AsQueryable() : Query;
_view = (typeof(IQueryable).IsAssignableFrom(Data.GetType())) ? (Query as IEnumerable).Cast<object>().ToList().AsQueryable() : Query;
}
}
}
@@ -770,6 +788,8 @@ namespace Radzen
await SelectItem(item, raiseChange);
}
internal object internalValue;
/// <summary>
/// Selects the item.
/// </summary>
@@ -785,11 +805,11 @@ namespace Radzen
selectedItem = item;
if (!string.IsNullOrEmpty(ValueProperty))
{
Value = PropertyAccess.GetItemOrValueFromProperty(item, ValueProperty);
internalValue = PropertyAccess.GetItemOrValueFromProperty(item, ValueProperty);
}
else
{
Value = item;
internalValue = item;
}
SetSelectedIndexFromSelectedItem();
@@ -810,7 +830,7 @@ namespace Radzen
if (!string.IsNullOrEmpty(ValueProperty))
{
System.Reflection.PropertyInfo pi = PropertyAccess.GetElementType(Data.GetType()).GetProperty(ValueProperty);
Value = selectedItems.Select(i => PropertyAccess.GetItemOrValueFromProperty(i, ValueProperty)).AsQueryable().Cast(pi.PropertyType);
internalValue = selectedItems.Select(i => PropertyAccess.GetItemOrValueFromProperty(i, ValueProperty)).AsQueryable().Cast(pi.PropertyType);
}
else
{
@@ -818,19 +838,19 @@ namespace Radzen
var elementType = firstElement != null ? firstElement.GetType() : null;
if (elementType != null)
{
Value = selectedItems.AsQueryable().Cast(elementType);
internalValue = selectedItems.AsQueryable().Cast(elementType);
}
else
{
Value = selectedItems;
internalValue = selectedItems;
}
}
}
if (raiseChange)
{
await ValueChanged.InvokeAsync(object.Equals(Value, null) ? default(T) : (T)Value);
await ValueChanged.InvokeAsync(object.Equals(internalValue, null) ? default(T) : (T)internalValue);
if (FieldIdentifier.FieldName != null) { EditContext?.NotifyFieldChanged(FieldIdentifier); }
await Change.InvokeAsync(Value);
await Change.InvokeAsync(internalValue);
}
StateHasChanged();
}
@@ -858,7 +878,7 @@ namespace Radzen
}
else
{
selectedItem = Value;
selectedItem = internalValue;
}
SetSelectedIndexFromSelectedItem();

View File

@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2018-2021 Radzen Ltd
Copyright (c) 2018-2022 Radzen Ltd
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -21,6 +21,20 @@ namespace Radzen
[Parameter]
public PagerPosition PagerPosition { get; set; } = PagerPosition.Bottom;
/// <summary>
/// Gets or sets a value indicating whether pager is visible even when not enough data for paging.
/// </summary>
/// <value><c>true</c> if pager is visible even when not enough data for paging otherwise, <c>false</c>.</value>
[Parameter]
public bool PagerAlwaysVisible { get; set; }
/// <summary>
/// Gets or sets the horizontal align.
/// </summary>
/// <value>The horizontal align.</value>
[Parameter]
public HorizontalAlign PagerHorizontalAlign { get; set; } = HorizontalAlign.Justify;
/// <summary>
/// Gets or sets a value indicating whether paging is allowed. Set to <c>false</c> by default.
/// </summary>
@@ -28,12 +42,23 @@ namespace Radzen
[Parameter]
public bool AllowPaging { get; set; }
int _PageSize = 10;
/// <summary>
/// Gets or sets the size of the page.
/// </summary>
/// <value>The size of the page.</value>
[Parameter]
public int PageSize { get; set; } = 10;
public int PageSize
{
get
{
return pageSize ?? _PageSize;
}
set
{
_PageSize = value;
}
}
/// <summary>
/// Gets or sets the page numbers count.
@@ -93,20 +118,27 @@ namespace Radzen
/// </summary>
/// <value>The page size options.</value>
[Parameter]
public IEnumerable<int> PageSizeOptions { get; set; }
public IEnumerable<int> PageSizeOptions { get; set; }
/// <summary>
/// Gets or sets the page size description text.
/// </summary>
/// <value>The page size description text.</value>
[Parameter]
public string PageSizeText { get; set; } = "items per page";
/// <summary>
/// Gets or sets the pager summary visibility.
/// </summary>
/// <value>The pager summary visibility.</value>
[Parameter]
public bool ShowPagingSummary { get; set; } = false;
public bool ShowPagingSummary { get; set; } = false;
/// <summary>
/// Gets or sets the pager summary format.
/// </summary>
/// <value>The pager summary format.</value>
[Parameter]
/// <value>The pager summary format.</value>
[Parameter]
public string PagingSummaryFormat { get; set; } = "Page {0} of {1} ({2} items)";
/// <summary>
@@ -185,7 +217,8 @@ namespace Radzen
/// <returns>A Task representing the asynchronous operation.</returns>
public override async Task SetParametersAsync(ParameterView parameters)
{
bool pageSizeChanged = parameters.DidParameterChange(nameof(PageSize), PageSize);
bool pageSizeChanged = parameters.DidParameterChange(nameof(PageSize), PageSize) &&
PageSize != pageSize;
await base.SetParametersAsync(parameters);
@@ -259,13 +292,15 @@ namespace Radzen
await InvokeAsync(Reload);
}
int? pageSize;
/// <summary>
/// Called when [page size changed].
/// </summary>
/// <param name="value">The value.</param>
protected async Task OnPageSizeChanged(int value)
{
PageSize = value;
pageSize = value;
await InvokeAsync(Reload);
}

View File

@@ -43,7 +43,9 @@ namespace Radzen
{FilterOperator.StartsWith, "StartsWith"},
{FilterOperator.EndsWith, "EndsWith"},
{FilterOperator.Contains, "Contains"},
{FilterOperator.DoesNotContain, "DoesNotContain"}
{FilterOperator.DoesNotContain, "DoesNotContain"},
{FilterOperator.IsNull, "=="},
{FilterOperator.IsNotNull, "!="}
};
/// <summary>
@@ -60,7 +62,9 @@ namespace Radzen
{FilterOperator.StartsWith, "startswith"},
{FilterOperator.EndsWith, "endswith"},
{FilterOperator.Contains, "contains"},
{FilterOperator.DoesNotContain, "DoesNotContain"}
{FilterOperator.DoesNotContain, "DoesNotContain"},
{FilterOperator.IsNull, "eq"},
{FilterOperator.IsNotNull, "ne"}
};
/// <summary>
@@ -136,7 +140,8 @@ namespace Radzen
public static string ToFilterString<T>(this IEnumerable<RadzenDataGridColumn<T>> columns)
{
Func<RadzenDataGridColumn<T>, bool> canFilter = (c) => c.Filterable && c.FilterPropertyType != null &&
!(c.GetFilterValue() == null || c.GetFilterValue() as string == string.Empty) && c.GetFilterProperty() != null;
(!(c.GetFilterValue() == null || c.GetFilterValue() as string == string.Empty) || c.GetFilterOperator() == FilterOperator.IsNotNull || c.GetFilterOperator() == FilterOperator.IsNull)
&& c.GetFilterProperty() != null;
if (columns.Where(canFilter).Any())
{
@@ -216,7 +221,7 @@ namespace Radzen
secondValue = (string)Convert.ChangeType(column.GetSecondFilterValue(), typeof(string));
}
if (!string.IsNullOrEmpty(value))
if (!string.IsNullOrEmpty(value) || column.GetFilterOperator() == FilterOperator.IsNotNull || column.GetFilterOperator() == FilterOperator.IsNull)
{
var linqOperator = LinqFilterOperators[column.GetFilterOperator()];
if (linqOperator == null)
@@ -388,6 +393,14 @@ namespace Radzen
{
return $@"({property} == null ? """" : {property}){filterCaseSensitivityOperator} != ""{value}""{filterCaseSensitivityOperator}";
}
else if (columnFilterOperator == FilterOperator.IsNull)
{
return $@"np({property}) == null";
}
else if (columnFilterOperator == FilterOperator.IsNotNull)
{
return $@"np({property}) != null";
}
}
else if (PropertyAccess.IsNumeric(column.FilterPropertyType))
{
@@ -398,12 +411,19 @@ namespace Radzen
column.FilterPropertyType == typeof(DateTimeOffset) ||
column.FilterPropertyType == typeof(DateTimeOffset?))
{
var dateTimeValue = DateTime.Parse(value, null, System.Globalization.DateTimeStyles.RoundtripKind);
var finalDate = dateTimeValue.TimeOfDay == TimeSpan.Zero ? dateTimeValue.Date : dateTimeValue;
var dateFormat = dateTimeValue.TimeOfDay == TimeSpan.Zero ? "yyyy-MM-dd" : "yyyy-MM-ddTHH:mm:ssZ";
var dateFunction = column.FilterPropertyType == typeof(DateTimeOffset) || column.FilterPropertyType == typeof(DateTimeOffset?) ? "DateTimeOffset" : "DateTime";
if (column.GetFilterOperator() == FilterOperator.IsNull || column.GetFilterOperator() == FilterOperator.IsNotNull)
{
return $"{property} {linqOperator} null";
}
else
{
var dateTimeValue = DateTime.Parse(value, null, System.Globalization.DateTimeStyles.RoundtripKind);
var finalDate = dateTimeValue.TimeOfDay == TimeSpan.Zero ? dateTimeValue.Date : dateTimeValue;
var dateFormat = dateTimeValue.TimeOfDay == TimeSpan.Zero ? "yyyy-MM-dd" : "yyyy-MM-ddTHH:mm:ssZ";
var dateFunction = column.FilterPropertyType == typeof(DateTimeOffset) || column.FilterPropertyType == typeof(DateTimeOffset?) ? "DateTimeOffset" : "DateTime";
return $@"{property} {linqOperator} {dateFunction}(""{finalDate.ToString(dateFormat)}"")";
return $@"{property} {linqOperator} {dateFunction}(""{finalDate.ToString(dateFormat)}"")";
}
}
else if (column.FilterPropertyType == typeof(bool) || column.FilterPropertyType == typeof(bool?))
{
@@ -411,7 +431,14 @@ namespace Radzen
}
else if (column.FilterPropertyType == typeof(Guid) || column.FilterPropertyType == typeof(Guid?))
{
return $@"{property} {linqOperator} Guid(""{value}"")";
if (column.GetFilterOperator() == FilterOperator.IsNull || column.GetFilterOperator() == FilterOperator.IsNotNull)
{
return $"{property} {linqOperator} null";
}
else
{
return $@"{property} {linqOperator} Guid(""{value}"")";
}
}
return "";
@@ -516,6 +543,7 @@ namespace Radzen
var property = column.GetFilterProperty().Replace('.', '/');
var columnFilterOperator = !second ? column.GetFilterOperator() : column.GetSecondFilterOperator();
var odataFilterOperator = ODataFilterOperators[columnFilterOperator];
var value = typeof(IEnumerable).IsAssignableFrom(column.FilterPropertyType) && column.FilterPropertyType != typeof(string) ? null :
!second ? (string)Convert.ChangeType(column.GetFilterValue(), typeof(string)) :
@@ -564,6 +592,10 @@ namespace Radzen
$"{property} ne tolower('{value}')" :
$"{property} ne '{value}'";
}
else if (columnFilterOperator == FilterOperator.IsNull || columnFilterOperator == FilterOperator.IsNotNull)
{
return $"{property} {odataFilterOperator} null";
}
}
else if (typeof(IEnumerable).IsAssignableFrom(column.FilterPropertyType) && column.FilterPropertyType != typeof(string))
{
@@ -585,22 +617,36 @@ namespace Radzen
}
else if (PropertyAccess.IsNumeric(column.FilterPropertyType))
{
return $"{property} {ODataFilterOperators[columnFilterOperator]} {value}";
return $"{property} {odataFilterOperator} {value}";
}
else if (column.FilterPropertyType == typeof(bool) || column.FilterPropertyType == typeof(bool?))
{
return $"{property} eq {value.ToLower()}";
if (columnFilterOperator == FilterOperator.IsNull || columnFilterOperator == FilterOperator.IsNotNull)
{
return $"{property} {odataFilterOperator} null";
}
else
{
return $"{property} eq {value.ToLower()}";
}
}
else if (column.FilterPropertyType == typeof(DateTime) ||
column.FilterPropertyType == typeof(DateTime?) ||
column.FilterPropertyType == typeof(DateTimeOffset) ||
column.FilterPropertyType == typeof(DateTimeOffset?))
{
return $"{property} {ODataFilterOperators[columnFilterOperator]} {DateTime.Parse(value, null, System.Globalization.DateTimeStyles.RoundtripKind).ToString("yyyy-MM-ddTHH:mm:ss.fffZ")}";
if (columnFilterOperator == FilterOperator.IsNull || columnFilterOperator == FilterOperator.IsNotNull)
{
return $"{property} {odataFilterOperator} null";
}
else
{
return $"{property} {odataFilterOperator} {DateTime.Parse(value, null, System.Globalization.DateTimeStyles.RoundtripKind).ToString("yyyy-MM-ddTHH:mm:ss.fffZ")}";
}
}
else if (column.FilterPropertyType == typeof(Guid) || column.FilterPropertyType == typeof(Guid?))
{
return $"{property} {ODataFilterOperators[columnFilterOperator]} {value}";
return $"{property} {odataFilterOperator} {value}";
}
return "";
@@ -669,7 +715,8 @@ namespace Radzen
public static string ToODataFilterString<T>(this IEnumerable<RadzenDataGridColumn<T>> columns)
{
Func<RadzenDataGridColumn<T>, bool> canFilter = (c) => c.Filterable && c.FilterPropertyType != null &&
!(c.GetFilterValue() == null || c.GetFilterValue() as string == string.Empty) && c.GetFilterProperty() != null;
(!(c.GetFilterValue() == null || c.GetFilterValue() as string == string.Empty) || c.GetFilterOperator() == FilterOperator.IsNotNull || c.GetFilterOperator() == FilterOperator.IsNull)
&& c.GetFilterProperty() != null;
if (columns.Where(canFilter).Any())
{
@@ -684,7 +731,7 @@ namespace Radzen
var value = column.GetFilterValue();
var secondValue = column.GetSecondFilterValue();
if (value != null)
if (value != null || column.GetFilterOperator() == FilterOperator.IsNotNull || column.GetFilterOperator() == FilterOperator.IsNull)
{
var linqOperator = ODataFilterOperators[column.GetFilterOperator()];
if (linqOperator == null)
@@ -804,7 +851,8 @@ namespace Radzen
public static IQueryable<T> Where<T>(this IQueryable<T> source, IEnumerable<RadzenDataGridColumn<T>> columns)
{
Func<RadzenDataGridColumn<T>, bool> canFilter = (c) => c.Filterable && c.FilterPropertyType != null &&
!(c.GetFilterValue() == null || c.GetFilterValue() as string == string.Empty) && c.GetFilterProperty() != null;
(!(c.GetFilterValue() == null || c.GetFilterValue() as string == string.Empty) || c.GetFilterOperator() == FilterOperator.IsNotNull || c.GetFilterOperator() == FilterOperator.IsNull)
&& c.GetFilterProperty() != null;
if (columns.Where(canFilter).Any())
{
@@ -827,7 +875,8 @@ namespace Radzen
property = $@"({property} == null ? """" : {property})";
}
string filterCaseSensitivityOperator = column.FilterPropertyType == typeof(string) &&
string filterCaseSensitivityOperator = column.FilterPropertyType == typeof(string)
&& column.GetFilterOperator() != FilterOperator.IsNotNull && column.GetFilterOperator() != FilterOperator.IsNull &&
column.Grid.FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ? ".ToLower()" : "";
var comparison = LinqFilterOperators[column.GetFilterOperator()];

View File

@@ -8,7 +8,7 @@
<IsPackable>true</IsPackable>
<PackageId>Radzen.Blazor</PackageId>
<Product>Radzen.Blazor</Product>
<Version>3.13.1</Version>
<Version>3.15.2</Version>
<Copyright>Radzen Ltd.</Copyright>
<Authors>Radzen Ltd.</Authors>
<Description>Native Blazor UI components by Radzen Ltd.</Description>
@@ -24,6 +24,7 @@
<DefineConstants>NET5</DefineConstants>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="LibSassBuilder" Version="2.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Components" Condition="'$(TargetFramework)' == 'netstandard2.1'" Version="3.1.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Condition="'$(TargetFramework)' == 'netstandard2.1'" Version="3.1.0" />
<PackageReference Include="Microsoft.AspNetCore.Components" Condition="'$(TargetFramework)' == 'net5.0'" Version="5.0.0" />
@@ -33,46 +34,39 @@
</ItemGroup>
<ItemGroup>
<None Include="LICENSE.txt" Pack="true" PackagePath="" />
<None Include="icon.png" Pack="true" PackagePath="" />
<None Include="LICENSE.txt" Pack="true" PackagePath="" />
<None Include="icon.png" Pack="true" PackagePath="" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="LinkerConfig.xml">
<LogicalName>$(MSBuildProjectName).xml</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="LinkerConfig.xml">
<LogicalName>$(MSBuildProjectName).xml</LogicalName>
</EmbeddedResource>
</ItemGroup>
<UsingTask TaskName="RemoveSourceMap" TaskFactory="RoslynCodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
<Task>
<Using Namespace="System" />
<Using Namespace="System.IO" />
<Using Namespace="System.Text" />
<Code Type="Fragment" Language="cs">
<![CDATA[
foreach (var file in Directory.EnumerateFiles("./wwwroot/css", "*.css"))
{
File.WriteAllText(file, File.ReadAllText(file).Replace("/*# sourceMappingURL=themes" + Path.DirectorySeparatorChar + Path.GetFileName(file) + ".map */", ""), Encoding.UTF8);
}
]]>
</Code>
</Task>
</UsingTask>
<Target Name="ToolRestore" BeforeTargets="PreBuildEvent">
<Exec Command="dotnet tool restore" StandardOutputImportance="high" />
<PropertyGroup>
<LibSassOutputStyle>expanded</LibSassOutputStyle>
<EnableDefaultSassItems>false</EnableDefaultSassItems>
</PropertyGroup>
<ItemGroup>
<Sass Include="$(MSBuildProjectDirectory)/themes/*.scss" Exclude="$(MSBuildProjectDirectory)/themes/_*.scss" Condition="'$(TargetFramework)' == 'net5.0'" />
</ItemGroup>
<Target Name="Sass" BeforeTargets="BeforeBuild" Condition="'$(TargetFramework)' == 'net5.0'">
<PropertyGroup>
<_SassFileList>@(Sass->'&quot;%(FullPath)&quot;', ' ')</_SassFileList>
<LibSassBuilderArgs>files $(_SassFileList) --outputstyle $(LibSassOutputStyle) --level $(LibSassOutputLevel)</LibSassBuilderArgs>
</PropertyGroup>
<Message Text="$(LibSassBuilderArgs)" Importance="$(LibSassMessageLevel)" />
<Message Text="Converted SassFile list to argument" Importance="$(LibSassMessageLevel)" />
</Target>
<Target Name="PreBuild" AfterTargets="ToolRestore">
<Exec Command="dotnet tool run webcompiler -r themes -o wwwroot/css -z disable -m disable -p disable" StandardOutputImportance="high" />
<Target Name="MoveCss" AfterTargets="AfterCompile" Condition="'$(TargetFramework)' == 'net5.0'" >
<ItemGroup>
<CssFiles Include="$(MSBuildProjectDirectory)\themes\*.css" />
<CssFile Include="$(MSBuildProjectDirectory)/themes/*.css" />
</ItemGroup>
<ItemGroup>
<BootstrapFiles Include="$(MSBuildProjectDirectory)\wwwroot\css\bootstrap\**\*.*" />
</ItemGroup>
<Delete Files="@(CssFiles)" />
<Delete Files="@(BootstrapFiles)" />
<RemoveDir Directories="$(MSBuildProjectDirectory)\wwwroot\css\bootstrap" />
<RemoveSourceMap />
<Move SourceFiles="@(CssFile)" DestinationFolder="$(MSBuildProjectDirectory)/wwwroot/css/" />
</Target>
</Project>

View File

@@ -102,7 +102,10 @@ namespace Radzen.Blazor
if (items.Contains(item))
{
items.Remove(item);
try { InvokeAsync(StateHasChanged); } catch { }
if (!disposed)
{
try { InvokeAsync(StateHasChanged); } catch { }
}
}
}

View File

@@ -10,13 +10,12 @@
@if (Visible)
{
<div @ref="@Element" style="@($"{Style};display:inline-block;")" @attributes="Attributes" class="@GetCssClass()" id="@GetId()">
<span class="rz-autocomplete" style="width:100%">
<input @ref="@search" @onkeydown="@OnFilterKeyPress" value="@Value" disabled="@Disabled"
onfocus="@OpenScript()" onkeypress="@OpenScript()" tabindex="@TabIndex" @onchange="@OnChange"
aria-autocomplete="list" aria-haspopup="true" autocomplete="off" role="combobox"
class="@InputClassList"
type="text" id="@Name" aria-expanded="true" placeholder="@Placeholder" />
</span><div id="@PopupID" class="rz-autocomplete-panel" style="display:none; transform: none; box-sizing: border-box; max-height: 200px;">
<input @ref="@search" @onkeydown="@OnFilterKeyPress" value="@Value" disabled="@Disabled"
onfocus="@OpenScript()" onkeypress="@OpenScript()" tabindex="@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;">
<ul @ref="@list" class="rz-autocomplete-items rz-autocomplete-list" role="listbox">
@if (!string.IsNullOrEmpty(searchText) || !string.IsNullOrEmpty(customSearchText))
{

View File

@@ -78,11 +78,11 @@ namespace Radzen.Blazor
selectedIndex = -1;
}
}
else if (key == "Escape")
else if (key == "Escape" || key == "Tab")
{
await JSRuntime.InvokeVoidAsync("Radzen.closePopup", PopupID);
}
else if(key != "Tab")
else
{
selectedIndex = -1;
@@ -203,7 +203,7 @@ namespace Radzen.Blazor
/// <inheritdoc />
protected override string GetComponentCssClass()
{
return GetClassList("").ToString();
return GetClassList("rz-autocomplete").ToString();
}
/// <inheritdoc />

View File

@@ -74,6 +74,12 @@ namespace Radzen.Blazor
return base.TransformCategoryScale(scale);
}
/// <inheritdoc />
protected override IList<object> GetCategories()
{
return base.GetCategories().Reverse().ToList();
}
private IList<IChartSeries> BarSeries
{
get

View File

@@ -1,5 +1,9 @@
using Microsoft.AspNetCore.Components;
using System.Linq;
using Radzen.Blazor.Rendering;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.Routing;
using Microsoft.JSInterop;
namespace Radzen.Blazor
{
@@ -8,17 +12,23 @@ namespace Radzen.Blazor
/// </summary>
public partial class RadzenBody : RadzenComponentWithChildren
{
private const string DefaultStyle = "margin-top: 51px; margin-bottom: 57px; margin-left:250px;";
/// <summary>
/// Gets or sets the style.
/// </summary>
/// <value>The style.</value>
[Parameter]
public override string Style { get; set; } = "margin-top: 51px; margin-bottom: 57px; margin-left:250px;";
public override string Style { get; set; } = DefaultStyle;
/// <inheritdoc />
protected override string GetComponentCssClass()
{
return Expanded ? "body body-expanded" : "body";
var classList = ClassList.Create("rz-body")
.Add("body")
.Add("body-expanded", Expanded);
return classList.ToString();
}
/// <summary>
@@ -31,24 +41,45 @@ namespace Radzen.Blazor
StateHasChanged();
}
/// <summary>
/// The <see cref="RadzenLayout" /> this component is nested in.
/// </summary>
[CascadingParameter]
public RadzenLayout Layout { get; set; }
/// <summary>
/// Gets the style.
/// </summary>
/// <returns>System.String.</returns>
protected string GetStyle()
{
var marginLeft = 250;
if (!string.IsNullOrEmpty(Style))
if (Layout == null)
{
var marginLeftStyle = Style.Split(';').Where(i => i.Split(':')[0].Contains("margin-left")).FirstOrDefault();
if (!string.IsNullOrEmpty(marginLeftStyle) && marginLeftStyle.Contains("px"))
{
marginLeft = int.Parse(marginLeftStyle.Split(':')[1].Trim().Replace("px", "").Split('.')[0].Trim());
}
}
var marginLeft = 250;
var style = Style;
return $"{Style}; margin-left: {(Expanded ? 0 : marginLeft)}px";
if (!string.IsNullOrEmpty(Style))
{
var marginLeftStyle = Style.Split(';').Where(i => i.Split(':')[0].Contains("margin-left")).FirstOrDefault();
if (!string.IsNullOrEmpty(marginLeftStyle) && marginLeftStyle.Contains("px"))
{
marginLeft = int.Parse(marginLeftStyle.Split(':')[1].Trim().Replace("px", "").Split('.')[0].Trim());
}
}
return $"{Style}; margin-left: {(Expanded ? 0 : marginLeft)}px";
}
else
{
var style = Style;
if (!string.IsNullOrEmpty(style))
{
style = style.Replace(DefaultStyle, "");
}
return $"{style}";
}
}
/// <summary>
@@ -64,5 +95,32 @@ namespace Radzen.Blazor
/// <value>The expanded changed callback.</value>
[Parameter]
public EventCallback<bool> ExpandedChanged { get; set; }
[Inject]
NavigationManager NavigationManager { get; set; }
/// <inheritdoc />
protected override Task OnInitializedAsync()
{
NavigationManager.LocationChanged += OnLocationChanged;
return base.OnInitializedAsync();
}
private void OnLocationChanged(object sender, LocationChangedEventArgs e)
{
if (IsJSRuntimeAvailable && Layout != null)
{
JSRuntime.InvokeVoidAsync("eval", $"document.getElementById('{GetId()}').scrollTop = 0");
}
}
/// <inheritdoc />
public override void Dispose()
{
NavigationManager.LocationChanged -= OnLocationChanged;
base.Dispose();
}
}
}
}

View File

@@ -5,13 +5,12 @@
@inherits FormComponent<TValue>
@if (Visible)
{
<div @ref="@Element" @attributes="Attributes" class="@GetCssClass()" @onmouseup=@Toggle @onkeypress=@OnKeyPress
@onkeypress:preventDefault style="@Style" tabindex="@TabIndex" id="@GetId()">
<div @ref="@Element" @attributes="Attributes" class="@GetCssClass()" @onkeypress=@OnKeyPress @onkeypress:preventDefault style="@Style" tabindex="@TabIndex" id="@GetId()">
<div class="rz-helper-hidden-accessible">
<input type="checkbox" @onchange=@Toggle value=@CheckBoxValue name=@Name id=@Name checked=@CheckBoxChecked
tabindex="-1">
</div>
<div class=@BoxClassList>
<div class=@BoxClassList @onclick=@Toggle>
<span class=@IconClassList></span>
</div>
</div>

View File

@@ -137,7 +137,10 @@ namespace Radzen.Blazor
if (items.Contains(item))
{
items.Remove(item);
try { InvokeAsync(StateHasChanged); } catch { }
if (!disposed)
{
try { InvokeAsync(StateHasChanged); } catch { }
}
}
}

View File

@@ -286,11 +286,15 @@ namespace Radzen
}
}
internal bool disposed = false;
/// <summary>
/// Detaches event handlers and disposes <see cref="Reference" />.
/// </summary>
public virtual void Dispose()
{
disposed = true;
reference?.Dispose();
reference = null;

View File

@@ -14,7 +14,7 @@
else if (menu.Options.Items != null && menu.Options.Items.Any())
{
<div class="rz-context-menu">
<RadzenMenu Click="@(args => { if (menu.Options.Click != null) { menu.Options.Click(args); } })">
<RadzenMenu Click="@(args => { if (menu.Options.Click != null) { menu.Options.Click(args); } })" Responsive="false">
@foreach (var item in menu.Options.Items)
{
<RadzenMenuItem Text="@item.Text" Value="@item.Value"></RadzenMenuItem>

View File

@@ -17,31 +17,50 @@
var visibleColumns = columns.Where(c => c.Visible).ToList();
<div @ref=@Element style="@Style" @attributes="Attributes" class="rz-data-grid @GetCssClass()" id="@GetId()">
@if(AllowGrouping)
@if(AllowGrouping || AllowColumnPicking)
{
<div class="rz-group-header" @onmouseup=@(args => EndColumnDropToGroup())>
@if(groups.Any())
{
@foreach(var gd in groups)
@if(AllowGrouping)
{
<div class="rz-group-header-item">
<span class="rz-group-header-item-title">@gd.GetTitle()</span>
<a href="javascript:void(0)" @onclick=@(args => { groups.Remove(gd); _groupedPagedView = null; }) role="button" class="rz-dialog-titlebar-icon rz-dialog-titlebar-close">
<span class="rzi rzi-times"></span>
</a>
@if(groups.Any())
{
<div class="rz-group-header-items">
@foreach(var gd in groups)
{
<div class="rz-group-header-item">
<span class="rz-group-header-item-title">@gd.GetTitle()</span>
<a href="javascript:void(0)" @onclick=@(args => { groups.Remove(gd); _groupedPagedView = null; }) role="button" class="rz-dialog-titlebar-icon rz-dialog-titlebar-close">
<span class="rzi rzi-times"></span>
</a>
</div>
}
</div>
}
else
{
<div class="rz-group-header-drop">@GroupPanelText</div>
}
}
@if(AllowColumnPicking)
{
<div class="rz-column-picker">
<RadzenDropDown SelectAllText="All"
MaxSelectedLabels="2"
SelectedItemsText="@ColumnsShowingText" Change=@(args => StateHasChanged())
@bind-Value="@selectedColumns"
Multiple="true"
Placeholder="Columns"
Data="allColumns"
TextProperty="Title" />
</div>
}
}
else
{
<div class="rz-group-header-drop">@GroupPanelText</div>
}
</div>
}
@if (AllowPaging && (PagerPosition == PagerPosition.Top || PagerPosition == PagerPosition.TopAndBottom))
{
<RadzenPager @ref="topPager" Count="@Count" PageSize="@PageSize" PageNumbersCount="@PageNumbersCount" PageChanged="@OnPageChanged" PageSizeChanged="@OnPageSizeChanged" PageSizeOptions="@PageSizeOptions" ShowPagingSummary="@ShowPagingSummary" PagingSummaryFormat="@PagingSummaryFormat" />
<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" />
}
<div class="rz-data-grid-data">
@@ -61,154 +80,61 @@
}
</colgroup>
<thead>
@for(var i = 0; i < deepestChildColumnLevel + 1; i++)
{
<tr>
@foreach(var g in groups)
{
<th class="rz-col-icon rz-unselectable-text" scope="col">
<th class="rz-col-icon rz-unselectable-text" scope="col" rowspan=@(deepestChildColumnLevel + 1)>
<span class="rz-column-title"></span>
</th>
}
@if (Template != null && ShowExpandColumn)
{
<th class="rz-col-icon rz-unselectable-text" scope="col">
<th class="rz-col-icon rz-unselectable-text" scope="col" rowspan=@(deepestChildColumnLevel + 1)>
<span class="rz-column-title"></span>
</th>
}
@foreach (var column in visibleColumns)
@for (var j = 0; j < visibleColumns.Count; j++)
{
var column = visibleColumns[j];
var cellAttr = HeaderCellAttributes(column);
object colspan;
cellAttr.TryGetValue("colspan", out colspan);
if (colspan != null)
{
j = j + (int)Convert.ChangeType(colspan, TypeCode.Int32) - 1;
}
var columnIndex = visibleColumns.IndexOf(column);
var sortableClass = AllowSorting && column.Sortable ? "rz-sortable-column" : "";
<th class="@($"rz-unselectable-text {sortableClass} {column.HeaderCssClass} {getFrozenColumnClass(column, visibleColumns)}")" scope="col" style="@column.GetStyle(true, true)" @onmouseup=@(args => EndColumnReorder(args, columnIndex))>
<div @onclick='@((args) => OnSort(args, column))' style="width:100%">
@if (AllowColumnReorder && column.Reorderable || AllowGrouping && column.Groupable)
{
<span id="@getColumnResizerId(columnIndex)" class="rz-column-drag"
@onclick:preventDefault="true" @onclick:stopPropagation="true"
@onmousedown=@(args => StartColumnReorder(args, columnIndex))>&nbsp;</span>
}
<span class="rz-column-title">
@if (column.HeaderTemplate != null)
{
@column.HeaderTemplate
}
else
{
@column.Title
}
</span>
@if (AllowSorting && column.Sortable)
{
@if (column.GetSortOrder() == SortOrder.Ascending)
{
<span class="rz-sortable-column-icon rzi-grid-sort rzi-sort rzi-sort-asc"></span>
}
else if (column.GetSortOrder() == SortOrder.Descending)
{
<span class="rz-sortable-column-icon rzi-grid-sort rzi-sort rzi-sort-desc"></span>
}
else
{
<span class="rz-sortable-column-icon rzi-grid-sort rzi-sort"></span>
}
}
@if (AllowColumnResize && column.Resizable)
{
<div id="@getColumnResizerId(columnIndex)" style="cursor:col-resize;float:right;"
@onclick:preventDefault="true" @onclick:stopPropagation="true" class="rz-column-resizer"
@onmousedown=@(args => StartColumnResize(args, columnIndex))>&nbsp;</div>
}
@if (AllowFiltering && column.Filterable && FilterMode == FilterMode.Advanced)
{
<i @onclick:stopPropagation="true" onclick="@($"Radzen.togglePopup(this, '{PopupID}{column.GetFilterProperty()}')")"
class="@getFilterIconCss(column)" />
<div id="@($"{PopupID}{column.GetFilterProperty()}")" class="rz-overlaypanel"
style="display:none;min-width:250px;" tabindex="0">
<div class="rz-grid-filter rz-overlaypanel-content">
@if (column.FilterTemplate != null)
{
@column.FilterTemplate(column)
}
else
{
<RadzenLabel Text="@FilterText" class="rz-grid-filter-label" />
<RadzenDropDown @onclick:preventDefault="true" Data="@(column.GetFilterOperators().Select(t => new { Value = column.GetFilterOperatorText(t), Key = t }))" TextProperty="Value" ValueProperty="Key" TValue="FilterOperator" Value="@column.GetFilterOperator()" Change="@(args => column.SetFilterOperator((FilterOperator)args))" />
@if (PropertyAccess.IsNumeric(column.FilterPropertyType))
{
@(DrawNumericFilter(column, false))
}
else if (PropertyAccess.IsDate(column.FilterPropertyType))
{
<RadzenDatePicker TValue="@object" ShowTime="true" ShowTimeOkButton="true" DateFormat="@getFilterDateFormat(column)"
Value="@column.GetFilterValue()" Change="@(args => column.SetFilterValue(args.Value))" />
}
else if (column.FilterPropertyType == typeof(bool) || column.FilterPropertyType == typeof(bool?))
{
<RadzenCheckBox TriState="true" TValue="@object" Value="@column.GetFilterValue()" Change="@(args => column.SetFilterValue(args))" />
}
else
{
<RadzenTextBox Value="@($"{column.GetFilterValue()}")" Change="@(args => column.SetFilterValue(args))" />
}
<RadzenDropDown @onclick:preventDefault="true" TextProperty="Text" ValueProperty="Value" Style="width: 80px"
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.GetFilterOperators().Select(t => new { Value = column.GetFilterOperatorText(t), Key = t }))" TextProperty="Value" ValueProperty="Key" TValue="FilterOperator" Value="@column.GetSecondFilterOperator()" Change="@(args => column.SetSecondFilterOperator((FilterOperator)args))" />
@if (PropertyAccess.IsNumeric(column.FilterPropertyType))
{
@(DrawNumericFilter(column, false, false))
}
else if (PropertyAccess.IsDate(column.FilterPropertyType))
{
<RadzenDatePicker TValue="@object"
ShowTime="true" ShowTimeOkButton="true" DateFormat="@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))"/>
}
else
{
<RadzenTextBox Value="@($"{column.GetSecondFilterValue()}")" Change="@(args => column.SetFilterValue(args, false))" />
}
}
</div>
@if (column.FilterTemplate == null)
{
<div class="rz-grid-filter-buttons">
<RadzenButton ButtonStyle="ButtonStyle.Secondary" Text=@ClearFilterText Click="@((args) => ClearFilter(column, true))" />
<RadzenButton ButtonStyle="ButtonStyle.Primary" Text=@ApplyFilterText Click="@((args) => ApplyFilter(column, true))" />
</div>
}
</div>
}
</div>
</th>
<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)" />
}
</tr>
}
@if (AllowFiltering && FilterMode == FilterMode.Simple && columns.Where(column => column.Filterable && (!string.IsNullOrEmpty(column.GetFilterProperty()) || column.FilterTemplate != null)).Any())
{
<tr>
@foreach(var g in groups)
{
<th class="rz-col-icon rz-unselectable-text" scope="col">
<th class="rz-col-icon rz-unselectable-text" scope="col" rowspan=@(deepestChildColumnLevel + 1)>
<span class="rz-column-title"></span>
</th>
}
@if (Template != null && ShowExpandColumn)
{
<th class="rz-col-icon rz-unselectable-text" scope="col">
<th class="rz-col-icon rz-unselectable-text" scope="col" rowspan=@(deepestChildColumnLevel + 1)>
<span class="rz-column-title"></span>
</th>
}
@foreach (var column in visibleColumns)
{
<th class="@($" rz-unselectable-text")" tabindex="1" scope="col" style="@column.GetStyle(true, true)">
@if (AllowFiltering && column.Filterable && (!string.IsNullOrEmpty(column.GetFilterProperty()) || column.FilterTemplate != null))
<th colspan="@column.GetColSpan()" class="@($" rz-unselectable-text")" 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">
<div class="rz-cell-filter-content">
@@ -218,14 +144,16 @@
}
else
{
<label class="rz-cell-filter-label" style="height:35px">
<label class="rz-cell-filter-label" style="height:35px" onclick="event.preventDefault()">
@if (column.FilterPropertyType == typeof(DateTime) || column.FilterPropertyType == typeof(DateTime?) || column.FilterPropertyType == typeof(DateTimeOffset) || column.FilterPropertyType == typeof(DateTimeOffset?))
{
<i onclick="@($"Radzen.togglePopup(this.parentNode, '{PopupID}{column.GetFilterProperty()}')")"
class="rzi">date_range</i>
@if (column.GetFilterValue() != null)
<button class="rz-button rz-button-md rz-button-icon-only btn-light" onclick="@($"Radzen.togglePopup(this.parentNode, '{PopupID}{column.GetFilterProperty()}')")">
<i class="rzi">date_range</i>
</button>
var filterValue = column.GetFilterValue();
@if (filterValue != null)
{
<span class="rz-current-filter">@column.GetFilterValue()</span>
<span class="rz-current-filter">@string.Format("{0:" + getFilterDateFormat(column) + "}", filterValue)</span>
<i @onclick="@((args) => ClearFilter(column))" class="rzi rz-cell-filter-clear">close</i>
}
<div id="@($"{PopupID}{column.GetFilterProperty()}")" class="rz-overlaypanel"
@@ -255,6 +183,12 @@
<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.IsNotNull))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.IsNotNull))" style="display: block;">
<span>@IsNotNullText</span>
</li>
</ul>
</div>
</div>
@@ -278,7 +212,6 @@
}
else if (PropertyAccess.IsNumeric(column.FilterPropertyType))
{
<i class="rzi">search</i>
@(DrawNumericFilter(column))
}
else if (column.FilterPropertyType == typeof(bool) || column.FilterPropertyType == typeof(bool?))
@@ -289,8 +222,7 @@
}
else
{
<i class="rzi">search</i>
<input id="@(getFilterInputId(column))" @onchange="@((args) => OnFilter(args, column))" @onkeydown="@((args) => OnFilterKeyPress(args, column))" value="@column.GetFilterValue()" type="text" />
<input id="@(getFilterInputId(column))" @onchange="@((args) => OnFilter(args, column))" @onkeydown="@((args) => OnFilterKeyPress(args, column))" value="@column.GetFilterValue()" type="text" class="rz-textbox" style="width: 100%;" />
}
</label>
}
@@ -305,9 +237,12 @@
<tbody>
@if (Data != null)
{
@if (Count > 0 && columns.Count > 0)
@if (Count > 0 || !AllowPaging && LoadData.HasDelegate && Count == 0)
{
@DrawRows(visibleColumns)
if (columns.Count > 0)
{
@DrawRows(visibleColumns)
}
}
else
{
@@ -319,7 +254,7 @@
}
else
{
<span>@EmptyText</span>
<span style="white-space: normal">@EmptyText</span>
}
</td>
</tr>
@@ -329,31 +264,40 @@
@if (visibleColumns.Where(c => c.FooterTemplate != null).Any())
{
<tfoot class="rz-datatable-tfoot">
@for(var i = 0; i < deepestChildColumnLevel + 1; i++)
{
<tr class="">
@foreach(var g in groups)
{
<td class="rz-col-icon rz-unselectable-text" scope="col">
<td class="rz-col-icon rz-unselectable-text" scope="col" rowspan=@(deepestChildColumnLevel + 1)>
<span class="rz-column-title"></span>
</td>
}
@if (Template != null && ShowExpandColumn)
{
<td class="rz-col-icon rz-unselectable-text" scope="col">
<td class="rz-col-icon rz-unselectable-text" scope="col" rowspan=@(deepestChildColumnLevel + 1)>
<span class="rz-column-title"></span>
</td>
}
@foreach (var column in visibleColumns)
@for (var j = 0; j < visibleColumns.Count; j++)
{
<td class="@($" {column.FooterCssClass} {getFrozenColumnClass(column, visibleColumns)}")" style="@column.GetStyle(true, true)">
<span class="rz-column-footer">
@if (column.FooterTemplate != null)
{
@column.FooterTemplate
}
</span>
</td>
var column = visibleColumns[j];
var cellAttr = FooterCellAttributes(column);
object colspan;
cellAttr.TryGetValue("colspan", out colspan);
if (colspan != null)
{
j = j + (int)Convert.ChangeType(colspan, TypeCode.Int32) - 1;
}
<RadzenDataGridFooterCell RowIndex="@i" Grid="@this" Column="@column"
CssClass="@($"{column.FooterCssClass} {getFrozenColumnClass(column, visibleColumns)} {(column.Columns != null || column.Parent != null ? "rz-composite-cell" : "")}".Trim())"
Attributes="@(cellAttr)" />
}
</tr>
}
</tfoot>
}
</table>
@@ -369,7 +313,7 @@
@if (AllowPaging && (PagerPosition == PagerPosition.Bottom || PagerPosition == PagerPosition.TopAndBottom))
{
<RadzenPager @ref="bottomPager" Count="@Count" PageSize="@PageSize" PageNumbersCount="@PageNumbersCount" PageChanged="@OnPageChanged" PageSizeChanged="@OnPageSizeChanged" PageSizeOptions="@PageSizeOptions" ShowPagingSummary="@ShowPagingSummary" PagingSummaryFormat="@PagingSummaryFormat" />
<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" />
}
</div>
}

View File

@@ -33,6 +33,7 @@ namespace Radzen.Blazor
}
internal Microsoft.AspNetCore.Components.Web.Virtualization.Virtualize<TItem> virtualize;
internal Microsoft.AspNetCore.Components.Web.Virtualization.Virtualize<GroupResult> groupVirtualize;
/// <summary>
/// Gets Virtualize component reference.
@@ -51,64 +52,96 @@ namespace Radzen.Blazor
{
var view = AllowPaging ? PagedView : View;
var totalItemsCount = LoadData.HasDelegate ? Count : view.Count();
var top = totalItemsCount > request.Count ? Math.Min(request.Count, totalItemsCount - request.StartIndex) : PageSize;
var top = request.Count;
if(top <= 0)
{
top = PageSize;
}
if (LoadData.HasDelegate)
{
var orderBy = GetOrderBy();
Query.Skip = request.StartIndex;
Query.Top = top;
Query.OrderBy = orderBy;
var filterString = columns.ToFilterString<TItem>();
Query.Filter = filterString;
await LoadData.InvokeAsync(new Radzen.LoadDataArgs() { Skip = request.StartIndex, Top = top, OrderBy = orderBy, Filter = IsOData() ? columns.ToODataFilterString<TItem>() : filterString });
}
await InvokeLoadData(request.StartIndex, top);
virtualDataItems = (LoadData.HasDelegate ? Data : itemToInsert != null ? (new[] { itemToInsert }).Concat(view.Skip(request.StartIndex).Take(top)) : view.Skip(request.StartIndex).Take(top)).ToList();
return new Microsoft.AspNetCore.Components.Web.Virtualization.ItemsProviderResult<TItem>(virtualDataItems, totalItemsCount);
}
private async ValueTask<Microsoft.AspNetCore.Components.Web.Virtualization.ItemsProviderResult<GroupResult>> LoadGroups(Microsoft.AspNetCore.Components.Web.Virtualization.ItemsProviderRequest request)
{
var top = request.Count;
if(top <= 0)
{
top = PageSize;
}
var view = AllowPaging ? PagedView : View;
var query = view.AsQueryable().OrderBy(string.Join(',', groups.Select(g => $"np({g.Property})")));
_groupedPagedView = query.GroupByMany(groups.Select(g => $"np({g.Property})").ToArray()).ToList();
var totalItemsCount = _groupedPagedView.Count();
return new Microsoft.AspNetCore.Components.Web.Virtualization.ItemsProviderResult<GroupResult>(_groupedPagedView.Skip(request.StartIndex).Take(top), totalItemsCount);
}
#endif
RenderFragment DrawRows(IList<RadzenDataGridColumn<TItem>> visibleColumns)
{
return new RenderFragment(builder =>
{
#if NET5
#if NET5
if (AllowVirtualization)
{
builder.OpenComponent(0, typeof(Microsoft.AspNetCore.Components.Web.Virtualization.Virtualize<TItem>));
builder.AddAttribute(1, "ItemsProvider", new Microsoft.AspNetCore.Components.Web.Virtualization.ItemsProviderDelegate<TItem>(LoadItems));
builder.AddAttribute(2, "ChildContent", (RenderFragment<TItem>)((context) =>
if(AllowGrouping && groups.Any() && !LoadData.HasDelegate)
{
return (RenderFragment)((b) =>
builder.OpenComponent(0, typeof(Microsoft.AspNetCore.Components.Web.Virtualization.Virtualize<GroupResult>));
builder.AddAttribute(1, "ItemsProvider", new Microsoft.AspNetCore.Components.Web.Virtualization.ItemsProviderDelegate<GroupResult>(LoadGroups));
builder.AddAttribute(2, "ChildContent", (RenderFragment<GroupResult>)((context) =>
{
b.OpenComponent<RadzenDataGridRow<TItem>>(3);
b.AddAttribute(4, "Columns", visibleColumns);
b.AddAttribute(5, "Grid", this);
b.AddAttribute(6, "TItem", typeof(TItem));
b.AddAttribute(7, "Item", context);
b.AddAttribute(8, "InEditMode", IsRowInEditMode(context));
b.AddAttribute(9, "Index", virtualDataItems.IndexOf(context));
if (editContexts.ContainsKey(context))
return (RenderFragment)((b) =>
{
b.AddAttribute(10, nameof(RadzenDataGridRow<TItem>.EditContext), editContexts[context]);
}
b.OpenComponent(3, typeof(RadzenDataGridGroupRow<TItem>));
b.AddAttribute(4, "Columns", visibleColumns);
b.AddAttribute(5, "Grid", this);
b.AddAttribute(6, "GroupResult", context);
b.AddAttribute(7, "Builder", b);
b.SetKey(context);
b.CloseComponent();
});
}));
b.SetKey(context);
b.CloseComponent();
});
}));
builder.AddComponentReferenceCapture(8, c => { groupVirtualize = (Microsoft.AspNetCore.Components.Web.Virtualization.Virtualize<GroupResult>)c; });
}
else
{
builder.OpenComponent(0, typeof(Microsoft.AspNetCore.Components.Web.Virtualization.Virtualize<TItem>));
builder.AddAttribute(1, "ItemsProvider", new Microsoft.AspNetCore.Components.Web.Virtualization.ItemsProviderDelegate<TItem>(LoadItems));
builder.AddAttribute(2, "ChildContent", (RenderFragment<TItem>)((context) =>
{
return (RenderFragment)((b) =>
{
b.OpenComponent<RadzenDataGridRow<TItem>>(3);
b.AddAttribute(4, "Columns", visibleColumns);
b.AddAttribute(5, "Grid", this);
b.AddAttribute(6, "TItem", typeof(TItem));
b.AddAttribute(7, "Item", context);
b.AddAttribute(8, "InEditMode", IsRowInEditMode(context));
b.AddAttribute(9, "Index", virtualDataItems.IndexOf(context));
builder.AddComponentReferenceCapture(8, c => { virtualize = (Microsoft.AspNetCore.Components.Web.Virtualization.Virtualize<TItem>)c; });
if (editContexts.ContainsKey(context))
{
b.AddAttribute(10, nameof(RadzenDataGridRow<TItem>.EditContext), editContexts[context]);
}
b.SetKey(context);
b.CloseComponent();
});
}));
builder.AddComponentReferenceCapture(8, c => { virtualize = (Microsoft.AspNetCore.Components.Web.Virtualization.Virtualize<TItem>)c; });
}
builder.CloseComponent();
}
@@ -116,9 +149,9 @@ namespace Radzen.Blazor
{
DrawGroupOrDataRows(builder, visibleColumns);
}
#else
#else
DrawGroupOrDataRows(builder, visibleColumns);
#endif
#endif
});
}
@@ -160,6 +193,20 @@ namespace Radzen.Blazor
}
}
/// <summary>
/// Gets or sets a value indicating whether DataGrid data cells will follow the header cells structure in composite columns.
/// </summary>
/// <value><c>true</c> if DataGrid data cells will follow the header cells structure in composite columns; otherwise, <c>false</c>.</value>
[Parameter]
public bool AllowCompositeDataCells { get; set; } = false;
/// <summary>
/// Gets or sets a value indicating whether DataGrid is responsive.
/// </summary>
/// <value><c>true</c> if DataGrid is Responsive; otherwise, <c>false</c>.</value>
[Parameter]
public bool Responsive { get; set; }
/// <summary>
/// The grouped and paged View
/// </summary>
@@ -172,9 +219,11 @@ namespace Radzen.Blazor
{
get
{
if(_groupedPagedView == null)
if (_groupedPagedView == null)
{
_groupedPagedView = PagedView.GroupByMany(groups.Select(g => $"np({g.Property})").ToArray()).ToList();
var query = groups.Count(g => g.SortOrder == null) == Groups.Count ? View : View.OrderBy(string.Join(',', groups.Select(g => $"np({g.Property}) {(g.SortOrder == null ? "" : g.SortOrder == SortOrder.Ascending ? " asc" : " desc")}")));
var v = (AllowPaging && !LoadData.HasDelegate ? query.Skip(skip).Take(PageSize) : query).ToList().AsQueryable();
_groupedPagedView = v.GroupByMany(groups.Select(g => $"np({g.Property})").ToArray()).ToList();
}
return _groupedPagedView;
}
@@ -182,7 +231,7 @@ namespace Radzen.Blazor
internal string getFrozenColumnClass(RadzenDataGridColumn<TItem> column, IList<RadzenDataGridColumn<TItem>> visibleColumns)
{
return column.Frozen ? "rz-frozen-cell" : "";
return column.IsFrozen() ? "rz-frozen-cell" : "";
}
/// <summary>
@@ -228,6 +277,9 @@ namespace Radzen.Blazor
}
private readonly List<RadzenDataGridColumn<TItem>> columns = new List<RadzenDataGridColumn<TItem>>();
internal readonly List<RadzenDataGridColumn<TItem>> childColumns = new List<RadzenDataGridColumn<TItem>>();
private readonly List<RadzenDataGridColumn<TItem>> allColumns = new List<RadzenDataGridColumn<TItem>>();
internal object selectedColumns;
/// <summary>
/// Gets or sets the columns.
@@ -238,17 +290,40 @@ namespace Radzen.Blazor
internal void AddColumn(RadzenDataGridColumn<TItem> column)
{
if (!columns.Contains(column))
if (!columns.Contains(column) && column.Parent == null)
{
columns.Add(column);
}
var descriptor = sorts.Where(d => d.Property == column?.GetSortProperty()).FirstOrDefault();
if (descriptor == null && column.SortOrder.HasValue)
if (!childColumns.Contains(column) && column.Parent != null)
{
childColumns.Add(column);
var level = column.GetLevel();
if (level > deepestChildColumnLevel)
{
descriptor = new SortDescriptor() { Property = column.Property, SortOrder = column.SortOrder.Value };
sorts.Add(descriptor);
deepestChildColumnLevel = level;
}
}
var descriptor = sorts.Where(d => d.Property == column?.GetSortProperty()).FirstOrDefault();
if (descriptor == null && column.SortOrder.HasValue)
{
descriptor = new SortDescriptor() { Property = column.Property, SortOrder = column.SortOrder.Value };
sorts.Add(descriptor);
}
if (!allColumns.Contains(column))
{
allColumns.Add(column);
}
if (AllowColumnPicking)
{
selectedColumns = allColumns;
}
StateHasChanged();
}
internal void RemoveColumn(RadzenDataGridColumn<TItem> column)
@@ -256,10 +331,21 @@ namespace Radzen.Blazor
if (columns.Contains(column))
{
columns.Remove(column);
if (!disposed)
{
try { InvokeAsync(StateHasChanged); } catch { }
}
}
if (childColumns.Contains(column))
{
childColumns.Remove(column);
}
if (allColumns.Contains(column))
{
allColumns.Remove(column);
}
if (!disposed)
{
try { InvokeAsync(StateHasChanged); } catch { }
}
}
@@ -268,7 +354,7 @@ namespace Radzen.Blazor
return string.Join("", $"{UniqueID}".Split('.')) + column.GetFilterProperty();
}
string getFilterDateFormat(RadzenDataGridColumn<TItem> column)
internal string getFilterDateFormat(RadzenDataGridColumn<TItem> column)
{
if (column != null && !string.IsNullOrEmpty(column.FormatString))
{
@@ -286,7 +372,7 @@ namespace Radzen.Blazor
return FilterDateFormat;
}
RenderFragment DrawNumericFilter(RadzenDataGridColumn<TItem> column, bool force = true, bool isFirst = true)
internal RenderFragment DrawNumericFilter(RadzenDataGridColumn<TItem> column, bool force = true, bool isFirst = true)
{
return new RenderFragment(builder =>
{
@@ -316,12 +402,12 @@ namespace Radzen.Blazor
builder.AddAttribute(3, "Change", eventCallbackGenericCreate.Invoke(this,
new object[] { this, eventCallbackGenericAction.Invoke(this, new object[] { action }) }));
if(FilterMode == FilterMode.Advanced)
if (FilterMode == FilterMode.Advanced)
{
builder.AddAttribute(4, "oninput", EventCallback.Factory.Create<ChangeEventArgs>(this, args => {
var value = $"{args.Value}";
column.SetFilterValue(!string.IsNullOrWhiteSpace(value) ? Convert.ChangeType(value, Nullable.GetUnderlyingType(type)) : null, isFirst);
} ));
}));
}
builder.CloseComponent();
@@ -369,18 +455,7 @@ namespace Radzen.Blazor
}
}
private string getFilterIconCss(RadzenDataGridColumn<TItem> column)
{
var additionalStyle = column.GetFilterValue() != null || column.GetSecondFilterValue() != null ? "rz-grid-filter-active" : "";
return $"rzi rz-grid-filter-icon {additionalStyle}";
}
/// <summary>
/// Called when sort.
/// </summary>
/// <param name="args">The <see cref="EventArgs"/> instance containing the event data.</param>
/// <param name="column">The column.</param>
protected void OnSort(EventArgs args, RadzenDataGridColumn<TItem> column)
internal void OnSort(EventArgs args, RadzenDataGridColumn<TItem> column)
{
if (AllowSorting && column.Sortable)
{
@@ -403,12 +478,7 @@ namespace Radzen.Blazor
}
}
/// <summary>
/// Clears the filter.
/// </summary>
/// <param name="column">The column.</param>
/// <param name="closePopup">if set to <c>true</c> [close popup].</param>
protected async Task ClearFilter(RadzenDataGridColumn<TItem> column, bool closePopup = false)
internal async Task ClearFilter(RadzenDataGridColumn<TItem> column, bool closePopup = false)
{
if (closePopup)
{
@@ -419,6 +489,12 @@ namespace Radzen.Blazor
column.SetFilterOperator(null);
column.SetSecondFilterOperator(null);
column.FilterValue = null;
column.SecondFilterValue = null;
column.FilterOperator = default(FilterOperator);
column.SecondFilterOperator = default(FilterOperator);
column.LogicalFilterOperator = default(LogicalFilterOperator);
skip = 0;
CurrentPage = 0;
@@ -430,12 +506,7 @@ namespace Radzen.Blazor
await InvokeAsync(Reload);
}
/// <summary>
/// Applies the filter.
/// </summary>
/// <param name="column">The column.</param>
/// <param name="closePopup">if set to <c>true</c> [close popup].</param>
protected async Task ApplyFilter(RadzenDataGridColumn<TItem> column, bool closePopup = false)
internal async Task ApplyFilter(RadzenDataGridColumn<TItem> column, bool closePopup = false)
{
if (closePopup)
{
@@ -456,6 +527,41 @@ namespace Radzen.Blazor
return new System.Collections.ObjectModel.ReadOnlyDictionary<string, object>(args.Attributes);
}
internal IReadOnlyDictionary<string, object> HeaderCellAttributes(RadzenDataGridColumn<TItem> column)
{
var args = new Radzen.DataGridCellRenderEventArgs<TItem>() { Column = column };
if (HeaderCellRender != null)
{
HeaderCellRender(args);
}
var sortOrder = column.GetSortOrder();
switch (sortOrder)
{
case SortOrder.Ascending:
args.Attributes.Add("aria-sort", "ascending");
break;
case SortOrder.Descending:
args.Attributes.Add("aria-sort", "descending");
break;
}
return new System.Collections.ObjectModel.ReadOnlyDictionary<string, object>(args.Attributes);
}
internal IReadOnlyDictionary<string, object> FooterCellAttributes(RadzenDataGridColumn<TItem> column)
{
var args = new Radzen.DataGridCellRenderEventArgs<TItem>() { Column = column };
if (FooterCellRender != null)
{
FooterCellRender(args);
}
return new System.Collections.ObjectModel.ReadOnlyDictionary<string, object>(args.Attributes);
}
internal Dictionary<int, int> rowSpans = new Dictionary<int, int>();
/// <summary>
@@ -598,6 +704,20 @@ namespace Radzen.Blazor
[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";
internal class NumericFilterEventCallback
{
public static EventCallback<T> Create<T>(object receiver, Action<T> action)
@@ -713,6 +833,20 @@ namespace Radzen.Blazor
[Parameter]
public bool AllowColumnReorder { get; set; }
/// <summary>
/// Gets or sets a value indicating whether column picking is allowed.
/// </summary>
/// <value><c>true</c> if column picking is allowed; otherwise, <c>false</c>.</value>
[Parameter]
public bool AllowColumnPicking { get; set; }
/// <summary>
/// Gets or sets the column picker columns showing text.
/// </summary>
/// <value>The column picker columns showing text.</value>
[Parameter]
public string ColumnsShowingText { get; set; } = "columns showing";
/// <summary>
/// Gets or sets a value indicating whether grouping is allowed.
/// </summary>
@@ -769,15 +903,16 @@ namespace Radzen.Blazor
if (columnToReorder != null && columnToReorderTo != null)
{
var actualColumnIndex = columns.IndexOf(columnToReorderTo);
var actualColumnIndexFrom = columns.IndexOf(columnToReorder);
var actualColumnIndexTo = columns.IndexOf(columnToReorderTo);
columns.Remove(columnToReorder);
columns.Insert(actualColumnIndex, columnToReorder);
columns.Insert(actualColumnIndexTo, columnToReorder);
await ColumnReordered.InvokeAsync(new DataGridColumnReorderedEventArgs<TItem>
{
Column = columnToReorder,
OldIndex = indexOfColumnToReoder.Value,
NewIndex = actualColumnIndex
OldIndex = actualColumnIndexFrom,
NewIndex = actualColumnIndexTo
});
}
@@ -794,7 +929,7 @@ namespace Radzen.Blazor
public async Task OnColumnResized(int columnIndex, double value)
{
var column = columns.Where(c => c.Visible).ToList()[columnIndex];
column.SetWidth($"{value}px");
column.SetWidth($"{Math.Round(value)}px");
await ColumnResized.InvokeAsync(new DataGridColumnResizedEventArgs<TItem>
{
Column = column,
@@ -804,7 +939,7 @@ namespace Radzen.Blazor
internal string GetOrderBy()
{
return string.Join(",", sorts.Select(d => columns.Where(c => c.GetSortProperty() == d.Property).FirstOrDefault()).Where(c => c != null).Select(c => c.GetSortOrderAsString(IsOData())));
return string.Join(",", sorts.Select(d => allColumns.ToList().Where(c => c.GetSortProperty() == d.Property).FirstOrDefault()).Where(c => c != null).Select(c => c.GetSortOrderAsString(IsOData())));
}
/// <summary>
@@ -834,7 +969,7 @@ namespace Radzen.Blazor
return base.View;
}
var view = base.View.Where<TItem>(columns);
var view = base.View.Where<TItem>(allColumns);
var orderBy = GetOrderBy();
if (!string.IsNullOrEmpty(orderBy))
@@ -865,6 +1000,12 @@ namespace Radzen.Blazor
skip = Count - PageSize;
}
if (Count <= PageSize)
{
skip = 0;
CurrentPage = 0;
}
StateHasChanged();
}
}
@@ -950,6 +1091,13 @@ namespace Radzen.Blazor
[Parameter]
public EventCallback<TItem> RowExpand { get; set; }
/// <summary>
/// Gets or sets the group row expand callback.
/// </summary>
/// <value>The group row expand callback.</value>
[Parameter]
public EventCallback<Group> GroupRowExpand { get; set; }
/// <summary>
/// Gets or sets the row collapse callback.
/// </summary>
@@ -957,6 +1105,13 @@ namespace Radzen.Blazor
[Parameter]
public EventCallback<TItem> RowCollapse { get; set; }
/// <summary>
/// Gets or sets the group row collapse callback.
/// </summary>
/// <value>The group row collapse callback.</value>
[Parameter]
public EventCallback<Group> GroupRowCollapse { get; set; }
/// <summary>
/// Gets or sets the row render callback. Use it to set row attributes.
/// </summary>
@@ -964,6 +1119,13 @@ namespace Radzen.Blazor
[Parameter]
public Action<RowRenderEventArgs<TItem>> RowRender { get; set; }
/// <summary>
/// Gets or sets the group row render callback. Use it to set group row attributes.
/// </summary>
/// <value>The group row render callback.</value>
[Parameter]
public Action<GroupRowRenderEventArgs> GroupRowRender { get; set; }
/// <summary>
/// Gets or sets the cell render callback. Use it to set cell attributes.
/// </summary>
@@ -971,6 +1133,20 @@ namespace Radzen.Blazor
[Parameter]
public Action<DataGridCellRenderEventArgs<TItem>> CellRender { get; set; }
/// <summary>
/// Gets or sets the header cell render callback. Use it to set header cell attributes.
/// </summary>
/// <value>The cell render callback.</value>
[Parameter]
public Action<DataGridCellRenderEventArgs<TItem>> HeaderCellRender { get; set; }
/// <summary>
/// Gets or sets the footer cell render callback. Use it to set footer cell attributes.
/// </summary>
/// <value>The cell render callback.</value>
[Parameter]
public Action<DataGridCellRenderEventArgs<TItem>> FooterCellRender { get; set; }
/// <summary>
/// Gets or sets the render callback.
/// </summary>
@@ -1005,8 +1181,8 @@ namespace Radzen.Blazor
if (resetColumnState)
{
columns.ForEach(c => { c.SetFilterValue(null); c.SetSecondFilterOperator(FilterOperator.Equals); });
columns.ForEach(c => { c.ResetSortOrder(); });
allColumns.ToList().ForEach(c => { c.SetFilterValue(null); c.SetFilterValue(null, false); c.SetSecondFilterOperator(FilterOperator.Equals); });
allColumns.ToList().ForEach(c => { c.ResetSortOrder(); });
sorts.Clear();
}
}
@@ -1023,48 +1199,28 @@ namespace Radzen.Blazor
{
Count = 1;
}
#if NET5
if (AllowVirtualization && virtualize != null)
#if NET5
if (AllowVirtualization)
{
if(!LoadData.HasDelegate)
{
await virtualize.RefreshDataAsync();
if(virtualize != null)
{
await virtualize.RefreshDataAsync();
}
if(groupVirtualize != null)
{
await groupVirtualize.RefreshDataAsync();
}
}
else
{
Data = null;
}
}
#endif
var orderBy = GetOrderBy();
Query.Skip = skip;
Query.Top = PageSize;
Query.OrderBy = orderBy;
var filterString = columns.ToFilterString<TItem>();
Query.Filter = filterString;
if (LoadData.HasDelegate)
{
await LoadData.InvokeAsync(new Radzen.LoadDataArgs()
{
Skip = skip,
Top = PageSize,
OrderBy = orderBy,
Filter = IsOData() ? columns.ToODataFilterString<TItem>() : filterString,
Filters = columns.Where(c => c.Filterable && c.Visible && c.GetFilterValue() != null).Select(c => new FilterDescriptor()
{
Property = c.GetFilterProperty(),
FilterValue = c.GetFilterValue(),
FilterOperator = c.GetFilterOperator(),
SecondFilterValue = c.GetSecondFilterValue(),
SecondFilterOperator = c.GetSecondFilterOperator(),
LogicalFilterOperator = c.GetLogicalFilterOperator()
}),
Sorts = sorts
}); ;
}
#endif
await InvokeLoadData(skip, PageSize);
CalculatePager();
@@ -1074,14 +1230,58 @@ namespace Radzen.Blazor
}
else
{
#if NET5
if (AllowVirtualization && virtualize != null)
#if NET5
if (AllowVirtualization)
{
await virtualize.RefreshDataAsync();
if(virtualize != null)
{
await virtualize.RefreshDataAsync();
}
if(groupVirtualize != null)
{
await groupVirtualize.RefreshDataAsync();
}
}
#endif
}
}
#endif
}
}
async Task InvokeLoadData(int start, int top)
{
var orderBy = GetOrderBy();
Query.Skip = skip;
Query.Top = PageSize;
Query.OrderBy = orderBy;
var filterString = allColumns.ToList().ToFilterString<TItem>();
Query.Filter = filterString;
if (LoadData.HasDelegate)
{
var filters = allColumns.ToList().Where(c => c.Filterable && c.Visible && (c.GetFilterValue() != null
|| c.GetFilterOperator() == FilterOperator.IsNotNull || c.GetFilterOperator() == FilterOperator.IsNull)).Select(c => new FilterDescriptor()
{
Property = c.GetFilterProperty(),
FilterValue = c.GetFilterValue(),
FilterOperator = c.GetFilterOperator(),
SecondFilterValue = c.GetSecondFilterValue(),
SecondFilterOperator = c.GetSecondFilterOperator(),
LogicalFilterOperator = c.GetLogicalFilterOperator()
});
await LoadData.InvokeAsync(new Radzen.LoadDataArgs()
{
Skip = start,
Top = top,
OrderBy = orderBy,
Filter = IsOData() ? allColumns.ToList().ToODataFilterString<TItem>() : filterString,
Filters = filters,
Sorts = sorts
});
}
}
internal async Task ChangeState()
{
@@ -1108,24 +1308,29 @@ namespace Radzen.Blazor
internal Dictionary<RadzenDataGridGroupRow<TItem>, bool> collapsedGroupItems = new Dictionary<RadzenDataGridGroupRow<TItem>, bool>();
internal string ExpandedGroupItemStyle(RadzenDataGridGroupRow<TItem> item)
internal string ExpandedGroupItemStyle(RadzenDataGridGroupRow<TItem> item, bool? expandedOnLoad)
{
return collapsedGroupItems.Keys.Contains(item) ? "rz-row-toggler rzi-grid-sort rzi-chevron-circle-right" : "rz-row-toggler rzi-grid-sort rzi-chevron-circle-down";
return collapsedGroupItems.Keys.Contains(item) || expandedOnLoad == false ? "rz-row-toggler rzi-grid-sort rzi-chevron-circle-right" : "rz-row-toggler rzi-grid-sort rzi-chevron-circle-down";
}
internal bool IsGroupItemExpanded(RadzenDataGridGroupRow<TItem> item)
{
return !collapsedGroupItems.Keys.Contains(item) ;
return !collapsedGroupItems.Keys.Contains(item);
}
internal async System.Threading.Tasks.Task ExpandGroupItem(RadzenDataGridGroupRow<TItem> item)
internal async System.Threading.Tasks.Task ExpandGroupItem(RadzenDataGridGroupRow<TItem> item, bool? expandedOnLoad)
{
if (expandedOnLoad != null)
return;
if (!collapsedGroupItems.Keys.Contains(item))
{
await GroupRowCollapse.InvokeAsync(item.Group);
collapsedGroupItems.Add(item, true);
}
else
{
await GroupRowExpand.InvokeAsync(item.Group);
collapsedGroupItems.Remove(item);
}
@@ -1161,8 +1366,20 @@ namespace Radzen.Blazor
return new Tuple<Radzen.RowRenderEventArgs<TItem>, IReadOnlyDictionary<string, object>>(args, new System.Collections.ObjectModel.ReadOnlyDictionary<string, object>(args.Attributes));
}
internal Tuple<GroupRowRenderEventArgs, IReadOnlyDictionary<string, object>> GroupRowAttributes(RadzenDataGridGroupRow<TItem> item)
{
var args = new Radzen.GroupRowRenderEventArgs() { Group = item.Group, FirstRender = firstRender };
if (GroupRowRender != null)
{
GroupRowRender(args);
}
return new Tuple<GroupRowRenderEventArgs, IReadOnlyDictionary<string, object>>(args, new System.Collections.ObjectModel.ReadOnlyDictionary<string, object>(args.Attributes));
}
private bool visibleChanged = false;
private bool firstRender = true;
internal bool firstRender = true;
/// <inheritdoc />
public override async Task SetParametersAsync(ParameterView parameters)
@@ -1198,18 +1415,6 @@ namespace Radzen.Blazor
}
}
/// <summary>
/// Called after render.
/// </summary>
/// <param name="firstRender">if set to <c>true</c> first render.</param>
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
StateHasChanged();
}
}
/// <inheritdoc />
protected override async Task OnAfterRenderAsync(bool firstRender)
{
@@ -1274,6 +1479,13 @@ namespace Radzen.Blazor
await InvokeAsync(StateHasChanged);
}
/// <summary>
/// Gets or sets a value indicating whether DataGrid row can be selected on row click.
/// </summary>
/// <value><c>true</c> if DataGrid row can be selected on row click; otherwise, <c>false</c>.</value>
[Parameter]
public bool AllowRowSelectOnRowClick { get; set; } = true;
/// <summary>
/// Gets or sets the selection mode.
/// </summary>
@@ -1289,7 +1501,10 @@ namespace Radzen.Blazor
internal async Task OnRowClick(DataGridRowMouseEventArgs<TItem> args)
{
await RowClick.InvokeAsync(args);
await OnRowSelect(args.Data);
if (AllowRowSelectOnRowClick)
{
await OnRowSelect(args.Data);
}
}
internal async System.Threading.Tasks.Task OnRowSelect(object item, bool raiseChange = true)
@@ -1475,13 +1690,18 @@ namespace Radzen.Blazor
}
else
{
#if NET5
#if NET5
itemToInsert = default(TItem);
if (virtualize != null)
if(virtualize != null)
{
virtualize.RefreshDataAsync();
}
#endif
if(groupVirtualize != null)
{
groupVirtualize.RefreshDataAsync();
}
#endif
}
}
else
@@ -1526,15 +1746,20 @@ namespace Radzen.Blazor
}
else
{
#if NET5
if (virtualize != null)
#if NET5
if(virtualize != null)
{
await virtualize.RefreshDataAsync();
}
#endif
if(groupVirtualize != null)
{
await groupVirtualize.RefreshDataAsync();
}
#endif
}
await EditRowInternal(item);
await EditRowInternal(item);
}
@@ -1556,7 +1781,7 @@ namespace Radzen.Blazor
{
if (!AllowMultiColumnSorting)
{
foreach (var c in columns.Where(c => c != column))
foreach (var c in allColumns.ToList().Where(c => c != column))
{
c.SetSortOrder(null);
}
@@ -1613,7 +1838,7 @@ namespace Radzen.Blazor
internal List<GroupDescriptor> groups = new List<GroupDescriptor>();
internal void EndColumnDropToGroup()
internal async Task EndColumnDropToGroup()
{
if(indexOfColumnToReoder != null)
{
@@ -1624,9 +1849,14 @@ namespace Radzen.Blazor
var descriptor = groups.Where(d => d.Property == column.GetGroupProperty()).FirstOrDefault();
if (descriptor == null)
{
descriptor = new GroupDescriptor() { Property = column.GetGroupProperty(), Title = column.Title };
descriptor = new GroupDescriptor() { Property = column.GetGroupProperty(), Title = column.Title, SortOrder = column.GetSortOrder() };
groups.Add(descriptor);
_groupedPagedView = null;
if (IsVirtualizationAllowed())
{
await Reload();
}
}
}
@@ -1642,7 +1872,8 @@ namespace Radzen.Blazor
{
var p = IsOData() ? property.Replace('.', '/') : PropertyAccess.GetProperty(property);
var column = columns.Where(c => c.GetSortProperty() == property).FirstOrDefault();
var column = allColumns.ToList().Where(c => c.GetSortProperty() == property).FirstOrDefault();
if (column != null)
{
SetColumnSortOrder(column);
@@ -1662,7 +1893,7 @@ namespace Radzen.Blazor
/// <param name="property">The property name.</param>
public void OrderByDescending(string property)
{
var column = columns.Where(c => c.GetSortProperty() == property).FirstOrDefault();
var column = allColumns.ToList().Where(c => c.GetSortProperty() == property).FirstOrDefault();
if (column != null)
{
column.SetSortOrder(SortOrder.Descending);
@@ -1685,6 +1916,11 @@ namespace Radzen.Blazor
additionalClasses.Add("rz-selectable");
}
if (Responsive)
{
additionalClasses.Add("rz-datatable-reflow");
}
return $"rz-has-paginator rz-datatable rz-datatable-scrollable {String.Join(" ", additionalClasses)}";
}
@@ -1708,22 +1944,20 @@ namespace Radzen.Blazor
}
}
internal bool disposed = false;
/// <inheritdoc />
public override void Dispose()
{
base.Dispose();
disposed = true;
if (IsJSRuntimeAvailable)
{
foreach (var column in columns.Where(c => c.Visible))
foreach (var column in allColumns.ToList().Where(c => c.Visible))
{
JSRuntime.InvokeVoidAsync("Radzen.destroyPopup", $"{PopupID}{column.GetFilterProperty()}");
}
}
}
internal int deepestChildColumnLevel;
}
}

View File

@@ -1,13 +1,69 @@
@typeparam TItem
<td @attributes="@Attributes" style="@GetStyle()" class="@GetCssClass()" @onclick="@OnClick" @ondblclick="@OnDblClick" @oncontextmenu="@OnContextMenu" @oncontextmenu:preventDefault="@Grid.CellContextMenu.HasDelegate">
@using Microsoft.AspNetCore.Components.Forms
<CascadingValue Value=@EditContext>
<CascadingValue Value=Row>
@if (Grid.AllowCompositeDataCells ? RowIndex == Column.GetLevel() : (Column.Parent != null && RowIndex == Column.GetLevel() || Column.Columns == null))
{
<td rowspan="@(Column.GetRowSpan(true))" colspan="@(Column.GetColSpan(true))" @attributes="@Attributes" style="@GetStyle()" class="@GetCssClass()" @onclick="@OnClick" @ondblclick="@OnDblClick" @oncontextmenu="@OnContextMenu" @oncontextmenu:preventDefault="@Grid.CellContextMenu.HasDelegate">
<CascadingValue Value=this>
@ChildContent
</CascadingValue>
</td>
}
else
{
@foreach(var column in Grid.childColumns.Where(c => c.Visible && c.Parent == Column))
{
<RadzenDataGridCell Row=@Row EditContext=EditContext RowIndex="@RowIndex" Grid="@Grid" Column="@column" Item="@Item"
Style="@column.GetStyle(true)" CssClass="@(column.CssClass + " " + Grid.getFrozenColumnClass(column, Grid.ColumnsCollection) + " " + (column.Columns != null || column.Parent != null ? "rz-composite-cell" : ""))" Attributes="@(Grid.CellAttributes(Item, column))">
@if (Grid.Responsive)
{
<span class="rz-column-title">
@if (column.HeaderTemplate != null)
{
@column.HeaderTemplate
}
else
{
@column.Title
}
</span>
}
<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>
</RadzenDataGridCell>
}
}
</CascadingValue>
</CascadingValue>
@code {
[Parameter(CaptureUnmatchedValues = true)]
public IReadOnlyDictionary<string, object> Attributes { get; set; }
[Parameter]
public int RowIndex { get; set; }
[Parameter]
public RadzenDataGridRow<TItem> Row { get; set; }
[Parameter]
public EditContext EditContext { get; set; }
[Parameter]
public RenderFragment ChildContent { get; set; }

View File

@@ -22,6 +22,74 @@ namespace Radzen.Blazor
[CascadingParameter]
public RadzenDataGrid<TItem> Grid { get; set; }
/// <summary>
/// Gets or sets the columns.
/// </summary>
/// <value>The columns.</value>
[Parameter]
public RenderFragment Columns { get; set; }
/// <summary>
/// Gets or sets the parent column.
/// </summary>
/// <value>The parent column.</value>
[CascadingParameter]
public RadzenDataGridColumn<TItem> Parent { get; set; }
internal void RemoveColumn(RadzenDataGridColumn<TItem> column)
{
if (Grid.childColumns.Contains(column))
{
Grid.childColumns.Remove(column);
if (!Grid.disposed)
{
try { InvokeAsync(StateHasChanged); } catch { }
}
}
}
internal int GetLevel()
{
int i = 0;
var p = Parent;
while (p != null)
{
p = p.Parent;
i++;
}
return i;
}
internal int GetColSpan(bool isDataCell = false)
{
if (!Grid.AllowCompositeDataCells && isDataCell)
return 1;
var directChildColumns = Grid.childColumns.Where(c => c.Visible && c.Parent == this);
if (Parent == null)
{
return Columns == null ? 1 : directChildColumns.Sum(c => c.GetColSpan());
}
return Columns == null ? 1 : directChildColumns.Count();
}
internal int GetRowSpan(bool isDataCell = false)
{
if (!Grid.AllowCompositeDataCells && isDataCell)
return 1;
if (Columns == null && Parent != null)
{
var level = this.GetLevel();
return level == Grid.deepestChildColumnLevel ? 1 : level + 1;
}
return Columns == null && Parent == null ? Grid.deepestChildColumnLevel + 1 : 1;
}
/// <summary>
/// Called when initialized.
/// </summary>
@@ -64,12 +132,31 @@ 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
{
if (Grid != null && Grid.selectedColumns != null)
{
return ((IEnumerable<object>)Grid.selectedColumns).Cast<RadzenDataGridColumn<TItem>>().Contains(this);
}
return _visible;
}
set
{
if (_visible != value)
{
_visible = value;
}
}
}
/// <summary>
/// Gets or sets the title.
@@ -127,6 +214,13 @@ namespace Radzen.Blazor
[Parameter]
public string Width { get; set; }
/// <summary>
/// Gets or sets the min-width.
/// </summary>
/// <value>The min-width.</value>
[Parameter]
public string MinWidth { get; set; }
/// <summary>
/// Gets or sets the format string.
/// </summary>
@@ -323,10 +417,10 @@ namespace Radzen.Blazor
style.Add($"text-align:{Enum.GetName(typeof(TextAlign), TextAlign).ToLower()};");
}
if (forCell && Frozen)
if (forCell && IsFrozen())
{
var left = Grid.ColumnsCollection
.TakeWhile((c, i) => Grid.ColumnsCollection.IndexOf(this) > i && c.Frozen)
.TakeWhile((c, i) => Grid.ColumnsCollection.IndexOf(this) > i && c.IsFrozen())
.Sum(c => {
var w = !string.IsNullOrEmpty(c.GetWidth()) ? c.GetWidth() : Grid.ColumnWidth;
var cw = 200;
@@ -340,14 +434,24 @@ namespace Radzen.Blazor
style.Add($"left:{left}px");
}
if ((isHeaderOrFooterCell && Frozen || isHeaderOrFooterCell && !Frozen || !isHeaderOrFooterCell && Frozen) && Grid.ColumnsCollection.Where(c => c.Visible && c.Frozen).Any())
if ((isHeaderOrFooterCell && IsFrozen() || isHeaderOrFooterCell && !IsFrozen() || !isHeaderOrFooterCell && IsFrozen()) && Grid.ColumnsCollection.Where(c => c.Visible && c.IsFrozen()).Any())
{
style.Add($"z-index:{(isHeaderOrFooterCell && Frozen ? 2 : 1)}");
style.Add($"z-index:{(isHeaderOrFooterCell && IsFrozen() ? 2 : 1)}");
}
if (!string.IsNullOrEmpty(MinWidth))
{
style.Add($"min-width:{MinWidth}");
}
return string.Join(";", style);
}
internal bool IsFrozen()
{
return Frozen && Parent == null && Columns == null;
}
/// <summary>
/// Gets the sort property.
/// </summary>
@@ -456,10 +560,24 @@ namespace Radzen.Blazor
if (parameters.DidParameterChange(nameof(FilterValue), FilterValue))
{
filterValue = parameters.GetValueOrDefault<object>(nameof(FilterValue));
if (FilterTemplate != null)
{
FilterValue = filterValue;
await Grid.Reload();
if (Grid.IsVirtualizationAllowed())
{
#if NET5
if (Grid.virtualize != null)
{
await Grid.virtualize.RefreshDataAsync();
}
#endif
}
else
{
await Grid.Reload();
}
return;
}
}
@@ -580,7 +698,9 @@ namespace Radzen.Blazor
{
return Enum.GetValues(typeof(FilterOperator)).Cast<FilterOperator>().Where(o => {
var isStringOperator = o == FilterOperator.Contains || o == FilterOperator.DoesNotContain || o == FilterOperator.StartsWith || o == FilterOperator.EndsWith;
return FilterPropertyType == typeof(string) ? isStringOperator || o == FilterOperator.Equals || o == FilterOperator.NotEquals : !isStringOperator;
return FilterPropertyType == typeof(string) ? isStringOperator
|| o == FilterOperator.Equals || o == FilterOperator.NotEquals || o == FilterOperator.IsNull || o == FilterOperator.IsNotNull
: !isStringOperator;
});
}
@@ -608,6 +728,10 @@ namespace Radzen.Blazor
return Grid?.StartsWithText;
case FilterOperator.NotEquals:
return Grid?.NotEqualsText;
case FilterOperator.IsNull:
return Grid?.IsNullText;
case FilterOperator.IsNotNull:
return Grid?.IsNotNullText;
default:
return $"{filterOperator}";
}

View File

@@ -0,0 +1,11 @@
@typeparam TItem
@inherits ComponentBase
@if (Columns != null)
{
<CascadingValue Value=this.Grid>
<CascadingValue Value=this>
@Columns
</CascadingValue>
</CascadingValue>
}

View File

@@ -0,0 +1,37 @@
@typeparam TItem
@if (RowIndex == Column.GetLevel())
{
<td rowspan="@(Column.GetRowSpan())" colspan="@(Column.GetColSpan())" @attributes="@Attributes" class="@CssClass" scope="col" style="@Column.GetStyle(true, true)">
<span class="rz-column-footer">
@if (Column.FooterTemplate != null)
{
@Column.FooterTemplate
}
</span>
</td>
}
else
{
@foreach(var column in Grid.childColumns.Where(c => c.Visible && c.Parent == Column))
{
<RadzenDataGridFooterCell RowIndex="@RowIndex" Grid="@Grid" Column="@column"
CssClass="@($"{Column.FooterCssClass} {Grid.getFrozenColumnClass(column, Grid.ColumnsCollection.Where(c => c.Visible).ToList())} {(column.Columns != null || column.Parent != null ? "rz-composite-cell" : "")}")"
Attributes="@(Attributes)" />
}
}
@code {
[Parameter(CaptureUnmatchedValues = true)]
public IReadOnlyDictionary<string, object> Attributes { get; set; }
[Parameter]
public RadzenDataGridColumn<TItem> Column { get; set; }
[Parameter]
public int RowIndex { get; set; }
[Parameter]
public RadzenDataGrid<TItem> Grid { get; set; }
[Parameter]
public string CssClass { get; set; }
}

View File

@@ -1,6 +1,12 @@
@typeparam TItem
@using System.Linq.Dynamic.Core
<tr>
@if (Grid.Template != null && Grid.ShowExpandColumn)
{
<th class="rz-col-icon rz-unselectable-text" scope="col">
<span class="rz-column-title"></span>
</th>
}
@for(var i = 0; i < GetLevel(); i++)
{
<td class="rz-col-icon">

View File

@@ -1,16 +1,23 @@
@typeparam TItem
@using System.Linq.Dynamic.Core
<tr>
@for(var i = 0; i < GetLevel(); i++)
@{
var rowArgs = Grid?.GroupRowAttributes(this);
}
<tr @attributes="@rowArgs.Item2">
@if (Group.GroupDescriptor != null)
{
<td class="rz-col-icon">
<span class="rz-column-title"></span>
</td>
@for (var i = 0; i < GetLevel(); i++)
{
<td class="rz-col-icon">
<span class="rz-column-title"></span>
</td>
}
}
<td class="rz-col-icon">
<span class="rz-column-title"></span>
<a href="javascript:void(0)" @onclick="@(_ => Grid.ExpandGroupItem(this))">
<span class="@(Grid.ExpandedGroupItemStyle(this))"></span>
<a href="javascript:void(0)" @onclick="@(_ => Grid.ExpandGroupItem(this, rowArgs.Item1.Expanded))">
<span class="@(Grid.ExpandedGroupItemStyle(this, rowArgs.Item1.Expanded))"></span>
</a>
</td>
<td colspan="@(Columns.Count + Grid.groups.Count - 1 - Group.Level)">
@@ -19,16 +26,16 @@
{
@Grid.GroupHeaderTemplate(Group)
}
else
else if(Group.GroupDescriptor != null)
{
@(Group.GroupDescriptor.GetTitle() + ": " + Group.Data.Key)
@(Group.GroupDescriptor.GetTitle() + ": " + (Group.Data.Key ?? ""))
}
</span>
</td>
</tr>
@if(Grid != null)
{
if (Grid.IsGroupItemExpanded(this))
if (Grid.IsGroupItemExpanded(this) && rowArgs.Item1.Expanded != false)
{
@DrawDataRows()
}
@@ -59,7 +66,7 @@
Group = new Group()
{
Level = level,
GroupDescriptor = Grid.groups[level],
GroupDescriptor = Grid.groups?.ElementAtOrDefault(level),
Data = _groupResult
};
}

View File

@@ -0,0 +1,160 @@
@typeparam TItem
@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">
@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>
}
<span class="rz-column-title">
@if (Column.HeaderTemplate != null)
{
@Column.HeaderTemplate
}
else
{
@Column.Title
}
</span>
@if (Grid.AllowSorting && Column.Sortable)
{
@if (Column.GetSortOrder() == SortOrder.Ascending)
{
<span class="rz-sortable-column-icon rzi-grid-sort rzi-sort rzi-sort-asc"></span>
}
else if (Column.GetSortOrder() == SortOrder.Descending)
{
<span class="rz-sortable-column-icon rzi-grid-sort rzi-sort rzi-sort-desc"></span>
}
else
{
<span class="rz-sortable-column-icon rzi-grid-sort rzi-sort"></span>
}
}
@if (Grid.AllowColumnResize && Column.Resizable && Column.Parent == null)
{
<div id="@Grid.getColumnResizerId(ColumnIndex)" style="cursor:col-resize;float:right;"
@onclick:preventDefault="true" @onclick:stopPropagation="true" class="rz-column-resizer"
@onmousedown=@(args => Grid.StartColumnResize(args, ColumnIndex))>&nbsp;</div>
}
@if (Grid.AllowFiltering && Column.Filterable && Grid.FilterMode == FilterMode.Advanced)
{
<i @onclick:stopPropagation="true" onclick="@($"Radzen.togglePopup(this, '{Grid.PopupID}{Column.GetFilterProperty()}')")"
class="@getFilterIconCss(Column)" />
<div id="@($"{Grid.PopupID}{Column.GetFilterProperty()}")" class="rz-overlaypanel"
style="display:none;min-width:250px;" tabindex="0">
<div class="rz-grid-filter rz-overlaypanel-content">
@if (Column.FilterTemplate != null)
{
@Column.FilterTemplate(Column)
}
else
{
<RadzenLabel Text="@Grid.FilterText" class="rz-grid-filter-label" />
<RadzenDropDown @onclick:preventDefault="true" Data="@(Column.GetFilterOperators().Select(t => new { Value = Column.GetFilterOperatorText(t), Key = t }))" TextProperty="Value" ValueProperty="Key" TValue="FilterOperator" Value="@Column.GetFilterOperator()" Change="@(args => Column.SetFilterOperator((FilterOperator)args))" />
@if (PropertyAccess.IsNumeric(Column.FilterPropertyType))
{
@(Grid.DrawNumericFilter(Column, false))
}
else if (PropertyAccess.IsDate(Column.FilterPropertyType))
{
<RadzenDatePicker TValue="@object" ShowTime="true" ShowTimeOkButton="true" DateFormat="@Grid.getFilterDateFormat(Column)"
Value="@Column.GetFilterValue()" Change="@(args => Column.SetFilterValue(args.Value))" />
}
else if (Column.FilterPropertyType == typeof(bool) || Column.FilterPropertyType == typeof(bool?))
{
<RadzenCheckBox TriState="true" TValue="@object" Value="@Column.GetFilterValue()" Change="@(args => Column.SetFilterValue(args))" />
}
else
{
<RadzenTextBox Value="@($"{Column.GetFilterValue()}")" Change="@(args => Column.SetFilterValue(args))" />
}
<RadzenDropDown @onclick:preventDefault="true" TextProperty="Text" ValueProperty="Value" Style="width: 80px"
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))" />
@if (PropertyAccess.IsNumeric(Column.FilterPropertyType))
{
@(Grid.DrawNumericFilter(Column, false, false))
}
else if (PropertyAccess.IsDate(Column.FilterPropertyType))
{
<RadzenDatePicker TValue="@object"
ShowTime="true" 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))"/>
}
else
{
<RadzenTextBox Value="@($"{Column.GetSecondFilterValue()}")" Change="@(args => Column.SetFilterValue(args, false))" />
}
}
</div>
@if (Column.FilterTemplate == null)
{
<div class="rz-grid-filter-buttons">
<RadzenButton ButtonStyle="ButtonStyle.Secondary" Text=@Grid.ClearFilterText Click="@((args) => Grid.ClearFilter(Column, true))" />
<RadzenButton ButtonStyle="ButtonStyle.Primary" Text=@Grid.ApplyFilterText Click="@((args) => Grid.ApplyFilter(Column, true))" />
</div>
}
</div>
}
</div>
</th>
}
else
{
@foreach(var column in Grid.childColumns.Where(c => c.Visible && 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.Visible).ToList())} {(column.Columns != null || column.Parent != null ? "rz-composite-cell" : "")}".Trim())" />
}
}
@code {
[Parameter(CaptureUnmatchedValues = true)]
public IReadOnlyDictionary<string, object> Attributes { get; set; }
[Parameter]
public RadzenDataGridColumn<TItem> Column { get; set; }
[Parameter]
public int ColumnIndex { get; set; }
[Parameter]
public int RowIndex { get; set; }
[Parameter]
public RadzenDataGrid<TItem> Grid { get; set; }
[Parameter]
public string CssClass { get; set; }
private int SortingTabIndex => Grid.AllowSorting && Column.Sortable ? 0 : -1;
private string getFilterIconCss(RadzenDataGridColumn<TItem> column)
{
var additionalStyle = column.GetFilterValue() != null || column.GetSecondFilterValue() != null ||
column.GetFilterOperator() == FilterOperator.IsNotNull || column.GetFilterOperator() == FilterOperator.IsNull
? "rz-grid-filter-active" : "";
return $"rzi rz-grid-filter-icon {additionalStyle}";
}
private void OnSortKeyPressed(KeyboardEventArgs args)
{
var key = args.Code ?? args.Key;
if (key == "Enter")
{
Grid.OnSort(args, Column);
}
}
}

View File

@@ -2,16 +2,19 @@
@typeparam TItem
@implements IRadzenForm
@{var rowArgs = Grid?.RowAttributes(Item); }
@{var firstLevel = Grid.AllowCompositeDataCells ? 0 : Grid.deepestChildColumnLevel; }
@for(var i = firstLevel; i < Grid.deepestChildColumnLevel + 1; i++)
{
<tr class="@(Grid.RowStyle(Item, Index))" @attributes="@rowArgs.Item2">
@foreach(var g in Grid.groups)
{
<td class="rz-col-icon">
<td class="rz-col-icon" rowspan="@(Grid.AllowCompositeDataCells ? (Grid.deepestChildColumnLevel + 1) : 1)">
<span class="rz-column-title"></span>
</td>
}
@if (Grid.Template != null && Grid.ShowExpandColumn)
@if (Grid.Template != null && Grid.ShowExpandColumn && i == firstLevel)
{
<td class="rz-col-icon">
<td class="rz-col-icon" rowspan="@(Grid.AllowCompositeDataCells ? (Grid.deepestChildColumnLevel + 1) : 1)">
<span class="rz-column-title"></span>
@if (rowArgs.Item1.Expandable)
{
@@ -21,8 +24,7 @@
}
</td>
}
<CascadingValue Value=@EditContext>
<CascadingValue Value=this>
@for (var j = 0; j < Columns.Count; j++)
{
if (Grid.rowSpans.ContainsKey(j))
@@ -58,8 +60,21 @@
Grid.rowSpans.Add(j, (int)Convert.ChangeType(rowspan, TypeCode.Int32));
}
<RadzenDataGridCell Grid="@this.Grid" Item="@Item" Column="@column"
Style="@column.GetStyle(true)" CssClass="@(column.CssClass + " " + Grid.getFrozenColumnClass(column, Columns))" Attributes="@(cellAttr)">
<RadzenDataGridCell Row=@this EditContext=EditContext RowIndex="@i" Grid="@this.Grid" Item="@Item" Column="@column"
Style="@column.GetStyle(true)" CssClass="@(column.CssClass + " " + Grid.getFrozenColumnClass(column, Columns) + " " + (column.Columns != null || column.Parent != null ? "rz-composite-cell" : ""))" Attributes="@(cellAttr)">
@if (Grid.Responsive)
{
<span class="rz-column-title">
@if (column.HeaderTemplate != null)
{
@column.HeaderTemplate
}
else
{
@column.Title
}
</span>
}
<span class="rz-cell-data" title="@(column.Template == null ? column.GetValue(Item) : "")">
@if (Item != null)
{
@@ -79,9 +94,10 @@
</span>
</RadzenDataGridCell>
}
</CascadingValue>
</CascadingValue>
</tr>
}
@if (Grid.Template != null && Grid.expandedItems.Keys.Contains(Item))
{
<tr class="rz-expanded-row-content">

View File

@@ -6,7 +6,7 @@
<div @ref="@Element" @attributes="Attributes" class="@GetCssClass()" style="@Style" id="@GetId()">
@if (AllowPaging && (PagerPosition == PagerPosition.Top || PagerPosition == PagerPosition.TopAndBottom))
{
<RadzenPager @ref="topPager" Count="@Count" PageSize="@PageSize" PageNumbersCount="@PageNumbersCount" PageChanged="@OnPageChanged" PageSizeChanged="@OnPageSizeChanged" PageSizeOptions="@PageSizeOptions" ShowPagingSummary="@ShowPagingSummary" PagingSummaryFormat="@PagingSummaryFormat" />
<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" />
}
@if (Data != null)
{
@@ -47,7 +47,7 @@
}
@if (AllowPaging && (PagerPosition == PagerPosition.Bottom || PagerPosition == PagerPosition.TopAndBottom))
{
<RadzenPager @ref="bottomPager" Count="@Count" PageSize="@PageSize" PageNumbersCount="@PageNumbersCount" PageChanged="@OnPageChanged" PageSizeChanged="@OnPageSizeChanged" PageSizeOptions="@PageSizeOptions" ShowPagingSummary="@ShowPagingSummary" PagingSummaryFormat="@PagingSummaryFormat" class="rz-paginator-bottom" />
<RadzenPager HorizontalAlign="@PagerHorizontalAlign" AlwaysVisible="@PagerAlwaysVisible" @ref="bottomPager" Count="@Count" PageSize="@PageSize" PageNumbersCount="@PageNumbersCount" PageChanged="@OnPageChanged" PageSizeChanged="@OnPageSizeChanged" PageSizeOptions="@PageSizeOptions" ShowPagingSummary="@ShowPagingSummary" PagingSummaryFormat="@PagingSummaryFormat" PageSizeText="@PageSizeText" class="rz-paginator-bottom" />
}
</div>
}

View File

@@ -15,7 +15,7 @@
{
<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"
@onchange="@ParseDate" autocomplete="off" type="text"
@onchange="@ParseDate" autocomplete="off" type="text" name="@Name"
class="rz-inputtext @InputClass" id="@Name" placeholder="@Placeholder" />
<button 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>
@@ -26,111 +26,115 @@
}
</span>
}
<div id="@PopupID" style=@PopupStyle class="@($"{(Inline ? "rz-datepicker-inline " : "")}rz-datepicker")" @onclick:preventDefault="true">
<div class="rz-datepicker-group">
@if (!TimeOnly)
{
<div class="rz-datepicker-header">
<a href="javascript:void(0)" class="rz-datepicker-prev" @onclick="@(async () => { if (!Disabled) { CurrentDate = CurrentDate.AddMonths(-1); } })">
<span class="rz-datepicker-prev-icon rzi rzi-chevron-left"></span>
</a>
<a href="javascript:void(0)" class="rz-datepicker-next" @onclick="@(async () => { if (!Disabled) { CurrentDate = CurrentDate.AddMonths(1); } })">
<span class="rz-datepicker-next-icon rzi rzi-chevron-right"></span>
</a>
<div class="rz-datepicker-title" style="height:40px;">
<RadzenDropDown @ref="monthDropDown" Style="height:auto;width:120px;margin-top:5px;text-align:left;" TabIndex="-1"
<div id="@PopupID" style=@PopupStyle class="@($"{(Inline ? "rz-datepicker-inline " : "")}rz-datepicker")" @onclick:preventDefault="true">
<div class="rz-datepicker-group">
@if (!TimeOnly)
{
<div class="rz-datepicker-header">
<a href="javascript:void(0)" class="rz-datepicker-prev" @onclick="@(async () => { if (!Disabled) { CurrentDate = CurrentDate.AddMonths(-1); } })">
<span class="rz-datepicker-prev-icon rzi rzi-chevron-left"></span>
</a>
<a href="javascript:void(0)" class="rz-datepicker-next" @onclick="@(async () => { if (!Disabled) { CurrentDate = CurrentDate.AddMonths(1); } })">
<span class="rz-datepicker-next-icon rzi rzi-chevron-right"></span>
</a>
<div class="rz-datepicker-title" style="height:40px;">
<RadzenDropDown @ref="monthDropDown" Style="height:auto;width:120px;margin-top:5px;text-align:left;" TabIndex="-1"
TValue="int" Value="@CurrentDate.Month" Disabled="@Disabled" Data="@months" TextProperty="Name" ValueProperty="Value"
Change="@((args) => { SetMonth(int.Parse(args.ToString())); })" />
<RadzenDropDown @ref="yearDropDown" Style="height:auto;width:80px;margin-top:5px;text-align:left;" TabIndex="-1"
<RadzenDropDown @ref="yearDropDown" Style="height:auto;width:80px;margin-top:5px;text-align:left;" TabIndex="-1"
TValue="int" Value="@CurrentDate.Year" Disabled="@Disabled" Data="@years" TextProperty="Name" ValueProperty="Value"
Change="@((args) => { SetYear(int.Parse(args.ToString())); })" />
</div>
</div>
</div>
<div class="rz-datepicker-calendar-container">
<table class="rz-datepicker-calendar" style="@(Inline ? "" : "width:100%")">
<thead>
<tr>
@foreach (var day in AbbreviatedDayNames)
{
<th scope="col">
<span>@day</span>
</th>
}
</tr>
</thead>
<tbody>
@{int dayNumber = 0;}
@for (int i = 0; i < 6; i++)
{
<div class="rz-datepicker-calendar-container">
<table class="rz-datepicker-calendar" style="@(Inline ? "" : "width:100%")">
<thead>
<tr>
@for (int j = 0; j < 7; j++)
@foreach (var day in AbbreviatedDayNames)
{
DateTime date = StartDate.AddDays(dayNumber++);
var dateArgs = DateAttributes(date);
@if (CurrentDate.Month == date.Month)
{
<td @attributes="@(dateArgs.Attributes)" onmouseup=@(Inline || ShowTime ? "" : $"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>
</td>
}
else
{
<td @attributes="@(dateArgs.Attributes)" class="rz-datepicker-other-month" onmouseup=@(Inline || ShowTime ? "" : $"Radzen.closePopup('{PopupID}')")
@onclick="@(async () => { if (!Disabled && !dateArgs.Disabled) { await SetDay(date); } })">
<span class="rz-state-default rz-state-disabled">@date.Day</span>
</td>
}
<th scope="col">
<span>@day</span>
</th>
}
</tr>
}
</tbody>
</table>
</thead>
<tbody>
@{
int dayNumber = 0;
}
@for (int i = 0; i < 6; i++)
{
<tr>
@for (int j = 0; j < 7; j++)
{
DateTime date = StartDate.AddDays(dayNumber++);
var dateArgs = DateAttributes(date);
@if (CurrentDate.Month == date.Month)
{
<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>
</td>
}
else
{
<td @attributes="@(dateArgs.Attributes)" class="rz-datepicker-other-month" onmouseup=@(Inline || ShowTime || dateArgs.Disabled ? "" : $"Radzen.closePopup('{PopupID}')")
@onclick="@(async () => { if (!Disabled && !dateArgs.Disabled) { await SetDay(date); } })">
<span class="rz-state-default rz-state-disabled">@date.Day</span>
</td>
}
}
</tr>
}
</tbody>
</table>
</div>
}
</div>
@if (ShowTime)
{
<div class="rz-timepicker">
<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 />
<div class="rz-separator">
<span>:</span>
</div>
<RadzenNumeric TValue="int" Disabled="@Disabled" Value="CurrentDate.Minute" TValue="double" Step="@MinutesStep" Min="0" Max="59"
Change="@UpdateMinutes" class="rz-minute-picker" @oninput=@OnUpdateHourMinutes />
@if (ShowSeconds)
{
<div class="rz-separator">
<span>:</span>
</div>
<RadzenNumeric TValue="int" Disabled="@Disabled" Value="CurrentDate.Second" TValue="double" Step="@SecondsStep" Min="0" Max="59"
Change="@UpdateSeconds" class="rz-second-picker" @oninput=@OnUpdateHourSeconds />
}
@if (HourFormat == "12")
{
<div class="rz-ampm-picker">
<a href="javascript:void(0)" @onclick="@AmToPm">
<span class="rzi rzi-chevron-up"></span>
</a>
<span>@CurrentDate.ToString("tt")</span>
<a href="javascript:void(0)" @onclick="@PmToAm">
<span class="rzi rzi-chevron-down"></span>
</a>
</div>
}
@if (ShowTimeOkButton)
{
<button type="button" class="rz-button rz-button-md btn-secondary" style="width:60px;padding:0px;margin-left:10px;"
@onclick="@OkClick"
onmouseup="@($"Radzen.closePopup('{PopupID}')")">
<span class="rz-button-text">Ok</span>
</button>
}
</div>
}
</div>
@if (ShowTime)
{
<div class="rz-timepicker">
<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 />
<div class="rz-separator">
<span>:</span>
</div>
<RadzenNumeric TValue="int" Disabled="@Disabled" Value="CurrentDate.Minute" TValue="double" Step="@MinutesStep" Min="0" Max="59"
Change="@UpdateMinutes" class="rz-minute-picker" @oninput=@OnUpdateHourMinutes />
@if (ShowSeconds)
{
<div class="rz-separator">
<span>:</span>
</div>
<RadzenNumeric TValue="int" Disabled="@Disabled" Value="CurrentDate.Second" TValue="double" Step="@SecondsStep" Min="0" Max="59"
Change="@UpdateSeconds" class="rz-second-picker" @oninput=@OnUpdateHourSeconds />
}
@if (HourFormat == "12")
{
<div class="rz-ampm-picker">
<a href="javascript:void(0)" @onclick="@AmToPm">
<span class="rzi rzi-chevron-up"></span>
</a>
<span>@CurrentDate.ToString("tt")</span>
<a href="javascript:void(0)" @onclick="@PmToAm">
<span class="rzi rzi-chevron-down"></span>
</a>
</div>
}
@if (ShowTimeOkButton)
{
<button type="button" class="rz-button rz-button-md btn-secondary" style="width:60px;padding:0px;margin-left:10px;"
@onclick="@OkClick"
onmouseup="@($"Radzen.closePopup('{PopupID}')")">
<span class="rz-button-text">Ok</span>
</button>
}
</div>
}
</div>
</div>
}

View File

@@ -81,7 +81,8 @@ namespace Radzen.Blazor
var value = $"{args.Value}";
if (!string.IsNullOrWhiteSpace(value))
{
hour = (int)Convert.ChangeType(value, typeof(int));
int outValue;
hour = int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out outValue) ? (int?)outValue : null;
}
}
@@ -93,7 +94,9 @@ namespace Radzen.Blazor
var value = $"{args.Value}";
if (!string.IsNullOrWhiteSpace(value))
{
minutes = (int)Convert.ChangeType(value, typeof(int));
int outValue;
minutes = int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out outValue) ? (int?)outValue : null;
}
}
@@ -104,7 +107,8 @@ namespace Radzen.Blazor
var value = $"{args.Value}";
if (!string.IsNullOrWhiteSpace(value))
{
seconds = (int)Convert.ChangeType(value, typeof(int));
int outValue;
seconds = int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out outValue) ? (int?)outValue : null;
}
}
@@ -356,9 +360,16 @@ namespace Radzen.Blazor
set
{
_currentDate = value;
CurrentDateChanged.InvokeAsync(value);
}
}
/// <summary>
/// Gets or set the current date changed callback.
/// </summary>
[Parameter]
public EventCallback<DateTime> CurrentDateChanged { get; set; }
private DateTime StartDate
{
get
@@ -758,12 +769,12 @@ namespace Radzen.Blazor
{
if (ShowTimeOkButton)
{
CurrentDate = new DateTime(CurrentDate.Year, newValue.Month,newValue.Day, CurrentDate.Hour, CurrentDate.Minute, CurrentDate.Second);
CurrentDate = new DateTime(newValue.Year, newValue.Month,newValue.Day, CurrentDate.Hour, CurrentDate.Minute, CurrentDate.Second);
await OkClick();
}
else
{
var v = new DateTime(CurrentDate.Year, newValue.Month, newValue.Day, CurrentDate.Hour, CurrentDate.Minute, CurrentDate.Second);
var v = new DateTime(newValue.Year, newValue.Month, newValue.Day, CurrentDate.Hour, CurrentDate.Minute, CurrentDate.Second);
if (v != DateTimeValue)
{
DateTimeValue = v;

View File

@@ -13,7 +13,7 @@
return
@<CascadingValue Value=@Scheduler>
<DayView StartDate=@StartDate EndDate=@EndDate StartTime=@StartTime EndTime=@EndTime Appointments=@appointments
TimeFormat="@TimeFormat" />
TimeFormat=@TimeFormat MinutesPerSlot=@MinutesPerSlot />
</CascadingValue>
;
}

View File

@@ -40,6 +40,14 @@ namespace Radzen.Blazor
[Parameter]
public TimeSpan EndTime { get; set; } = TimeSpan.FromHours(24);
/// <summary>
/// Gets or sets slot size in minutes. Set to <c>30</c> by default.
/// </summary>
/// <value>The slot size in minutes.</value>
[Parameter]
public int MinutesPerSlot { get; set; } = 30;
/// <inheritdoc />
public override string Title
{

View File

@@ -42,14 +42,12 @@
{
Service.OnOpen -= OnOpen;
Service.OnClose -= OnClose;
Service.OnRefresh -= OnRefresh;
}
protected override void OnInitialized()
{
Service.OnOpen += OnOpen;
Service.OnClose += OnClose;
Service.OnRefresh += OnRefresh;
}
void OnOpen(string title, Type type, Dictionary<string, object> parameters, DialogOptions options)
@@ -61,9 +59,4 @@
{
Close(result).ConfigureAwait(false);
}
void OnRefresh()
{
InvokeAsync(StateHasChanged).ConfigureAwait(false);
}
}

View File

@@ -13,8 +13,8 @@
@onkeydown="@((args) => OnKeyPress(args))" id="@GetId()">
<div class="rz-helper-hidden-accessible">
<input disabled="@Disabled" style="width:100%" aria-haspopup="listbox" readonly="" type="text" tabindex="-1"
name="@Name" value="@(Value != null ? Value : "")"
aria-label="@(!Multiple && Value != null ? PropertyAccess.GetItemOrValueFromProperty(Value, TextProperty) : "")" />
name="@Name" value="@(internalValue != null ? internalValue : "")"
aria-label="@(!Multiple && internalValue != null ? PropertyAccess.GetItemOrValueFromProperty(internalValue, TextProperty) : "")" />
</div>
@if (Template != null && selectedItem != null)
@@ -23,7 +23,7 @@
@Template(selectedItem)
</label>
}
else if (selectedItem != null)
else if (selectedItem != null && !Multiple)
{
<label class="rz-dropdown-label rz-inputtext ">
@PropertyAccess.GetItemOrValueFromProperty(selectedItem, TextProperty)

View File

@@ -13,7 +13,7 @@
style="@Style" tabindex="@TabIndex" id="@GetId()">
<div class="rz-helper-hidden-accessible">
<input disabled="@Disabled" style="width:100%" aria-haspopup="listbox" readonly="" type="text"
name="@Name" aria-label="@(!Multiple && Value != null ? PropertyAccess.GetItemOrValueFromProperty(Value, TextProperty) : "")" />
name="@Name" aria-label="@(!Multiple && internalValue != null ? PropertyAccess.GetItemOrValueFromProperty(internalValue, TextProperty) : "")" />
</div>
@@ -23,7 +23,7 @@
@Template(selectedItem)
</label>
}
else if (selectedItem != null)
else if (selectedItem != null && !Multiple)
{
<label class="rz-dropdown-label rz-inputtext " onclick="@OpenPopupScript()" style="width:100%;">
@PropertyAccess.GetItemOrValueFromProperty(selectedItem, TextProperty)
@@ -74,6 +74,7 @@
<div class="rz-dropdown-trigger rz-corner-right" onclick="@OpenPopupScript()">
<span class="rz-dropdown-trigger-icon rzi rzi-chevron-down"></span>
</div>
<div id="@PopupID" class="@(Multiple ? "rz-multiselect-panel" : "rz-dropdown-panel")"
style="display:none;min-width:320px;padding:0px;">
<div class="rz-lookup-panel">
@@ -92,7 +93,7 @@
}
@if (Template != null)
{
<RadzenDataGrid ColumnWidth="@ColumnWidth" @ref="grid" Data="@(LoadData.HasDelegate ? (Data != null ? Data.Cast<object>() : Enumerable.Empty<object>()) : pagedData)" Count="@(LoadData.HasDelegate ? Count : count)" LoadData="@OnLoadData"
<RadzenDataGrid 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" 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)">
@@ -101,13 +102,16 @@
</Template>
</RadzenDataGridColumn>
</Columns>
<EmptyTemplate>
@EmptyTemplate
</EmptyTemplate>
</RadzenDataGrid>
}
else
{
if (!string.IsNullOrEmpty(TextProperty) || Columns != null)
{
<RadzenDataGrid 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 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" ShowPagingSummary="@ShowPagingSummary" PagingSummaryFormat="@PagingSummaryFormat" PageSize="@PageSize" PageNumbersCount="@PageNumbersCount" AllowPaging="@(!IsVirtualizationAllowed())" AllowSorting="@AllowSorting" RowSelect="@OnRowSelect" Style="@(IsVirtualizationAllowed() ? "height:285px" : "")">
<Columns>
@if (Columns != null)
@@ -119,11 +123,14 @@
<RadzenDataGridColumn TItem="object" Property="@TextProperty" Title="@TextProperty" Type="typeof(string)" />
}
</Columns>
<EmptyTemplate>
@EmptyTemplate
</EmptyTemplate>
</RadzenDataGrid>
}
else
{
<RadzenDataGrid 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 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" 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)">
@@ -132,11 +139,15 @@
</Template>
</RadzenDataGridColumn>
</Columns>
<EmptyTemplate>
@EmptyTemplate
</EmptyTemplate>
</RadzenDataGrid>
}
}
</div>
</div>
@if (AllowClear && (!Multiple && HasValue || Multiple && selectedItems.Count > 0))
{
<i class="rz-dropdown-clear-icon rzi rzi-times" @onclick="@Clear"></i>

View File

@@ -21,6 +21,34 @@ namespace Radzen.Blazor
/// </example>
public partial class RadzenDropDownDataGrid<TValue> : DropDownBase<TValue>
{
/// <summary>
/// Gets or sets the empty template shown when Data is empty collection.
/// </summary>
/// <value>The empty template.</value>
[Parameter]
public RenderFragment EmptyTemplate { get; set; }
/// <summary>
/// Gets or sets a value indicating whether pager is visible even when not enough data for paging.
/// </summary>
/// <value><c>true</c> if pager is visible even when not enough data for paging otherwise, <c>false</c>.</value>
[Parameter]
public bool PagerAlwaysVisible { get; set; }
/// <summary>
/// Gets or sets the horizontal align.
/// </summary>
/// <value>The horizontal align.</value>
[Parameter]
public HorizontalAlign PagerHorizontalAlign { get; set; } = HorizontalAlign.Justify;
/// <summary>
/// Gets or sets a value indicating whether column resizing is allowed.
/// </summary>
/// <value><c>true</c> if column resizing is allowed; otherwise, <c>false</c>.</value>
[Parameter]
public bool AllowColumnResize { get; set; }
/// <summary>
/// Gets or sets the width of all columns.
/// </summary>
@@ -33,7 +61,7 @@ namespace Radzen.Blazor
/// </summary>
/// <value><c>true</c> if responsive; otherwise, <c>false</c>.</value>
[Parameter]
public bool Responsive { get; set; } = true;
public bool Responsive { get; set; } = false;
/// <summary>
/// Gets or sets a value indicating whether search button is shown.
@@ -283,7 +311,7 @@ namespace Radzen.Blazor
}
else
{
selectedItem = Value;
selectedItem = internalValue;
}
SelectedItemChanged?.Invoke(selectedItem);
}
@@ -323,14 +351,14 @@ namespace Radzen.Blazor
return;
searchText = null;
Value = default(TValue);
internalValue = default(TValue);
selectedItem = null;
selectedItems.Clear();
await ValueChanged.InvokeAsync((TValue)Value);
await ValueChanged.InvokeAsync((TValue)internalValue);
if (FieldIdentifier.FieldName != null) { EditContext?.NotifyFieldChanged(FieldIdentifier); }
await Change.InvokeAsync(Value);
await Change.InvokeAsync(internalValue);
await grid.Reload();
@@ -465,11 +493,11 @@ namespace Radzen.Blazor
async Task OnRowSelect(object item)
{
await SelectItem(item);
if (!Disabled && !Multiple)
{
await JSRuntime.InvokeVoidAsync("Radzen.closePopup", PopupID);
}
await SelectItem(item);
}
/// <inheritdoc />

View File

@@ -9,8 +9,8 @@
{
<div @ref="@Element" style="@Style" @attributes="Attributes" class="@GetCssClass()" id="@GetId()">
<div class="rz-fileupload-buttonbar">
<span class="@ChooseClassList" label="Choose" tabindex="@TabIndex">
<input disabled="@Disabled" @ref="@fileUpload" name="@Name" type="file" accept="@Accept"
<span class="@ChooseClassList" label="Choose" tabindex="@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="@OnChange" />
<span class="rz-button-text">@ChooseText</span>
</span>
@@ -23,7 +23,7 @@
<div>
@if (IsImage)
{
<img style="@ImageStyle" src="@Value">
<img style="@ImageStyle" src="@Value" @onclick="@OnImageClick">
}
</div>
<div>

View File

@@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.JSInterop;
using Radzen.Blazor.Rendering;
using System;
@@ -116,6 +117,37 @@ namespace Radzen.Blazor
[Parameter]
public EventCallback<UploadErrorEventArgs> Error { get; set; }
/// <summary>
/// Gets or sets the image click callback.
/// </summary>
/// <value>The image click callback.</value>
[Parameter]
public EventCallback<MouseEventArgs> ImageClick { get; set; }
bool clicking;
/// <summary>
/// Handles the <see cref="E:ImageClick" /> event.
/// </summary>
/// <param name="args">The <see cref="MouseEventArgs"/> instance containing the event data.</param>
public async Task OnImageClick(MouseEventArgs args)
{
if (clicking)
{
return;
}
try
{
clicking = true;
await ImageClick.InvokeAsync(args);
}
finally
{
clicking = false;
}
}
async System.Threading.Tasks.Task Remove(EventArgs args)
{
Value = default(TValue);

View File

@@ -1,14 +1,26 @@
namespace Radzen.Blazor
using Microsoft.AspNetCore.Components;
using Radzen.Blazor.Rendering;
namespace Radzen.Blazor
{
/// <summary>
/// RadzenFooter component.
/// </summary>
public partial class RadzenFooter : RadzenComponentWithChildren
{
/// <summary>
/// The <see cref="RadzenLayout" /> this component is nested in.
/// </summary>
[CascadingParameter]
public RadzenLayout Layout { get; set; }
/// <inheritdoc />
protected override string GetComponentCssClass()
{
return "footer fixed";
return ClassList.Create("footer")
.Add("rz-footer")
.Add("fixed", Layout == null)
.ToString();
}
}
}

View File

@@ -168,7 +168,7 @@
}
@foreach (var column in visibleColumns)
{
<th class="@($" rz-unselectable-text")" tabindex="1" scope="col" style="@column.GetStyle(true)">
<th class="@($" rz-unselectable-text")" scope="col" style="@column.GetStyle(true)">
@if (AllowFiltering && column.Filterable && (!string.IsNullOrEmpty(column.GetFilterProperty()) || column.FilterTemplate != null))
{
<div class="rz-cell-filter">
@@ -182,8 +182,9 @@
<label class="rz-cell-filter-label" style="height:35px">
@if (column.Type == "string" && column.Format == "date-time")
{
<i onclick="@($"Radzen.togglePopup(this.parentNode, '{PopupID}{column.GetFilterProperty()}')")"
class="rzi">date_range</i>
<button class="rz-button rz-button-md rz-button-icon-only btn-light" onclick="@($"Radzen.togglePopup(this.parentNode, '{PopupID}{column.GetFilterProperty()}')")">
<i class="rzi">date_range</i>
</button>
@if (column.FilterValue != null)
{
<span class="rz-current-filter">@column.FilterValue</span>
@@ -239,7 +240,6 @@
}
else if (column.Type == "number")
{
<i class="rzi">search</i>
@(DrawNumericFilter(column))
}
else if (column.Type == "boolean")
@@ -248,8 +248,7 @@
}
else
{
<i class="rzi">search</i>
<input id="@(getFilterInputId(column))" @onchange="@((args) => OnFilter(args, column))" @onkeydown="@((args) => OnFilterKeyPress(args, column))" value="@column.FilterValue" type="text" />
<input id="@(getFilterInputId(column))" @onchange="@((args) => OnFilter(args, column))" @onkeydown="@((args) => OnFilterKeyPress(args, column))" value="@column.FilterValue" type="text" class="rz-textbox" style="width: 100%;" />
}
</label>
}
@@ -1369,14 +1368,10 @@
}
}
private bool disposed = false;
public override void Dispose()
{
base.Dispose();
disposed = true;
foreach (var column in columns.Where(c => c.Visible))
{
JSRuntime.InvokeVoidAsync("Radzen.destroyPopup", $"{PopupID}{column.GetFilterProperty()}");

View File

@@ -1,14 +1,26 @@
namespace Radzen.Blazor
using Microsoft.AspNetCore.Components;
using Radzen.Blazor.Rendering;
namespace Radzen.Blazor
{
/// <summary>
/// RadzenHeader component.
/// </summary>
public partial class RadzenHeader : RadzenComponentWithChildren
{
/// <summary>
/// The <see cref="RadzenLayout" /> this component is nested in.
/// </summary>
[CascadingParameter]
public RadzenLayout Layout { get; set; }
/// <inheritdoc />
protected override string GetComponentCssClass()
{
return "header fixed";
return ClassList.Create("header")
.Add("rz-header")
.Add("fixed", Layout == null)
.ToString();
}
}
}

View File

@@ -19,10 +19,16 @@ namespace Radzen.Blazor
[Parameter]
public string Icon { get; set; }
/// <summary>
/// Specifies the display style of the icon.
/// </summary>
[Parameter]
public IconStyle? IconStyle { get; set; }
/// <inheritdoc />
protected override string GetComponentCssClass()
{
return "rzi d-inline-flex justify-content-center align-items-center";
return $"rzi {(IconStyle.HasValue ? $"rzi-{IconStyle.Value.ToString().ToLower()} " : "")}d-inline-flex justify-content-center align-items-center";
}
}
}

View File

@@ -26,5 +26,11 @@ namespace Radzen.Blazor
/// <value>The text.</value>
[Parameter]
public string Text { get; set; } = "";
/// <inheritdoc />
protected override string GetComponentCssClass()
{
return "rz-label";
}
}
}

View File

@@ -0,0 +1,17 @@
using Microsoft.AspNetCore.Components;
using System.Linq;
namespace Radzen.Blazor
{
/// <summary>
/// RadzenLayout component.
/// </summary>
public partial class RadzenLayout : RadzenComponentWithChildren
{
/// <inheritdoc />
protected override string GetComponentCssClass()
{
return "rz-layout";
}
}
}

View File

@@ -0,0 +1,8 @@
@inherits RadzenComponentWithChildren
@if (Visible)
{
<div @ref=Element style=@Style @attributes=@Attributes class=@GetCssClass() id=@GetId()>
<CascadingValue Value=@this>@ChildContent</CascadingValue>
</div>
}

View File

@@ -198,10 +198,7 @@ namespace Radzen.Blazor
/// <param name="args">The <see cref="EventArgs"/> instance containing the event data.</param>
protected async Task OnReset(EventArgs args)
{
if (!string.IsNullOrEmpty(Username))
{
await ResetPassword.InvokeAsync(Username);
}
await ResetPassword.InvokeAsync(Username);
}
/// <summary>

View File

@@ -0,0 +1,92 @@
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
namespace Radzen.Blazor
{
/// <summary>
/// RadzenMediaQuery fires its <see cref="Change" /> event when the media query specified via <see cref="Query" /> matches or not.
/// </summary>
/// <example>
/// &lt; RadzenMediaQuery Query="(max-width: 768px)" Change=@OnChange /&gt;
/// @code {
/// void OnChange(bool matches)
/// {
/// // matches is true if the media query applies; otherwise false.
/// }
///}
/// </example>
public class RadzenMediaQuery : ComponentBase, IDisposable
{
[Inject]
IJSRuntime JSRuntime { get; set; }
/// <summary>
/// The CSS media query this component will listen for.
/// </summary>
[Parameter]
public string Query { get; set; }
/// <summary>
/// A callback that will be invoked when the status of the media query changes - to either match or not.
/// </summary>
[Parameter]
public EventCallback<bool> Change { get; set; }
/// <summary>
/// Invoked by interop when media query changes.
/// </summary>
[JSInvokable]
public async Task OnChange(bool matches)
{
await Change.InvokeAsync(matches);
}
bool initialized;
private DotNetObjectReference<RadzenMediaQuery> reference;
private DotNetObjectReference<RadzenMediaQuery> Reference
{
get
{
if (reference == null)
{
reference = DotNetObjectReference.Create(this);
}
return reference;
}
}
/// <summary>
/// Called by the Blazor runtime. Initializes the media query on the client-side.
/// </summary>
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
initialized = true;
var matches = await JSRuntime.InvokeAsync<bool>("Radzen.mediaQuery", Query, Reference);
await Change.InvokeAsync(matches);
}
}
/// <summary>
/// Detaches client-side event listeners.
/// </summary>
public void Dispose()
{
if (initialized)
{
JSRuntime.InvokeVoidAsync("Radzen.mediaQuery", Reference);
}
reference?.Dispose();
reference = null;
}
}
}

View File

@@ -1,5 +1,6 @@
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using System.Threading.Tasks;
namespace Radzen.Blazor
{
@@ -70,6 +71,13 @@ namespace Radzen.Blazor
[Parameter]
public RenderFragment ChildContent { get; set; }
/// <summary>
/// Gets or sets the click callback.
/// </summary>
/// <value>The click callback.</value>
[Parameter]
public EventCallback<MenuItemEventArgs> Click { get; set; }
/// <summary>
/// Gets or sets the parent.
/// </summary>
@@ -81,11 +89,34 @@ namespace Radzen.Blazor
/// Handles the <see cref="E:Click" /> event.
/// </summary>
/// <param name="args">The <see cref="MouseEventArgs"/> instance containing the event data.</param>
public async System.Threading.Tasks.Task OnClick(MouseEventArgs args)
public async Task OnClick(MouseEventArgs args)
{
if (Parent != null)
{
await Parent.Click.InvokeAsync(new MenuItemEventArgs() { Text = this.Text, Path = this.Path, Value = this.Value });
var eventArgs = new MenuItemEventArgs
{
Text = Text,
Path = Path,
Value = Value,
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,
};
await Parent.Click.InvokeAsync(eventArgs);
if (Click.HasDelegate)
{
await Click.InvokeAsync(eventArgs);
}
}
}
}

View File

@@ -193,7 +193,14 @@ namespace Radzen.Blazor
private async System.Threading.Tasks.Task InternalValueChanged(object value)
{
TValue newValue;
BindConverter.TryConvertTo<TValue>(RemoveNonNumericCharacters(value), Culture, out newValue);
try
{
BindConverter.TryConvertTo<TValue>(RemoveNonNumericCharacters(value), Culture, out newValue);
}
catch
{
newValue = default(TValue);
}
decimal? newValueAsDecimal = newValue == null ? default(decimal?) : (decimal)ConvertType.ChangeType(newValue, typeof(decimal));
@@ -264,5 +271,16 @@ namespace Radzen.Blazor
}
}
}
#if NET5
/// <summary>
/// Sets the focus on the input element.
/// </summary>
public async Task FocusAsync()
{
await input.FocusAsync();
}
#endif
}
}

View File

@@ -30,6 +30,7 @@
@if(PageSizeOptions != null && PageSizeOptions.Any())
{
<RadzenDropDown TValue="int" Data="@PageSizeOptions" Value="@PageSize" Change="@OnPageSizeChanged" />
<span class="rz-pagesize-text">@PageSizeText</span>
}
</div>
}

View File

@@ -16,12 +16,27 @@ namespace Radzen.Blazor
/// </example>
public partial class RadzenPager : RadzenComponent
{
static readonly IDictionary<HorizontalAlign, string> HorizontalAlignCssClasses = new Dictionary<HorizontalAlign, string>
{
{HorizontalAlign.Center, "rz-align-center"},
{HorizontalAlign.Left, "rz-align-left"},
{HorizontalAlign.Right, "rz-align-right"},
{HorizontalAlign.Justify, "rz-align-justify"}
};
/// <inheritdoc />
protected override string GetComponentCssClass()
{
return "rz-paginator rz-unselectable-text rz-helper-clearfix";
return $"rz-paginator rz-unselectable-text rz-helper-clearfix {HorizontalAlignCssClasses[HorizontalAlign]}";
}
/// <summary>
/// Gets or sets the horizontal align.
/// </summary>
/// <value>The horizontal align.</value>
[Parameter]
public HorizontalAlign HorizontalAlign { get; set; } = HorizontalAlign.Justify;
/// <summary>
/// Gets or sets the page size.
/// </summary>
@@ -41,20 +56,27 @@ namespace Radzen.Blazor
/// </summary>
/// <value>The page size options.</value>
[Parameter]
public IEnumerable<int> PageSizeOptions { get; set; }
public IEnumerable<int> PageSizeOptions { get; set; }
/// <summary>
/// Gets or sets the page size description text.
/// </summary>
/// <value>The page size description text.</value>
[Parameter]
public string PageSizeText { get; set; } = "items per page";
/// <summary>
/// Gets or sets the pager summary visibility.
/// </summary>
/// <value>The pager summary visibility.</value>
[Parameter]
/// <value>The pager summary visibility.</value>
[Parameter]
public bool ShowPagingSummary { get; set; }
/// <summary>
/// Gets or sets the pager summary format.
/// </summary>
/// <value>The pager summary format.</value>
[Parameter]
/// <value>The pager summary format.</value>
[Parameter]
public string PagingSummaryFormat { get; set; } = "Page {0} of {1} ({2} items)";
/// <summary>
@@ -89,9 +111,16 @@ namespace Radzen.Blazor
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
protected bool GetVisible()
{
return Visible && (Count > PageSize || (PageSizeOptions != null && PageSizeOptions.Any()));
return Visible && (AlwaysVisible || Count > PageSize || (PageSizeOptions != null && PageSizeOptions.Any()));
}
/// <summary>
/// Gets or sets a value indicating whether pager is visible even when not enough data for paging.
/// </summary>
/// <value><c>true</c> if pager is visible even when not enough data for paging otherwise, <c>false</c>.</value>
[Parameter]
public bool AlwaysVisible { get; set; }
/// <summary>
/// Gets or sets the page changed callback.
/// </summary>
@@ -193,6 +222,8 @@ namespace Radzen.Blazor
if (skip == Count)
{
skip = pageSize * (numberOfPages - 1);
//InvokeAsync(Reload);
//PageChanged.InvokeAsync(new PagerEventArgs() { Skip = skip, Top = PageSize, PageIndex = CurrentPage });
}
}

View File

@@ -3,13 +3,19 @@
{
<div @ref="@Element" style="@Style" @attributes="Attributes" class="@GetCssClass()" id="@GetId()">
<div class="rz-panel-titlebar">
<div>
@if (!string.IsNullOrEmpty(Icon))
{
<i class="rzi">@((MarkupString)Icon)</i>
}
<span>@Text</span>
</div>
@if (!string.IsNullOrEmpty(Text) || !string.IsNullOrEmpty(Icon))
{
<div>
@if (!string.IsNullOrEmpty(Icon))
{
<i class="rzi">@((MarkupString)Icon)</i>
}
@if (!string.IsNullOrEmpty(Text))
{
<span>@Text</span>
}
</div>
}
@HeaderTemplate
@if (AllowCollapse)
{

View File

@@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Routing;
using System;
using System.Collections.Generic;
@@ -26,6 +27,12 @@ namespace Radzen.Blazor
[Parameter]
public EventCallback<MenuItemEventArgs> Click { get; set; }
/// <summary>
/// Gets or sets a value representing the URL matching behavior.
/// </summary>
[Parameter]
public NavLinkMatch Match { get; set; }
List<RadzenPanelMenuItem> items = new List<RadzenPanelMenuItem>();
/// <summary>
@@ -73,7 +80,65 @@ namespace Radzen.Blazor
var currentAbsoluteUrl = UriHelper.ToAbsoluteUri(UriHelper.Uri).AbsoluteUri;
var absoluteUrl = UriHelper.ToAbsoluteUri(url).AbsoluteUri;
return string.Equals(currentAbsoluteUrl, absoluteUrl, StringComparison.OrdinalIgnoreCase);
if (EqualsHrefExactlyOrIfTrailingSlashAdded(absoluteUrl, currentAbsoluteUrl))
{
return true;
}
if (url == "/")
{
return false;
}
if (Match == NavLinkMatch.Prefix
&& IsStrictlyPrefixWithSeparator(currentAbsoluteUrl, absoluteUrl))
{
return true;
}
return false;
}
private static bool EqualsHrefExactlyOrIfTrailingSlashAdded(string absoluteUrl, string currentAbsoluteUrl)
{
if (string.Equals(currentAbsoluteUrl, absoluteUrl, StringComparison.OrdinalIgnoreCase))
{
return true;
}
if (currentAbsoluteUrl.Length == absoluteUrl.Length - 1)
{
if (absoluteUrl[absoluteUrl.Length - 1] == '/'
&& absoluteUrl.StartsWith(currentAbsoluteUrl, StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
return false;
}
private static bool IsSeparator(char c)
{
return c == '?' || c == '/';
}
private static bool IsStrictlyPrefixWithSeparator(string value, string prefix)
{
var prefixLength = prefix.Length;
if (value.Length > prefixLength)
{
return value.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)
&& (
prefixLength == 0
|| IsSeparator(prefix[prefixLength - 1])
|| IsSeparator(value[prefixLength])
);
}
else
{
return false;
}
}
void SelectItem(RadzenPanelMenuItem item)

View File

@@ -15,11 +15,13 @@
}
else
{
@if (!string.IsNullOrEmpty(Icon))
{
<i class="rzi rz-navigation-item-icon">@((MarkupString)Icon)</i>
}
<span class="rz-navigation-item-text">@Text</span>
<div class="rz-navigation-item-link">
@if (!string.IsNullOrEmpty(Icon))
{
<i class="rzi rz-navigation-item-icon">@((MarkupString)Icon)</i>
}
<span class="rz-navigation-item-text">@Text</span>
</div>
}
</div>
</li>

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))>@view.Text</button>
<button class="@($"rz-button{(IsSelected(view)? " rz-state-active" : "")}")" @onclick=@(args => OnChangeView(view))><RadzenIcon Icon=@($"calendar_view_{view.Text.ToLower()}") /><span>@view.Text</span></button>
}
</div>
</div>

View File

@@ -126,7 +126,10 @@ namespace Radzen.Blazor
if (items.Contains(item))
{
items.Remove(item);
try { InvokeAsync(StateHasChanged); } catch { }
if (!disposed)
{
try { InvokeAsync(StateHasChanged); } catch { }
}
}
}

View File

@@ -2,7 +2,11 @@
@if (Visible)
{
@if (Responsive)
{
<RadzenMediaQuery Query="(max-width: 768px)" Change=@OnChange />
}
<div @ref="@Element" style="@GetStyle()" @attributes="Attributes" class="@GetCssClass()" id="@GetId()">
@ChildContent
</div>
}
}

View File

@@ -1,4 +1,8 @@
using Microsoft.AspNetCore.Components;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Radzen.Blazor.Rendering;
namespace Radzen.Blazor
{
@@ -7,17 +11,34 @@ namespace Radzen.Blazor
/// </summary>
public partial class RadzenSidebar : RadzenComponentWithChildren
{
private const string DefaultStyle = "top:51px;bottom:57px;width:250px;";
/// <summary>
/// Gets or sets the style.
/// </summary>
/// <value>The style.</value>
[Parameter]
public override string Style { get; set; } = "top:51px;bottom:57px;width:250px;";
public override string Style { get; set; } = DefaultStyle;
/// <summary>
/// Toggles the responsive mode of the component. If set to <c>true</c> (the default) the component will be
/// expanded on larger displays and collapsed on touch devices. Set to <c>false</c> if you want to disable this behavior.
/// </summary>
[Parameter]
public bool Responsive { get; set; } = true;
/// <summary>
/// The <see cref="RadzenLayout" /> this component is nested in.
/// </summary>
[CascadingParameter]
public RadzenLayout Layout { get; set; }
/// <inheritdoc />
protected override string GetComponentCssClass()
{
return Expanded ? "rz-sidebar rz-sidebar-expanded" : "rz-sidebar";
return ClassList.Create("rz-sidebar").Add("rz-sidebar-expanded", expanded == true)
.Add("rz-sidebar-collapsed", expanded == false)
.ToString();
}
/// <summary>
@@ -25,7 +46,7 @@ namespace Radzen.Blazor
/// </summary>
public void Toggle()
{
Expanded = !Expanded;
expanded = Expanded = !Expanded;
StateHasChanged();
}
@@ -36,7 +57,19 @@ namespace Radzen.Blazor
/// <returns>System.String.</returns>
protected string GetStyle()
{
return $"{Style}{(Expanded ? ";transform:translateX(0px);" : ";width:0px;transform:translateX(-100%);")}";
var style = Style;
if (Layout != null && !string.IsNullOrEmpty(style))
{
style = style.Replace(DefaultStyle, "");
}
if (Layout != null)
{
return style;
}
return $"{style}{(Expanded ? ";transform:translateX(0px);" : ";width:0px;transform:translateX(-100%);")}";
}
/// <summary>
@@ -52,5 +85,35 @@ namespace Radzen.Blazor
/// <value>The expanded changed callback.</value>
[Parameter]
public EventCallback<bool> ExpandedChanged { get; set; }
bool? expanded;
/// <inheritdoc />
protected override void OnInitialized()
{
if (!Responsive)
{
expanded = Expanded;
}
base.OnInitialized();
}
/// <inheritdoc />
public override async Task SetParametersAsync(ParameterView parameters)
{
if (parameters.DidParameterChange(nameof(Expanded), Expanded))
{
expanded = parameters.GetValueOrDefault<bool>(nameof(Expanded));
}
await base.SetParametersAsync(parameters);
}
async Task OnChange(bool matches)
{
expanded = !matches;
await ExpandedChanged.InvokeAsync(!matches);
}
}
}

View File

@@ -118,7 +118,7 @@ namespace Radzen.Blazor
{
var step = string.IsNullOrEmpty(Step) || Step == "any" ? 1 : decimal.Parse(Step.Replace(",", "."), System.Globalization.CultureInfo.InvariantCulture);
var newValue = Math.Round(value / step) * step;
var newValue = Math.Round((value - MinValue()) / step) * step + MinValue();
if (Range)
{

View File

@@ -21,8 +21,8 @@
{
<span class="rz-button-text">&nbsp;</span>
}
</button><button onclick="@OpenPopupScript()" class="@getPopupButtonCss()" icon="rzi rzi-chevron-down" type="button">
<span aria-hidden="true" class="rz-button-icon-left rzi rzi-chevron-down"></span><span class="rz-button-text ">rz-btn</span>
</button><button onclick="@OpenPopupScript()" class="@getPopupButtonCss()" type="button">
<span aria-hidden="true" class="rz-button-icon-left rzi rzi-chevron-down"></span><span class="rz-button-text"></span>
</button>
<div id="@PopupID" class="rz-splitbutton-menu">
<ul class="rz-menu-list">

View File

@@ -245,7 +245,10 @@ namespace Radzen.Blazor
{
steps.Remove(item);
StateHasChanged();
if (!disposed)
{
try { InvokeAsync(StateHasChanged); } catch { }
}
}
}

View File

@@ -4,7 +4,7 @@
@if (Visible)
{
<div @ref="@Element" @attributes="Attributes" class="@GetCssClass()" id="@GetId()"
@onmouseup="@OnMouseUp" @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="@TabIndex">
<div class="rz-helper-hidden-accessible">
<input type="checkbox" name="@Name" value="@Value" tabindex="-1">
</div>

View File

@@ -20,15 +20,9 @@ namespace Radzen.Blazor
}
/// <summary>
/// Handles the <see cref="E:MouseUp" /> event.
/// Toggles this instance checked state.
/// </summary>
/// <param name="args">The <see cref="MouseEventArgs"/> instance containing the event data.</param>
public async Task OnMouseUp(MouseEventArgs args)
{
await Toggle();
}
async System.Threading.Tasks.Task Toggle()
public async System.Threading.Tasks.Task Toggle()
{
if (Disabled)
{

View File

@@ -32,6 +32,13 @@ namespace Radzen.Blazor
[Parameter]
public TabRenderMode RenderMode { get; set; } = TabRenderMode.Server;
/// <summary>
/// Gets or sets the tab position.
/// </summary>
/// <value>The tab position.</value>
[Parameter]
public TabPosition TabPosition { get; set; } = TabPosition.Top;
/// <summary>
/// Gets or sets the selected index.
/// </summary>
@@ -116,13 +123,9 @@ namespace Radzen.Blazor
{
tabs.Remove(item);
try
if (!disposed)
{
InvokeAsync(StateHasChanged);
}
catch
{
try { InvokeAsync(StateHasChanged); } catch { }
}
}
}
@@ -162,7 +165,22 @@ namespace Radzen.Blazor
/// <inheritdoc />
protected override string GetComponentCssClass()
{
return "rz-tabview";
var positionCSS = "rz-tabview-top";
if (TabPosition == TabPosition.Bottom)
{
positionCSS = "rz-tabview-bottom";
}
else if (TabPosition == TabPosition.Right)
{
positionCSS = "rz-tabview-right";
}
else if (TabPosition == TabPosition.Left)
{
positionCSS = "rz-tabview-left";
}
return $"rz-tabview {positionCSS}";
}
/// <inheritdoc />
@@ -182,11 +200,17 @@ namespace Radzen.Blazor
}
await base.SetParametersAsync(parameters);
}
/// <inheritdoc />
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (RenderMode == TabRenderMode.Client)
{
await JSRuntime.InvokeVoidAsync("Radzen.selectTab", $"{GetId()}-tabpanel-{selectedIndex}", selectedIndex);
}
await base.OnAfterRenderAsync(firstRender);
}
bool shouldRender = true;

View File

@@ -3,7 +3,7 @@
@if (Visible)
{
<li role="presentation" @attributes=@Attributes style=@Style class=@ClassList>
<a @onclick=@OnClick role="tab" href="javascript: void(0)" id="@($"{Tabs.Id}-tabpanel-{Index}-label")"
<a @onclick=@OnClick role="tab" href="javascript: void(0)" tabindex=@(Disabled? "-1" : "0") id="@($"{Tabs.Id}-tabpanel-{Index}-label")"
aria-selected=@(IsSelected? "true" : "false") aria-controls="@($"{Tabs.Id}-tabpanel-{Index}")">
@if (!string.IsNullOrEmpty(Icon))
{

View File

@@ -195,7 +195,7 @@ namespace Radzen.Blazor
public EventCallback<IEnumerable<object>> CheckedValuesChanged { get; set; }
void RenderTreeItem(RenderTreeBuilder builder, object data, RenderFragment<RadzenTreeItem> template, Func<object, string> text,
Func<object, bool> hasChildren, Func<object, bool> expanded, Func<object, bool> selected)
Func<object, bool> hasChildren, Func<object, bool> expanded, Func<object, bool> selected, IEnumerable children = null)
{
builder.OpenComponent<RadzenTreeItem>(0);
builder.AddAttribute(1, nameof(RadzenTreeItem.Text), text(data));
@@ -233,6 +233,7 @@ namespace Radzen.Blazor
if (grandChildren != null && hasChildren)
{
builder.AddAttribute(7, "ChildContent", RenderChildren(grandChildren, depth + 1));
builder.AddAttribute(8, nameof(RadzenTreeItem.Data), grandChildren);
}
}
@@ -308,6 +309,20 @@ namespace Radzen.Blazor
}
}
}
else if (item.Data != null)
{
if (AllowCheckBoxes && AllowCheckChildren && item.Data != null)
{
if (CheckedValues != null && CheckedValues.Contains(item.Value))
{
await SetCheckedValues(CheckedValues.Union(item.Data.Cast<object>().Except(UncheckedValues)));
}
else
{
await SetCheckedValues(CheckedValues);
}
}
}
}
Func<object, T> Getter<T>(object data, string property)

View File

@@ -1,6 +1,7 @@
using Microsoft.AspNetCore.Components;
using Radzen.Blazor.Rendering;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
@@ -76,6 +77,12 @@ namespace Radzen.Blazor
[CascadingParameter]
public RadzenTreeItem ParentItem { get; set; }
/// <summary>
/// The children data.
/// </summary>
[Parameter]
public IEnumerable Data { get; set; }
internal List<RadzenTreeItem> items = new List<RadzenTreeItem>();
internal void AddItem(RadzenTreeItem item)

View File

@@ -8,8 +8,8 @@
{
<div @ref="@Element" style="@Style" @attributes="Attributes" class="@GetCssClass()" id="@GetId()">
<div class="rz-fileupload-buttonbar">
<span class="rz-fileupload-choose rz-button btn-secondary">
<input id="@Id" @ref="@fileUpload" type="file" multiple="@Multiple" accept="@Accept"
<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)" />
<span class="rz-button-text">@ChooseText</span>
</span>
@@ -26,7 +26,7 @@
<div>@file.Name</div>
<div>@(file.Size / 1024) KB</div>
<div>
<button @onclick="@(args => OnRemove(file))" type="button" class="rz-button rz-button-icon-only btn-light"><span class="rz-icon-trash" style="display:block"></span></button>
<button disabled="@Disabled" @onclick="@(args => OnRemove(file))" type="button" class="@ButtonClassList"><span class="rz-icon-trash" style="display:block"></span></button>
</div>
</div>
}

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;
@@ -86,6 +87,27 @@ namespace Radzen.Blazor
[Parameter]
public bool Multiple { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this <see cref="RadzenUpload"/> is disabled.
/// </summary>
/// <value><c>true</c> if disabled; otherwise, <c>false</c>.</value>
[Parameter]
public bool Disabled { get; set; }
/// <summary>
/// Gets the choose class list.
/// </summary>
/// <value>The choose class list.</value>
ClassList ChooseClassList => ClassList.Create("rz-fileupload-choose rz-button")
.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")
.AddDisabled(Disabled);
/// <summary>
/// Gets or sets the child content.
/// </summary>
@@ -101,16 +123,22 @@ namespace Radzen.Blazor
await JSRuntime.InvokeAsync<string>("Radzen.upload", fileUpload, Url, Multiple);
}
IDictionary<string, string> headers = new Dictionary<string, string>();
readonly IDictionary<string, string> headers = new Dictionary<string, string>();
internal void AddHeader(string name, string value)
{
headers.Add(name, value);
if (name != null)
{
headers.Add(name, value);
}
}
internal void RemoveHeader(string name)
{
headers.Remove(name);
if (name != null)
{
headers.Remove(name);
}
}
private bool visibleChanged = false;

View File

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

View File

@@ -39,6 +39,12 @@ namespace Radzen.Blazor
[Parameter]
public TimeSpan EndTime { get; set; } = TimeSpan.FromHours(24);
/// <summary>
/// Gets or sets slot size in minutes. Set to <c>30</c> by default.
/// </summary>
/// <value>The slot size in minutes.</value>
[Parameter]
public int MinutesPerSlot { get; set; } = 30;
/// <inheritdoc />
public override DateTime StartDate
{

View File

@@ -5,10 +5,10 @@
var eventGroups = AppointmentGroups();
var lefts = new Dictionary<AppointmentData, double>();
}
@for (var date = StartDate; date < EndDate; date = date.AddMinutes(30))
@for (var date = StartDate; date < EndDate; date = date.AddMinutes(MinutesPerSlot))
{
var start = date;
var end = start.AddMinutes(30);
var end = start.AddMinutes(MinutesPerSlot);
var appointments = AppointmentsInSlot(start, end);
var existingLefts = ExistingLefts(lefts, appointments);
@@ -26,7 +26,7 @@
var eventStart = item.Start < StartDate ? StartDate : item.Start;
var eventEnd = item.End > EndDate ? EndDate : item.End;
var length = eventStart.Subtract(StartDate).TotalMinutes / 30;
var length = eventStart.Subtract(StartDate).TotalMinutes / MinutesPerSlot;
var top = 1.5 * length;
var height = Math.Max(1.5, 1.5 * eventEnd.Subtract(eventStart).TotalHours * 2);
@@ -52,6 +52,9 @@
[Parameter]
public DateTime EndDate { get; set; }
[Parameter]
public int MinutesPerSlot { get; set; }
[Parameter]
public IList<AppointmentData> Appointments { get; set; }
@@ -105,10 +108,10 @@
groups[index] = 0;
}
for (var date = StartDate; date < EndDate; date = date.AddMinutes(30))
for (var date = StartDate; date < EndDate; date = date.AddMinutes(MinutesPerSlot))
{
var start = date;
var end = start.AddMinutes(30);
var end = start.AddMinutes(MinutesPerSlot);
var appointments = AppointmentsInSlot(start, end);

View File

@@ -8,10 +8,10 @@
</div>
</div>
<div class="rz-view-content">
<Hours Start=@StartTime End=@EndTime TimeFormat="@TimeFormat" />
<Hours Start=@StartTime End=@EndTime TimeFormat=@TimeFormat MinutesPerSlot=@MinutesPerSlot />
<div class="rz-slots">
<DaySlotEvents StartDate=@StartDate EndDate=@EndDate Appointments=@Appointments />
@for (var date = StartDate; date < EndDate; date = date.AddMinutes(30))
<DaySlotEvents MinutesPerSlot=@MinutesPerSlot StartDate=@StartDate EndDate=@EndDate Appointments=@Appointments />
@for (var date = StartDate; date < EndDate; date = date.AddMinutes(MinutesPerSlot))
{
var slotDate = date;
<div @onclick=@(args => OnSlotClick(slotDate)) @attributes=@Attributes(date)></div>
@@ -36,6 +36,9 @@
[Parameter]
public string TimeFormat { get; set; }
[Parameter]
public int MinutesPerSlot { get; set; }
[Parameter]
public IList<AppointmentData> Appointments { get; set; }
@@ -44,13 +47,13 @@
async Task OnSlotClick(DateTime date)
{
await Scheduler.SelectSlot(date, date.AddMinutes(30));
await Scheduler.SelectSlot(date, date.AddMinutes(MinutesPerSlot));
}
IDictionary<string, object> Attributes(DateTime date)
{
var attributes = Scheduler.GetSlotAttributes(date, date.AddMinutes(30));
attributes["class"] = ClassList.Create("rz-slot").Add("rz-slot-minor", date.Minute == 30).Add(attributes).ToString();
var attributes = Scheduler.GetSlotAttributes(date, date.AddMinutes(MinutesPerSlot));
attributes["class"] = ClassList.Create("rz-slot").Add("rz-slot-minor", (date.Minute / MinutesPerSlot) % 2 == 1).Add(attributes).ToString();
return attributes;
}
}

View File

@@ -1,5 +1,7 @@
@using Microsoft.JSInterop
@using System.Reflection;
@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>
@if (Dialog.Options.ShowTitle)
@@ -8,7 +10,7 @@
{
<Draggable Drag="@OnDrag" DragStart="@OnDragStart">
<div class="rz-dialog-titlebar">
<span class="rz-dialog-title" id="rz-dialog-0-label">@Dialog.Title</span>
<span class="rz-dialog-title" id="rz-dialog-0-label">@((MarkupString)Dialog.Title)</span>
@if (Dialog.Options.ShowClose)
{
<a href="javascript:void(0)" @onclick=@Close role="button" class="rz-dialog-titlebar-icon rz-dialog-titlebar-close">
@@ -21,7 +23,7 @@
else
{
<div class="rz-dialog-titlebar">
<span class="rz-dialog-title" id="rz-dialog-0-label">@Dialog.Title</span>
<span class="rz-dialog-title" id="rz-dialog-0-label">@((MarkupString)Dialog.Title)</span>
@if (Dialog.Options.ShowClose)
{
<a href="javascript:void(0)" @onclick=@Close role="button" class="rz-dialog-titlebar-icon rz-dialog-titlebar-close">
@@ -103,9 +105,13 @@
}
}
builder.AddComponentReferenceCapture(2, component => reference = component);
builder.CloseComponent();
});
object reference;
void Close()
{
Service.Close();
@@ -120,12 +126,35 @@
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};";
var leftStyle = !string.IsNullOrEmpty(left) ? left :string.IsNullOrEmpty(Dialog.Options.Left) ? "" : $"left: {Dialog.Options.Left};";
var bottomStyle = string.IsNullOrEmpty(Dialog.Options.Bottom) ? "" : $"bottom: {Dialog.Options.Bottom};";
var resizeStyle = Dialog.Options.Resizable ? "resize:both;" : "";
return $"{baseStyle}{widthStyle}{heightStyle}{topStyle}{leftStyle}{resizeStyle}{Dialog.Options.Style}";
return $"{baseStyle}{widthStyle}{heightStyle}{topStyle}{leftStyle}{bottomStyle}{resizeStyle}{Dialog.Options.Style}";
}
}
[Inject]
DialogService Service { get; set; }
protected override void OnInitialized()
{
Service.OnRefresh += OnRefresh;
}
void OnRefresh()
{
var stateHasChanged = reference?.GetType().GetMethod("StateHasChanged", BindingFlags.NonPublic | BindingFlags.Instance);
InvokeAsync(() =>
{
StateHasChanged();
stateHasChanged?.Invoke(reference, null);
})
.ConfigureAwait(false);
}
public void Dispose()
{
Service.OnRefresh -= OnRefresh;
}
}

View File

@@ -1,6 +1,6 @@
<div class="rz-slot-hours">
@{var minor = false; }
@for (var date = DateTime.Today.Add(Start); date < DateTime.Today.Add(End); date = date.AddMinutes(30))
@for (var date = DateTime.Today.Add(Start); date < DateTime.Today.Add(End); date = date.AddMinutes(MinutesPerSlot))
{
@if (minor)
{
@@ -23,4 +23,7 @@
[Parameter]
public string TimeFormat { get; set; } = "h tt";
[Parameter]
public int MinutesPerSlot { get; set; }
}

View File

@@ -193,6 +193,11 @@ namespace Radzen.Blazor.Rendering
/// <returns>RGB.</returns>
public static RGB Parse(string color)
{
if (string.IsNullOrEmpty(color))
{
return null;
}
var rgb = new Regex(@"rgb\((?<r>\d{1,3}),\s*(?<g>\d{1,3}),\s*(?<b>\d{1,3})\)");
var match = rgb.Match(color);

View File

@@ -11,15 +11,15 @@
}
</div>
<div class="rz-view-content">
<Hours Start=@StartTime End=@EndTime TimeFormat="@TimeFormat" />
<Hours Start=@StartTime End=@EndTime TimeFormat=@TimeFormat MinutesPerSlot=@MinutesPerSlot />
<div class="rz-week-view-content">
@for (var day = StartDate; day < EndDate; day = day.AddDays(1))
{
var start = day.Add(StartTime);
var end = day.Add(EndTime);
<div class="rz-slots">
<DaySlotEvents StartDate=@start EndDate=@end Appointments=@Appointments />
@for (var date = start; date < end; date = date.AddMinutes(30))
<DaySlotEvents MinutesPerSlot=@MinutesPerSlot StartDate=@start EndDate=@end Appointments=@Appointments />
@for (var date = start; date < end; date = date.AddMinutes(MinutesPerSlot))
{
var slotDate = date;
<div @onclick=@(args => OnSlotClick(slotDate)) @attributes=@Attributes(date)></div>
@@ -45,6 +45,9 @@
[Parameter]
public string TimeFormat { get; set; }
[Parameter]
public int MinutesPerSlot { get; set; }
[Parameter]
public IList<AppointmentData> Appointments { get; set; }
@@ -53,13 +56,13 @@
async Task OnSlotClick(DateTime date)
{
await Scheduler.SelectSlot(date, date.AddMinutes(30));
await Scheduler.SelectSlot(date, date.AddMinutes(MinutesPerSlot));
}
IDictionary<string, object> Attributes(DateTime date)
{
var attributes = Scheduler.GetSlotAttributes(date, date.AddMinutes(30));
attributes["class"] = ClassList.Create("rz-slot").Add("rz-slot-minor", date.Minute == 30).Add(attributes).ToString();
var attributes = Scheduler.GetSlotAttributes(date, date.AddMinutes(MinutesPerSlot));
attributes["class"] = ClassList.Create("rz-slot").Add("rz-slot-minor", (date.Minute / MinutesPerSlot) % 2 == 1).Add(attributes).ToString();
return attributes;
}
}

View File

@@ -58,4 +58,4 @@
@import 'components/blazor/editor';
@import 'components/blazor/colorpicker';
@import 'components/blazor/splitter';
@import 'components/blazor/layout'

View File

@@ -1,3 +1,5 @@
$bootstrap: false !default;
// Headings
$headings: (
@@ -7,25 +9,47 @@ $headings: (
h4: (font-size: 1.125rem, font-weight: 600),
h5: (font-size: 1rem, font-weight: 600),
h6: (font-size: 0.875rem, font-weight: 600)
);
) !default;
@each $name, $heading in $headings {
#{$name} {
#{$name}.rz-heading {
@each $name, $value in $heading {
#{$name}: #{$value};
}
}
}
@if $bootstrap {
@each $name, $heading in $headings {
#{$name},
.#{$name} {
@each $name, $value in $heading {
#{$name}: #{$value};
}
}
}
}
// Paragraph
$paragraph-line-height: 1.38 !default;
p {
line-height: $paragraph-line-height;
@if $bootstrap {
p {
line-height: $paragraph-line-height;
}
}
$link-color: $default-link !default;
// Label
label {
.rz-label {
margin-bottom: 0;
}
@if $bootstrap {
label {
margin-bottom: 0;
}
}
// Link
$link-color: $default-link !default;

View File

@@ -4,15 +4,13 @@
border-radius: $input-border-radius;
overflow: hidden;
&:hover {
&:hover:not(.rz-state-disabled) {
@extend %input-hover;
}
}
.rz-state-disabled {
.rz-autocomplete {
.rz-state-disabled.rz-autocomplete {
@extend %input-disabled;
}
}
.rz-autocomplete-input {

View File

@@ -1,7 +1,13 @@
$body-padding: 1rem !default;
$body-background: none !default;
.body {
padding: $body-padding;
background: $body-background;
}
.rz-body {
padding: $body-padding;
.rz-layout & {
transform: translateZ(0);
}
}

View File

@@ -107,7 +107,7 @@ $checkbox-tri-icon-font-size: $checkbox-icon-font-size !default;
font-size: $checkbox-tri-icon-font-size;
&:before {
content: 'close';
content: 'remove';
}
}

View File

@@ -221,7 +221,7 @@ $timepicker-border: none !default;
text-decoration: none;
color: $datepicker-calendar-hover-color;
background-color: $datepicker-calendar-hover-background-color;
cursor: default;
cursor: pointer;
}
}

View File

@@ -37,7 +37,7 @@ $grid-foot-cell-color: $grid-cell-color !default;
$grid-foot-background-color: $grid-header-background-color !default;
$grid-filter-background-color: #f6f8f9 !default;
$grid-filter-padding: 0.25rem 0.625rem !default;
$grid-filter-padding: 0.5rem 0.625rem !default;
$grid-filter-margin: 0 !default;
$grid-filter-border: $grid-cell-border !default;
$grid-filter-font-size: 0.8125rem !default;
@@ -55,6 +55,7 @@ $grid-filter-buttons-background-color: $white !default;
$grid-clear-filter-button-background-color: #e6ecef !default;
$grid-clear-filter-button-color: $cool-grey !default;
$grid-apply-filter-button-background-color: $default-link !default;
$grid-apply-filter-button-color: inherit !default;
$grid-header-filter-icon-margin: 5px 5px 0 0 !default;
$grid-header-filter-icon-hover-color: inherit !default;
@@ -80,6 +81,7 @@ $grid-detail-template-border-radius: 2px !default;
$grid-detail-template-padding: 0.625rem !default;
$grid-detail-template-background-color: $white !default;
$grid-loading-indicator-color: currentColor !default;
$grid-loading-indicator-background-color: rgba($cool-grey, 0.5) !default;
$grid-button-icon-only-padding: 0 0.25rem !default;
$grid-button-text-padding: 0 0.6875rem !default;
@@ -97,6 +99,7 @@ $grid-state-transition: none !default;
$grid-group-header-padding: 15px !default;
$grid-group-header-item-padding: 10px !default;
$grid-group-header-item-margin: 5px !default;
$grid-group-header-items-margin: 0 !default;
$column-drag-handle-color: $grid-header-color !default;
$column-drag-handle-hover-color: $column-drag-handle-color !default;
@@ -226,7 +229,7 @@ $column-drag-handle-hover-color: $column-drag-handle-color !default;
@if $material == false and $fluent == false {
border-bottom: $grid-header-cell-border-bottom;
&:not(:last-child) {
&:not(:last-child), &.rz-composite-cell {
border-right: $grid-header-cell-border;
}
@@ -256,7 +259,7 @@ $column-drag-handle-hover-color: $column-drag-handle-color !default;
text-overflow: ellipsis;
@if $material == false and $fluent == false {
&:not(:last-child) {
&:not(:last-child), &.rz-composite-cell {
border-right: $grid-right-cell-border;
}
}
@@ -371,7 +374,7 @@ $column-drag-handle-hover-color: $column-drag-handle-color !default;
border-bottom: $grid-bottom-cell-border;
@if $material == false and $fluent == false {
&:not(:last-child) {
&:not(:last-child), &.rz-composite-cell {
border-right: $grid-right-cell-border;
}
}
@@ -390,7 +393,7 @@ $column-drag-handle-hover-color: $column-drag-handle-color !default;
&:first-child {
border-left: none;
}
&:last-child {
&:last-child:not(.rz-composite-cell) {
border-right: none;
}
}
@@ -410,7 +413,7 @@ $column-drag-handle-hover-color: $column-drag-handle-color !default;
}
.rz-datatable-reflow {
.rz-datatable-data {
tbody {
td {
> .rz-column-title {
display: none;
@@ -488,49 +491,8 @@ $column-drag-handle-hover-color: $column-drag-handle-color !default;
}
}
.rz-spinner {
border: none;
padding: 0;
height: auto;
background-color: transparent;
box-shadow: none;
line-height: 1;
flex: auto;
input {
line-height: 1;
&:focus {
outline: none;
color: $grid-filter-focus-color;
}
}
button {
display: none;
}
}
.rz-chkbox-box {
&.rz-state-active {
background-color: $input-background-color;
}
}
> input {
width: 0;
flex: auto;
border: none;
box-shadow: none;
padding: 0;
background-color: transparent;
color: $grid-filter-color;
font-size: $grid-filter-font-size;
line-height: 1;
&:focus {
outline: none;
color: $grid-filter-focus-color;
}
.rz-current-filter {
margin-left: 0.5rem;
}
}
}
@@ -649,6 +611,7 @@ $column-drag-handle-hover-color: $column-drag-handle-color !default;
.rz-apply-filter {
background-color: $grid-apply-filter-button-background-color;
color: $grid-apply-filter-button-color;
}
.rz-datatable-loading {
@@ -666,12 +629,14 @@ $column-drag-handle-hover-color: $column-drag-handle-color !default;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
color: $grid-loading-indicator-color;
z-index: 1;
.rzi-circle-o-notch {
@extend .rzi;
animation: rotation 1s linear infinite;
animation: rotation .5s linear infinite;
font-size: 2rem;
&:before {
content: 'refresh';
@@ -691,15 +656,20 @@ $column-drag-handle-hover-color: $column-drag-handle-color !default;
@media (max-width: 768px) {
.rz-datatable-reflow {
.rz-data-grid-data,
.rz-datatable-tablewrapper,
.rz-datatable-scrollable-header-box,
.rz-datatable-scrollable-table-wrapper {
> table {
table-layout: auto;
display: block;
}
> tbody {
display: block;
}
}
.rz-datatable-thead {
thead {
th {
display: none;
}
@@ -707,6 +677,7 @@ $column-drag-handle-hover-color: $column-drag-handle-color !default;
.rz-datatable-odd,
.rz-datatable-even {
display: block;
> td {
display: block;
width: 100% !important;
@@ -781,6 +752,9 @@ $column-drag-handle-hover-color: $column-drag-handle-color !default;
}
.rz-grid-table thead {
position: sticky;
top: 0;
z-index: 2;
th {
position: sticky;
@@ -866,6 +840,13 @@ $column-drag-handle-hover-color: $column-drag-handle-color !default;
background-color: $grid-header-background-color;
padding: $grid-group-header-padding;
border-bottom: $grid-bottom-cell-border;
display: flex;
justify-content: space-between;
align-items: center;
}
.rz-group-header-items {
margin: $grid-group-header-items-margin;
}
.rz-group-header-item {
@@ -873,9 +854,17 @@ $column-drag-handle-hover-color: $column-drag-handle-color !default;
padding: $grid-group-header-item-padding;
margin: $grid-group-header-item-margin;
width: fit-content;
float:left;
float: left;
}
.rz-group-header-item-title {
margin-right: 5px;
}
.rz-group-header-drop {
height: fit-content;
}
.rz-column-picker {
display: flex;
}

View File

@@ -1,5 +1,36 @@
$icon-base-font-size: 1.5em !default; /* Preferred icon size */
$icon-styles: () !default;
$icon-styles: map-merge(
(
primary: (
color: $primary
),
light: (
color: $light,
),
secondary: (
color: $secondary
),
info: (
color: $info
),
warning: (
color: $warning
),
error: (
color: $danger
),
danger: (
color: $danger
),
success: (
color: $success
)
),
$icon-styles
);
.rzi {
font-family: 'Material Icons';
font-weight: normal;
@@ -26,3 +57,11 @@ $icon-base-font-size: 1.5em !default; /* Preferred icon size */
/* Support for IE. */
font-feature-settings: 'liga';
}
@each $style, $icon in $icon-styles {
.rzi-#{$style} {
@each $name, $value in $icon {
#{$name}: #{$value};
}
}
}

View File

@@ -0,0 +1,30 @@
.rz-layout {
height: 100vh;
overflow: hidden;
display: grid;
grid-template-columns: auto 1fr;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"rz-header rz-header"
"rz-sidebar rz-body"
"rz-footer rz-footer";
.rz-body {
grid-area: rz-body;
overflow: auto;
}
.rz-sidebar {
grid-area: rz-sidebar;
position: static;
}
.rz-header {
grid-area: rz-header;
z-index: 2;
}
.rz-footer {
grid-area: rz-footer;
}
}

View File

@@ -90,7 +90,7 @@ $context-menu-box-shadow: 0 10px 8px 0 rgba(58, 71, 77, 0.06) !default;
margin: 0;
min-width: 100%;
box-shadow: $context-menu-box-shadow;
z-index: 2;
border-radius: $menu-border-radius;
background-color: $menu-background-color;

View File

@@ -4,11 +4,12 @@ $paginator-padding: 0.625rem !default;
$paginator-numeric-button-background-color: #e6ecef !default;
$paginator-numeric-button-color: $battleship-grey !default;
$paginator-numeric-button-margin: 0 0.3125rem !default;
$paginator-numeric-button-padding: 0.3125rem 0.6875rem !default;
$paginator-numeric-button-padding: 0.3125rem !default;
$paginator-numeric-button-selected-background-color: $white !default;
$paginator-numeric-button-selected-color: $primary-color !default;
$paginator-numeric-button-selected-border: 1px solid #e6ecef !default;
$paginator-numeric-button-selected-padding: 0.25rem 0.625rem !default;
$paginator-numeric-button-selected-padding: 0.25rem !default;
$paginator-numeric-button-min-width: 1.75rem !default;
$paginator-back-button-background-color: #e6ecef !default;
$paginator-back-button-color: $battleship-grey !default;
@@ -33,6 +34,18 @@ $paginator-button-size: ".rz-button-sm" !default;
align-items: center;
justify-content: space-between;
&.rz-align-right {
justify-content: flex-end;
}
&.rz-align-left {
justify-content: flex-start;
}
&.rz-align-center {
justify-content: center;
}
background-color: $paginator-background-color;
padding: $paginator-padding;
@@ -61,11 +74,19 @@ $paginator-button-size: ".rz-button-sm" !default;
}
.rz-dropdown {
order: 2;
width: $paginator-dropdown-width;
margin: $paginator-last-button-margin;
margin-left: 1rem;
overflow: visible;
}
.rz-pagesize-text {
order: 2;
margin: $paginator-last-button-margin;
font-size: $paginator-summary-font-size;
color: $paginator-summary-color;
}
.rz-dropdown-items-wrapper {
width: $paginator-dropdown-width - 4px;
}
@@ -85,24 +106,48 @@ $paginator-button-size: ".rz-button-sm" !default;
border-bottom-left-radius: $border-radius;
}
.rz-paginator-pages {
margin: 0 0.5rem;
}
.rz-paginator-element {
@extend .rz-button, #{$paginator-button-size}, .rz-button-icon-only;
}
.rz-paginator-first {
margin: $paginator-first-button-margin;
.rz-align-center & {
margin-left: auto;
}
}
.rz-paginator-prev {
margin-right: auto;
.rz-align-left &,
.rz-align-right &,
.rz-align-center & {
margin: $paginator-first-button-margin;
}
}
.rz-paginator-next {
margin-left: auto;
.rz-align-left &,
.rz-align-right &,
.rz-align-center & {
margin: $paginator-last-button-margin;
}
}
.rz-paginator-last {
margin: $paginator-last-button-margin;
.rz-align-center & {
margin-right: auto;
}
}
.rz-paginator-first,
@@ -129,7 +174,8 @@ $paginator-button-size: ".rz-button-sm" !default;
.rz-paginator-page {
display: inline-block;
min-width: $paginator-numeric-button-min-width;
text-align: center;
margin: $paginator-numeric-button-margin;
background-color: $paginator-numeric-button-background-color;
border-radius: $border-radius;
@@ -148,6 +194,16 @@ $paginator-button-size: ".rz-button-sm" !default;
padding: $paginator-summary-padding;
font-size: $paginator-summary-font-size;
color: $paginator-summary-color;
.rz-align-right & {
margin-right: auto;
}
.rz-align-left & {
order: 2;
margin-left: auto;
padding: 0;
}
}
@media (max-width: 768px) {

View File

@@ -19,7 +19,7 @@ ul.rz-profile-menu {
background-color: $profile-menu-top-item-background-color;
border-left: $profile-menu-border;
position: relative;
z-index: 1;
z-index: 2;
.rz-navigation-item-icon-children {
color: $profile-menu-toggle-button-color;

View File

@@ -1,8 +1,8 @@
$radio-width: 1.25rem !default;
$radio-height: $radio-width !default;
$radio-border-radius: 50%;
$radio-label-margin: 0 1rem 0 0.5rem;
$radio-margin: 1rem 0;
$radio-border-radius: 50% !default;
$radio-label-margin: 0 1rem 0 0.5rem !default;
$radio-margin: 1rem 0 !default;
$radio-active-background-color: #3f8cb3 !default;
$radio-active-shadow: inset 0 3px 0 0 rgba(0, 0, 0, 0.1) !default;

View File

@@ -16,12 +16,12 @@ $scheduler-toolbar-text-transform: uppercase;
$scheduler-toolbar-title-font-size: inherit !default;
$scheduler-toolbar-title-font-weight: inherit !default;
$scheduler-button-padding: 0 0.875rem !default;
$scheduler-button-padding: 0.25rem 0.5rem !default;
$scheduler-button-font-size: 0.6875rem !default;
$scheduler-prev-next-button-padding: $scheduler-button-padding !default;
$scheduler-prev-next-button-font-size: $scheduler-button-font-size !default;
$scheduler-button-line-height: 1.75rem !default;
$scheduler-today-button-margin-left: 16px !default;
$scheduler-button-line-height: 1.25rem !default;
$scheduler-today-button-margin-left: 0.5rem !default;
$scheduler-view-button-border: solid 1px #dadfe2 !default;
$scheduler-view-button-color: $cool-grey !default;
@@ -137,6 +137,7 @@ $scheduler-border-radius: $border-radius !default;
.rz-scheduler-nav {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
padding: $scheduler-toolbar-padding;
background: $scheduler-toolbar-background-color;
@@ -243,6 +244,10 @@ $scheduler-border-radius: $border-radius !default;
border: $scheduler-view-button-border;
border-radius: 0;
span {
margin-left: 0.25rem;
}
&:first-child {
border-top-left-radius: $scheduler-border-radius;
border-bottom-left-radius: $scheduler-border-radius;
@@ -298,3 +303,43 @@ $scheduler-border-radius: $border-radius !default;
position: static;
}
}
@media (max-width: 576px) {
.rz-scheduler-nav {
.rz-scheduler-nav-prev-next {
justify-content: space-between;
margin-bottom: 0.5rem;
margin-right: 0.5rem;
order: 1;
}
.rz-scheduler-nav-title {
justify-content: center;
width: 100%;
order: 3;
}
.rz-scheduler-nav-views {
margin-bottom: 0.5rem;
justify-content: center;
flex-grow: 1;
order: 2;
.rz-button {
flex-grow: 1;
padding-left: 0.5rem;
padding-right: 0.5rem;
span {
display: none;
}
}
}
}
.rz-slot-hours {
.rz-slot-header {
width: auto;
}
}
}

View File

@@ -13,4 +13,23 @@ $sidebar-background-color: $charcoal-grey !default;
bottom: 0;
z-index: $sidebar-z;
width: $sidebar-width;
opacity: 1;
transition: all .1s linear;
}
@media (max-width: 768px) {
.rz-sidebar {
width: 0;
opacity: 0;
}
}
.rz-sidebar-expanded {
width: $sidebar-width;
opacity: 1;
}
.rz-sidebar-collapsed {
width: 0 !important;
opacity: 0;
}

View File

@@ -20,6 +20,10 @@ $splitbutton-border-radius: $input-border-radius !default;
border-bottom-right-radius: 0;
padding: $splitbutton-padding;
}
.rz-button-text-icon-left {
flex: 1;
}
}
.rz-splitbutton-menu {

View File

@@ -1,14 +1,18 @@
$switch-background-color: #ced4da !default;
$switch-checked-background-color:#479cc8 !default;
$switch-box-shadow: none !default;
$switch-width: 3rem !default;
$switch-height: round($switch-width*600)/1000;
$switch-circle-size: round($switch-width*420)/1000;
$switch-circle-margin: round(($switch-height - $switch-circle-size)*500)/1000;
.rz-switch {
position: relative;
display: inline-block;
width: 3rem;
min-width: 3rem;
height: 1.75rem;
position: relative;
display: inline-block;
width: $switch-width;
min-width: $switch-width;
height: $switch-height;
}
.rz-switch-circle {
@@ -26,9 +30,9 @@ $switch-box-shadow: none !default;
}
.rz-switch .rz-switch-circle {
background: $switch-background-color;
transition: background-color 0.2s, color 0.2s, border-color 0.2s, box-shadow 0.2s;
border-radius: 30px;
background: $switch-background-color;
transition: background-color 0.2s, color 0.2s, border-color 0.2s, box-shadow 0.2s;
border-radius: $switch-height;
}
.rz-switch.rz-switch-checked .rz-switch-circle {
@@ -36,14 +40,14 @@ $switch-box-shadow: none !default;
}
.rz-switch .rz-switch-circle:before {
background: #ffffff;
width: 1.25rem;
height: 1.25rem;
left: 0.25rem;
margin-top: -0.625rem;
border-radius: 50%;
transition-duration: 0.2s;
box-shadow: $switch-box-shadow;
background: #ffffff;
width: $switch-circle-size;
height: $switch-circle-size;
left: $switch-circle-margin;
margin-top: round($switch-circle-size*-500)/1000;
border-radius: 50%;
transition-duration: 0.2s;
box-shadow: $switch-box-shadow;
}
.rz-switch-circle:before {
@@ -61,5 +65,5 @@ $switch-box-shadow: none !default;
}
.rz-switch.rz-switch-checked .rz-switch-circle:before {
transform: translateX(1.25rem);
}
transform: translateX($switch-width - ($switch-circle-size+$switch-circle-margin*2));
}

View File

@@ -18,7 +18,22 @@ $tabs-transition: none !default;
.rz-tabview {
display: flex;
flex-direction: column;
&.rz-tabview-top {
flex-direction: column;
}
&.rz-tabview-bottom {
flex-direction: column-reverse;
}
&.rz-tabview-left {
flex-direction: row;
}
&.rz-tabview-right {
flex-direction: row-reverse;
}
}
.rz-tabview-nav {
@@ -29,17 +44,13 @@ $tabs-transition: none !default;
li {
border: $tabs-border;
border-top-width: 2px;
border-bottom-color: $tabs-tab-background-color;
background-color: $tabs-tab-background-color;
border-radius: $tabs-border-radius $tabs-border-radius 0 0;
transition: $tabs-transition;
&:hover {
&:not(.rz-tabview-selected) {
&:not(.rz-state-disabled) {
background-color: $tabs-hover-background-color;
border-top-color: $tabs-tab-selected-top-border-color;
a {
color: $tabs-hover-color;
@@ -49,7 +60,7 @@ $tabs-transition: none !default;
}
a {
display: inline-flex;
display: flex;
align-items: center;
color: $tabs-tab-color;
padding: $tabs-tab-padding;
@@ -68,24 +79,131 @@ $tabs-transition: none !default;
.rz-tabview-selected {
background-color: $tabs-background-color;
border-bottom-color: $tabs-background-color;
margin-bottom: -1px;
position: relative;
border-top-color: $tabs-tab-selected-top-border-color;
a {
color: $tabs-selected-tab-color;
}
}
.rz-tabview-top > & {
flex-direction: row;
li {
border-top-width: 2px;
border-bottom-color: $tabs-tab-background-color;
border-radius: $tabs-border-radius $tabs-border-radius 0 0;
&:hover {
&:not(.rz-tabview-selected) {
&:not(.rz-state-disabled) {
border-top-color: $tabs-tab-selected-top-border-color;
}
}
}
}
.rz-tabview-selected {
border-bottom-color: $tabs-background-color;
margin-bottom: -1px;
border-top-color: $tabs-tab-selected-top-border-color;
}
}
.rz-tabview-bottom > & {
flex-direction: row;
li {
border-bottom-width: 2px;
border-top-color: $tabs-tab-background-color;
border-radius: 0 0 $tabs-border-radius $tabs-border-radius;
&:hover {
&:not(.rz-tabview-selected) {
&:not(.rz-state-disabled) {
border-bottom-color: $tabs-tab-selected-top-border-color;
}
}
}
}
.rz-tabview-selected {
border-top-color: $tabs-background-color;
margin-top: -1px;
padding-top: 1px;
border-bottom-color: $tabs-tab-selected-top-border-color;
}
}
.rz-tabview-left > & {
flex-direction: column;
li {
border-left-width: 2px;
border-right-color: $tabs-tab-background-color;
border-radius: $tabs-border-radius 0 0 $tabs-border-radius;
&:hover {
&:not(.rz-tabview-selected) {
&:not(.rz-state-disabled) {
border-left-color: $tabs-tab-selected-top-border-color;
}
}
}
}
.rz-tabview-selected {
border-right-color: $tabs-background-color;
margin-right: -1px;
border-left-color: $tabs-tab-selected-top-border-color;
}
}
.rz-tabview-right > & {
flex-direction: column;
li {
border-right-width: 2px;
border-left-color: $tabs-tab-background-color;
border-radius: 0 $tabs-border-radius $tabs-border-radius 0;
&:hover {
&:not(.rz-tabview-selected) {
&:not(.rz-state-disabled) {
border-right-color: $tabs-tab-selected-top-border-color;
}
}
}
}
.rz-tabview-selected {
border-left-color: $tabs-background-color;
margin-left: -1px;
padding-left: 1px;
border-right-color: $tabs-tab-selected-top-border-color;
}
}
}
.rz-tabview-panels {
background-color: $tabs-background-color;
border: $tabs-border;
border-radius: 0 0 $border-radius $border-radius;
box-shadow: $tabs-shadow;
flex: 1;
overflow: auto;
.rz-tabview-top > & {
border-radius: 0 0 $border-radius $border-radius;
}
.rz-tabview-bottom > & {
border-radius: $border-radius $border-radius 0 0;
}
.rz-tabview-left > & {
border-radius: 0 $border-radius $border-radius 0;
}
.rz-tabview-right > & {
border-radius: $border-radius 0 0 $border-radius;
}
}
@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {

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