Compare commits

...

2330 Commits

Author SHA1 Message Date
Vladimir Enchev
feaebb6f0f Version updated 2025-12-04 10:52:15 +02:00
yordanov
9a45759414 Add rz-default-scrollbars CSS class to base themes 2025-12-04 10:49:10 +02:00
yordanov
14c5a0447b Remove Black Friday promo banner 2025-12-04 10:37:47 +02:00
yordanov
7793e03d82 Update premium themes 2025-12-03 10:27:13 +02:00
Martin Hans
f422573fcc Add resizable option to side dialog. (#2331)
* Add resizable option to side dialog.

* Fix resize bar CSS class typo and make sideDialogResizeHandleJsModule nullable

* Add tests for resizable side dialog.

* Rename element references.

* Enable nullable refernce types for RadzenDialg.razor.cs

* Resolve requested change

Move code back to RadzenDialog.razor.

* Use sideDialog.classList to gather position rather than data-dir attribute.

* Rework initSideDialogResize function.

- Take position from options.
- Take width and height from sideDialogs clientWidth and clientHeight.
- Take minWidth and minHeight from options.
- Remove superflous pointer capturing.
- Remove superflous 'dragging' class.

* Replace title and aria label string constants by properties.

* Treat resizableMinWidth and resizableMinHeight as present.

* Reformat

* Use options.resizableMinWidth/Height only

* No need to set min-width neither min-height on side dialog.

* Rename ResizableMinWidth => MinWidth, ResizableMinHeight => MinHeight.

* Rename initSideDialogResize => createSideDialogResizer.

* Add dialog resize bar css variables

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: yordanov <vasil@yordanov.info>
2025-12-03 10:22:33 +02:00
tharreck
516109ecd3 Correctly select RadzenTocItem based on scroll direction in RadzenToc (#2370)
* Select toc item based on scroll direction in TOC

* Select correct RadzenTocItem when reloading a page with anchor
cleanup code

* add debounce back into scrollhandler

---------

Co-authored-by: Torrelle Steven <steven.torrelle@uzgent.be>
2025-12-02 15:45:10 +02:00
Mason Voxland
31d32b16a5 Clicking SelectAllText in CheckBoxList will do change (#2377) 2025-12-02 11:13:16 +02:00
yordanov
435c1bd6e2 Update Black Friday promo 2025-12-01 10:56:10 +02:00
Vladimir Enchev
6d5ebf3f58 Version updated 2025-12-01 10:55:13 +02:00
Vladimir Enchev
b97036b447 Support large strings added to QRCode
Fix #2373
2025-12-01 10:51:55 +02:00
Vladimir Enchev
d7ef3cb896 Upload file not removed properly when on file delete from UI 2025-11-27 14:10:49 +02:00
Robyn Choi
2218eefa67 RadzenPivotDataGrid AddPivotAggregate exposed (#2371) 2025-11-27 08:14:10 +02:00
Vladimir Enchev
666d33d767 Version updated 2025-11-26 14:00:45 +02:00
Vladimir Enchev
3f4f83d354 PivotDataGrid filter icon popup exception after adding more fields 2025-11-26 08:35:43 +02:00
Atanas Korchev
3dea547559 Enable CSS minification for the embedded themes. 2025-11-25 18:33:46 +02:00
rklfss
0e9c6acb84 Allow Specifying the interactive SortOrder Sequence on Data Grids (#2366) 2025-11-25 15:46:23 +02:00
Vladimir Enchev
1b6881673e AI assistant messages are sent as ‘user’ instead of ‘assistant’ role. ChatMessage Role property added
Fix #2365
2025-11-25 10:17:15 +02:00
yordanov
f069b33b60 Add videos to UI fundamentals demos 2025-11-25 10:03:54 +02:00
Vladimir Enchev
c0a86e31da Version updated 2025-11-24 10:05:17 +02:00
Vladimir Enchev
7b95778efe PivotDataGrid ColumnsCollection, RowsCollection and AggregatesCollection added 2025-11-24 09:45:02 +02:00
Vladimir Enchev
ef8a102d0a DataGrid OData column Type Guid exception on set filter
Fix #2363
2025-11-24 09:18:55 +02:00
Vladimir Enchev
95448de3ed DataGrid column CloseFilter() does not work when FilterProperty has a value 2025-11-21 10:14:08 +02:00
Vladimir Enchev
0a574762c7 RadzenTocItem inherits RadzenComponentWithChildren 2025-11-18 14:10:07 +02:00
joriverm
59b1440990 RadzenTocItem: take in attributes to pass on to the list item element (#2360)
Co-authored-by: AI\jvermeyl <joris.vermeylen@uzgent.be>
2025-11-18 13:56:36 +02:00
Vladimir Enchev
98d6729d4b Version updated 2025-11-18 09:06:25 +02:00
Vladimir Enchev
135a0bbe5c RadzenPivotDataGrid AddPivotField, AddPivotColumn and AddPivotRow exposed 2025-11-18 09:05:05 +02:00
Vladimir Enchev
c3f579931d RadzenDropDownDataGrid LoadChildData event added 2025-11-18 08:57:30 +02:00
Vladimir Enchev
21c51e81d2 PagedDataBoundComponent current page not synced for top and bottom pagers
Fix #2357
2025-11-18 08:48:03 +02:00
Ali Yousefi
e6538c95ad feat: keyboard key that triggers opening the popup (#2356) 2025-11-17 15:50:59 +02:00
Vladimir Enchev
0e63e87f9b DatePicker will not populate iniitially hour and minutes when bound to TimeOnly 2025-11-14 09:49:22 +02:00
Vladimir Enchev
1e900ec775 Added XML comments to Popup public API 2025-11-14 09:30:44 +02:00
edgett
5ff30874dd Add CloseOnClickOutside parameter to Popup (#2355)
* Add CloseOnClickOutside parameter to Popup

Add a parameter called CloseOnClickOutside Popup, default is true. This maintains the current behavior. If set false, the Popup will remain open with the user click outside of it.

* Fix js function usage

Updated the parameters for the Radzen.openPopup JS function to include closeOnDocumentClick.
2025-11-14 09:27:36 +02:00
Vladimir Enchev
94550006c4 RadzenPivotDataGrid code improved 2025-11-13 15:54:11 +02:00
yordanov
202636ce72 Add BlackFriday offer 2025-11-13 13:12:12 +02:00
Vladimir Enchev
cae8c6f622 version updated 2025-11-13 10:37:42 +02:00
Vladimir Enchev
0e03c4377f PivotDataGrid set filter value should invalidate filter 2025-11-13 10:32:16 +02:00
Vladimir Enchev
7497ea1262 PivotDataGrid dynamic data support added 2025-11-13 10:19:37 +02:00
Atanas Korchev
d68bb34f6f Update getting started to include .NET 10. 2025-11-12 12:38:43 +02:00
Vladimir Enchev
732a6f4942 DataGrid sort ambiguous match found 2025-11-12 09:40:55 +02:00
Atanas Korchev
70fb896ae1 Update CI workflow to use .NET 10 2025-11-12 08:04:17 +02:00
Vladimir Enchev
034eae6722 Version updated 2025-11-11 17:50:22 +02:00
Vladimir Enchev
3472949bf0 sdk updated 2025-11-11 17:46:25 +02:00
Vladimir Enchev
c333b8ca30 Net10 support added (#2353)
* NET10 support added

* DataGrid Paging Disappears on Click in .NET Core 10.0.0 RC

Fix #2286

* various fixes

* KnownIPNetworks used instead KnownNetworks

* build fixed
2025-11-11 17:43:29 +02:00
Vladimir Enchev
17e3fbdabf version updated 2025-11-10 10:27:36 +02:00
Vladimir Enchev
30c5c9dfaf More strict GetDeclaredMethods() for FirstOrDefault(), LastOrDefault(), Cast() and Distinct()
Fix #2343
2025-11-10 09:41:06 +02:00
Vladimir Enchev
585d1ee38a DropDown ReadOnly XML description fixed 2025-11-10 09:37:02 +02:00
Vladimir Enchev
3255afb487 DialogService method CloseSideAsync made virtual
Fix #2349
2025-11-10 09:28:07 +02:00
Vladimir Enchev
9f75648b50 DropDownDataGrid exception with sorting when no columns are defined 2025-11-10 09:18:21 +02:00
yordanov
50406f8984 Update Material Icons font. Resolves #2342 2025-11-07 15:05:05 +02:00
Atanas Korchev
f24c7ebc5f Add demo showing how to use Google Fonts. 2025-11-07 13:34:18 +02:00
Vladimir Enchev
75dcecfab0 Version updated 2025-11-07 08:18:47 +02:00
Atanas Korchev
34c603ce53 Revert "Cleanup code a little (#2336)"
This reverts commit d816d841a8.
2025-11-07 07:01:16 +02:00
Vladimir Enchev
7785a73876 Version updated 2025-11-06 16:26:34 +02:00
Vladimir Enchev
cfa8f731f2 DropDown FooterTemplate added
Close #2344
2025-11-06 16:25:59 +02:00
Ondrej Bach
5ecd05c7b3 Additional parameters passed from RadzenDropDownDataGrid to RadzenDataGrid (#2347)
* Inject ServiceProvider to RadzenDataAnnotationValidator to use it within ValidationContext

* Fix ... add inject attribute

* Add pass-through parameters AllowColumnPicking, AllowColumnReorder and PageSizeOptions to DropDownDataGrid

---------

Co-authored-by: Ondrej Bach <ondrej.bach@external.drivalia.com>
2025-11-06 16:17:08 +02:00
Vladimir Enchev
4ec95c2f1c Various types extracted in separate files 2025-11-05 14:31:34 +02:00
Ondrej Bach
9e4413b02e Inject ServiceProvider to RadzenDataAnnotationValidator to use it wit… (#2339)
* Inject ServiceProvider to RadzenDataAnnotationValidator to use it within ValidationContext

* Fix ... add inject attribute

---------

Co-authored-by: Ondrej Bach <ondrej.bach@external.drivalia.com>
2025-11-04 18:43:12 +02:00
Vladimir Enchev
38d0d689b3 DataGrid CollectionFilterMode improved and added example 2025-11-04 11:38:06 +02:00
Vladimir Enchev
799c5e9e4e DataGrid column CollectionFilterMode property added
Close #2313
2025-11-04 10:27:11 +02:00
joriverm
b98dffda8f Add Immediate to Radzen Password (#2337)
Co-authored-by: AI\jvermeyl <joris.vermeylen@uzgent.be>
2025-11-03 19:08:12 +02:00
joriverm
d816d841a8 Cleanup code a little (#2336)
* TextArea/Box change tests extended

fixup copy paste fail

* Cleanup warnings about FieldIdentifier.FieldName not able to be null

its defined as a non-nullable string, and an empty string is considerd valid

---------

Co-authored-by: AI\jvermeyl <joris.vermeylen@uzgent.be>
2025-11-03 19:06:46 +02:00
Vladimir Enchev
1730e02dc3 Version updated 2025-11-02 10:19:59 +02:00
Vladimir Enchev
53737d2f3c TextArea/TextBox adding custom oninput attribute fixed 2025-11-02 10:14:55 +02:00
MVSAlex
932dc3f9f6 Fix for Dialog autofocus for HTMLEditors wrapped in RadzenFormField with Tabindex correct (#2334)
* Fix for Dialog Autofocus for HTMLEditors inside RadzenFormField

If a Dialog had an HTMLEditor which was wrapped inside of a RadzenFormField it would always get focused no matter where it is breaking the Autofocus of the first Element

* Fix for unintentionally ignored TabIndex

Made a mistake that would completely ignore the TabIndex being set to -1 and therefore still include those elements
2025-10-30 15:54:27 +02:00
Vladimir Enchev
567fdb6a36 ListBoxTests extended 2025-10-30 14:33:24 +02:00
Vladimir Enchev
3e323b929d DropDownDataGridTests extended 2025-10-30 14:26:46 +02:00
Vladimir Enchev
a53fb126ac Version updated 2025-10-30 14:00:46 +02:00
MVSAlex
ec2c17bc21 Fix for Dialog Autofocus for HTMLEditors inside RadzenFormField (#2332)
If a Dialog had an HTMLEditor which was wrapped inside of a RadzenFormField it would always get focused no matter where it is breaking the Autofocus of the first Element
2025-10-30 13:43:29 +02:00
Vladimir Enchev
3894f31c2c RadzenPivotDataGrid tests added 2025-10-30 10:04:48 +02:00
Vladimir Enchev
342b96801a RadzenTextArea/RadzenTestBox Immediate code improved 2025-10-29 16:20:04 +02:00
Vladimir Enchev
36f1dfe2e0 more tests added 2025-10-29 16:07:47 +02:00
Vladimir Enchev
f90951add1 various tests added 2025-10-29 15:24:49 +02:00
joriverm
7d65c45833 Add Support for Immediate changes in TextArea (#2329)
Co-authored-by: AI\jvermeyl <joris.vermeylen@uzgent.be>
2025-10-29 15:12:11 +02:00
joriverm
3629235a00 Cleanup RadzenStack's style compiling to not generate an extra semicolon (#2330)
Co-authored-by: AI\jvermeyl <joris.vermeylen@uzgent.be>
2025-10-29 15:10:40 +02:00
Atanas Korchev
09ff7744dc Load compilation dependencies on demand. 2025-10-28 23:30:57 +02:00
Atanas Korchev
1fa9d59634 Use specific static asset provider for the source code. 2025-10-28 21:53:07 +02:00
Atanas Korchev
ccec9dbc70 Remove UseStaticAssets as it seems to disable compression. 2025-10-28 20:51:59 +02:00
Vladimir Enchev
a49dbad913 Version updated 2025-10-28 16:17:54 +02:00
Vladimir Enchev
4f0497158b Upload cannot drag & drop files after file remove
Fix #2160
2025-10-28 14:19:10 +02:00
Vladimir Enchev
4757d158a8 Label moved to Forms 2025-10-28 10:25:46 +02:00
Vladimir Enchev
4bbd371a42 Label demos added 2025-10-27 15:31:02 +02:00
Vladimir Enchev
10b4b877de RadzenMediaQuery examples added
Fix #1755
2025-10-27 14:56:27 +02:00
Vladimir Enchev
3bd030c397 Splitter double click will toggle expand/collapse
Fix #385
2025-10-27 14:47:07 +02:00
Vladimir Enchev
7c408808c9 more descriptions added 2025-10-27 13:53:33 +02:00
Vladimir Enchev
39dcaa8fc4 demos descriptions improved 2025-10-27 12:27:25 +02:00
Vladimir Enchev
04cdd584a2 demo improved 2025-10-27 11:27:41 +02:00
Atanas Korchev
2693487f81 Move AddRadzenComponents in theme registration as RadzenTheme needs it. 2025-10-27 11:15:15 +02:00
Vladimir Enchev
d73dce8804 Components API remarks moved to summary 2025-10-27 09:22:20 +02:00
Vladimir Enchev
cf333e8c15 Version updated 2025-10-24 17:46:02 +03:00
Vladimir Enchev
5aea28611b DataGrid LoadDataArgs.Filter and LoadDataArgs.Filters represent different filters after remove filtered column by column picker
Fix #1286
2025-10-24 17:44:16 +03:00
Vladimir Enchev
c58ccf0a66 SecurityCode Doesn't work well with Android
Fix #2323
2025-10-24 17:14:51 +03:00
Vladimir Enchev
d5c870eb9d XML API improved 2025-10-24 16:28:11 +03:00
Vladimir Enchev
a41b00e0be various demos descriptions added 2025-10-24 12:32:11 +03:00
Vladimir Enchev
383ee7e577 Cascading DropDowns demo extended with additional DataGrid 2025-10-24 09:50:15 +03:00
Atanas Korchev
b3b1f887ef Enable color lists in the color picker tools of RadzenHtmlEditor. 2025-10-23 21:28:56 +03:00
yordanov
b6089f5d28 Update banners 2025-10-23 18:37:18 +03:00
yordanov
2d7d5cad39 Update subscription info 2025-10-23 15:55:52 +03:00
Vladimir Enchev
cb06833882 ContextMenu on Datagrid does not respect specificity
Fix #2325
2025-10-23 14:38:26 +03:00
Vladimir Enchev
cf3ab86cec Version updated 2025-10-23 14:22:29 +03:00
Vladimir Enchev
efd3d18484 RadzenProfileMenuItem Template property added
Fix #1754
2025-10-23 12:45:27 +03:00
Atanas Korchev
e6baaa6184 (internal) Flatten elements within <span class="rbs-text"> for improved RBS support. 2025-10-23 12:32:57 +03:00
Vladimir Enchev
81c943ecda "Update dialog properties" does not work for side dialogs.
Fix #2091
2025-10-23 12:10:38 +03:00
Vladimir Enchev
587a4f479c Screen reader is not announcing the name for the 'progress bar' control in Windows.
Fix #2184
2025-10-23 11:51:21 +03:00
Vladimir Enchev
5638152121 Wrong Pager position/displayed data on PagedDataBoundComponent after triggering Visible Parameter
Fix #2225
2025-10-23 11:39:57 +03:00
Vladimir Enchev
81fc744270 Focus not set to the RadzenDropDown with options 'AllowFiltering=true' and 'Multiple=true', when pressing Esc or TAB to close dropdown
Fix #2308
2025-10-23 11:32:51 +03:00
Vladimir Enchev
2437b9e028 more descriptions added 2025-10-23 11:18:57 +03:00
Vladimir Enchev
d148cac10e more descriptions added 2025-10-23 11:10:26 +03:00
Vladimir Enchev
af8c9e3cc3 Fixed DatePicker keyboard navigation with multiple selection 2025-10-23 10:50:29 +03:00
Vladimir Enchev
b64c71c307 various descriptions added 2025-10-23 10:39:49 +03:00
Vladimir Enchev
2d60d8fcc1 Version updated 2025-10-22 16:30:35 +03:00
Vladimir Enchev
814221997e DatePicker invalid cast error with Multiple 2025-10-22 16:30:20 +03:00
Vladimir Enchev
5e112b6f59 await removed 2025-10-22 16:03:44 +03:00
Vladimir Enchev
6b253c30b2 Version updated 2025-10-22 15:56:02 +03:00
Vladimir Enchev
b5b0c1efa7 DatePicker async void removed 2025-10-22 15:55:33 +03:00
Vladimir Enchev
5dce6f81af Version updated 2025-10-22 15:26:07 +03:00
yordanov
6ff186d7de Update premium themes 2025-10-22 15:19:55 +03:00
yordanov
801a1cab1a Update links 2025-10-22 12:54:05 +03:00
Vladimir Enchev
737539e3a8 DataGrid demo improved
Fix #2311
2025-10-22 09:17:57 +03:00
Petar Slavov
2992f868ef Added ShowFooter property to GroupDescriptor. Added ability to show group footer rows on every group lavel. Added ability to control group footer visibility from the ShowFooter property of the GroupDescriptor. (#2321) 2025-10-22 09:08:36 +03:00
yordanov
e718ef80dc Update responsive styles 2025-10-21 18:31:07 +03:00
yordanov
220a441422 Move QRCode to Data Visualization category 2025-10-21 17:21:38 +03:00
yordanov
8440eb513a Update font-sizes 2025-10-21 17:20:53 +03:00
yordanov
09004fd7db Update demos homepage and footer 2025-10-21 16:41:35 +03:00
Vladimir Enchev
e9fb2bf677 various descriptions improved 2025-10-21 14:31:42 +03:00
Vladimir Enchev
81261e2413 DatePicker Multiple property added 2025-10-21 11:44:15 +03:00
Vladimir Enchev
2c7b51dc00 DatePicker ShowHour and ShowMinutes properties added 2025-10-20 15:05:37 +03:00
Atanas Korchev
47447badc1 Remove first line from Dockerfile. 2025-10-20 11:47:05 +03:00
Vladimir Enchev
1233a2347d Version updated 2025-10-20 11:18:21 +03:00
Vladimir Enchev
b0cec6f668 RadzenQRCode component added (#2319)
* RadzenQRCode added

* RadzenQRCode render improved

* QRCode improved

* Update qrcode demos

* Reorder color pickers in qrcode demo

---------

Co-authored-by: yordanov <vasil@yordanov.info>
2025-10-20 11:09:25 +03:00
Atanas Korchev
05e25d51ec Remove trailing / from sitemap. 2025-10-19 12:14:21 +03:00
Atanas Korchev
81c27836c2 Proxy the protocol. 2025-10-19 00:06:44 +03:00
Atanas Korchev
24aa1ec1b3 Add sitemap.xml and robots.txt 2025-10-18 23:33:39 +03:00
Atanas Korchev
6c7bc84ff4 Add canonical links. 2025-10-18 21:17:20 +03:00
Bilal Korkmaz
bc1d139cca set filter datetimes according to specified DateTimeKind (#2317)
* set filter datetimes according to specified DateTimeKind

* Updated DateTimeKind implementation to avoid new parameter as per code review

---------

Co-authored-by: Bilal Korkmaz <b58korkmaz@hotmail.com>
2025-10-17 14:53:34 +03:00
Vladimir Enchev
c1afef18f3 ChatUser color not applied 2025-10-17 12:34:44 +03:00
Vladimir Enchev
f46ff6237b demos fixed 2025-10-15 14:38:34 +03:00
Atanas Korchev
fd94e8037d Add NotFound page. 2025-10-15 09:21:36 +03:00
Vladimir Enchev
b95bf75dce Filtering of collection by item property tests added 2025-10-14 14:24:27 +03:00
Vladimir Enchev
b08b3aa3b1 more filtering tests added 2025-10-14 13:26:59 +03:00
Vladimir Enchev
5ed931243e QueryableExtensionTests added 2025-10-14 11:19:32 +03:00
Vladimir Enchev
f5ab48c8af More DataGrid filtering tests added 2025-10-14 11:12:02 +03:00
Vladimir Enchev
75202f4ff8 DataGrid filtering tests added 2025-10-14 10:59:21 +03:00
Vladimir Enchev
3c679674d5 Version updated 2025-10-08 14:59:23 +03:00
yordanov
6f7921691c The total number of UI components is now over 100. 2025-10-08 10:49:35 +03:00
Vladimir Enchev
13ba136c66 DataGrid IsValid should call all EditContexts Validate() 2025-10-08 09:35:21 +03:00
Vladimir Enchev
abd80af816 DatePicker InitialViewDate change should be respected 2025-10-08 09:20:24 +03:00
Vladimir Enchev
aac927e6ea AIChatServiceOptions exposed as individual properties of RadzenAIChat 2025-10-07 10:06:21 +03:00
Atanas Korchev
f7e0d7d698 Theme changing does not work in RenderMode.InteractiveAuto. 2025-10-07 08:14:30 +03:00
Vladimir Enchev
eb633bae3a Version updated 2025-10-06 17:37:39 +03:00
Vladimir Enchev
76a0b5e3e2 PivotDataGrid expression for non string values improved 2025-10-06 17:36:39 +03:00
Vladimir Enchev
0679525905 Version updated 2025-10-06 16:17:44 +03:00
Vladimir Enchev
3396c7bca4 PivotDataGrid aggregates for nested properties fixed 2025-10-06 15:00:33 +03:00
Vladimir Enchev
5031ce3936 PivotDataGrid invalid expression with non string row values 2025-10-06 14:06:11 +03:00
Vladimir Enchev
8b774b47e2 New examples updated 2025-10-06 13:06:29 +03:00
Vladimir Enchev
f0e7a398fa version updated 2025-10-06 12:02:32 +03:00
Vladimir Enchev
72c3f23c67 Fields picking properties moved to RadzenPivotDataGrid 2025-10-06 12:02:08 +03:00
yordanov
33c01b611e Update demos 2025-10-06 10:58:35 +03:00
yordanov
7cc2e6953b Update changelog 2025-10-06 10:33:17 +03:00
yordanov
1284d4ab80 Add PivotDataGrid to demos home and update component icon 2025-10-06 10:13:28 +03:00
Vladimir Enchev
cd83f01132 Version updated 2025-10-06 10:06:18 +03:00
Vasil Yordanov
3b4480fa8b Sidebar Position and FullHeight options added (#2310)
* Add SidebarPosition and FullHeight options to RadzenSidebar and adjust layout styles accordingly

* Update RadzenLayout demos
2025-10-06 10:02:00 +03:00
Vladimir Enchev
a9f8fbbff5 code fixed 2025-10-06 09:10:18 +03:00
Vladimir Enchev
e37b055e24 DatePicker updates year/months before setting YearRange which can cause a crash
Fix #2250
2025-10-06 09:08:12 +03:00
Vladimir Enchev
8eeda0e647 RadzenAIChat MessageTemplate and EmptyTemplate added 2025-10-03 14:14:46 +03:00
Vladimir Enchev
c28b47e231 RadzenPivotDataGrid added (#2307) 2025-10-03 11:07:39 +03:00
Atanas Korchev
ab989107a5 Serve demo source from wwwroot instead of github. 2025-10-02 15:50:21 +03:00
Vladimir Enchev
268fe93dd9 code fixed 2025-10-02 15:34:57 +03:00
Vladimir Enchev
e154fb05ea RadzenChat component added (#2306)
* RadzenChat component added

* Update chat message layout

* Update participant avatars in chat header

---------

Co-authored-by: yordanov <vasil@yordanov.info>
2025-10-02 14:45:45 +03:00
Vasil Yordanov
fb14fe587b Add new RadzenFab and RadzenFabMenu components (#2305)
* Add Fab and FabMenu components

---------

Co-authored-by: Atanas Korchev <akorchev@gmail.com>
2025-10-01 15:23:52 +03:00
Vladimir Enchev
e72a17ce32 Update DropDownBase.cs
Closes #2302, Closes #2298, Closes #2304
2025-10-01 11:46:30 +03:00
Vladimir Enchev
6c11409e7e Version updated 2025-09-29 15:14:16 +03:00
Vladimir Enchev
f43db71b01 SecurityCode invalid index error on paste
Fix #2300
2025-09-29 14:40:47 +03:00
Atanas Korchev
dc3611474f Markdown anchors that contain only fragments (e.g. [link](#fragment)) navigate to the root. 2025-09-28 13:50:35 +03:00
Atanas Korchev
5c5a306f7f Optimize the drag-and-drop performance of Scheduler appointments. 2025-09-27 13:42:38 +03:00
Vladimir Enchev
024d9fb5ac Version updated 2025-09-26 07:36:01 +03:00
Vladimir Enchev
6fb480042f Revert "RadzenDataGrid throws an exception when a filter value is loaded for a sub property (#2290)"
This reverts commit 224032d0c2.
2025-09-26 07:35:34 +03:00
Vladimir Enchev
acc1f8624e Version updated 2025-09-24 16:49:33 +03:00
Atanas Korchev
0b97853a57 Enabling WCAG colors via ThemeService no longer works. Fixes #2296. 2025-09-24 16:47:14 +03:00
Vladimir Enchev
8408b55e08 Version updated 2025-09-24 16:08:17 +03:00
Atanas Korchev
e49d9f7eab Prevent FOUC in RadzenTheme (#2294)
* ThemeService.SetTheme uses JavaScript to change the theme CSS files to prevent FOUC during Blazor initial hydration.

* Update the getting started instructions.

* Initialize the theme in ThemeService from RadzenTheme.
2025-09-23 16:47:24 +03:00
yordanov
6202bd78f3 Update banners 2025-09-23 15:21:27 +03:00
Vladimir Enchev
a2a5916e09 Version updated 2025-09-23 10:05:52 +03:00
Atanas Korchev
3f52e42661 Add Reload method to RadzenSankeyDiagram. 2025-09-22 11:37:34 +03:00
IncaTechnologies
224032d0c2 RadzenDataGrid throws an exception when a filter value is loaded for a sub property (#2290)
* Add tests

* Fix load settings from json

---------

Co-authored-by: noname <noname@nomail>
2025-09-22 08:37:52 +03:00
joriverm
4dece2e58a DataBoundFormComponent: Generate FieldIdentifier if ValueChanged is given (#2291)
Co-authored-by: AI\jvermeyl <joris.vermeylen@uzgent.be>
2025-09-22 08:37:40 +03:00
Atanas Korchev
7eb85d4454 Scheduler does not use the Culture when determining the start of the week. Fixes #2293. 2025-09-20 14:19:18 +03:00
Atanas Korchev
bd750e6f97 RadzenScheduler no longer uses a private Rect class. 2025-09-20 13:31:58 +03:00
Vladimir Enchev
ee0d4d29e1 Source links fixed
Fix #2289
2025-09-16 14:09:14 +03:00
Vladimir Enchev
10d2ea7c0a Version updated 2025-09-16 13:29:53 +03:00
Vladimir Enchev
0ab76d53ec DataGrid GroupFooterTemplate wrong rendering when ShowGroupExpandColumn=false 2025-09-15 15:31:07 +03:00
Vladimir Enchev
3dea0a5f67 Chat model updated 2025-09-15 11:28:13 +03:00
Vladimir Enchev
41c2e04cfa Chat messages cleared in some cases 2025-09-15 10:29:10 +03:00
DinuRoth
d8183feb07 only use the designated fragment when pasting html into a RadzenHtmlEditor (#2285)
* only use the designated fragment when pasting html into a RadzenHtmlEditor

* fragment-extraction inlined

---------

Co-authored-by: Martin Roth <martin.roth@swisscom.com>
2025-09-15 10:10:45 +03:00
Vladimir Enchev
e49fe2bca8 Version updated 2025-09-11 10:34:12 +03:00
Vladimir Enchev
67664a2816 DataGrid CheckBoxList with OData demo updated
Fix https://github.com/radzenhq/radzen-blazor/issues/2252
2025-09-09 09:37:16 +03:00
Gincsai Gábor
eefbe00aec Fix grid settings handling for sub properties column (#2274)
* Fix loading settings when multiple colum has same Property (e.g using sub-property filtering)
Fix loaded settings type handling to handle IEnumerable column with non ValueKind.Array.
Added default value for Unique ID is not set.

Add example.

* Set shouldUpdateState too.

* Make QueryableExtension.Select public

* Change filter mode back to original on demo page.
2025-09-09 09:15:34 +03:00
Atanas Korchev
be67d5f120 JavaScript error is thrown when the user selects an image in RadzenHtmlEditor and presses the insert link tool. 2025-09-04 13:57:50 +03:00
Vladimir Enchev
fa1fe694cf version updated 2025-09-02 13:53:40 +03:00
yordanov
9f681c0c09 Add CSS variables for DataGrid alternating row backgrounds in frozen columns 2025-09-02 12:43:31 +03:00
Vladimir Enchev
18dde2849e DataGrid will look first for column UniqueID before Property when loading settings 2025-08-29 18:25:20 +03:00
Vladimir Enchev
5678774de0 PickList MoveFilteredItemsOnlyOnMoveAll added 2025-08-29 18:19:51 +03:00
Vladimir Enchev
f5370e1384 RadzenColorPicker SelectedColorChanged null exception fixed 2025-08-29 08:46:45 +03:00
Vladimir Enchev
934d7cb104 Version updated 2025-08-28 09:58:56 +03:00
Vladimir Enchev
33b201147d DynamicExtensions Where() should use ExpressionSerializer Value for Format for FilterParameters 2025-08-28 09:58:27 +03:00
yordanov
abe2006e15 RadzenDialog source link should point to DialogService as well. Resolves #2270 2025-08-27 19:25:00 +03:00
Vladimir Enchev
81b5cb386d DataGridLoadColumnFilterDataEventArgs Property setter made public 2025-08-27 08:53:44 +03:00
Vladimir Enchev
c713dd6c87 Version updated 2025-08-26 09:18:01 +03:00
Vladimir Enchev
eda5c490b7 DropDownDataGrid AllowFilteringByAllStringColumns will raise exception with IDictionary binding 2025-08-26 09:17:22 +03:00
yordanov
b6bc9e1257 Fix link to Skeleton animations example source 2025-08-25 17:50:31 +03:00
yordanov
123ffd8886 Update premium themes 2025-08-25 12:51:51 +03:00
Vladimir Enchev
9a2c09c6e8 version updated 2025-08-25 11:38:24 +03:00
Vladimir Enchev
5b5fdde9a2 Skeleton component added (#2268)
* RadzenSkeleton component added

* Update Skeleton component properties, themes, and demos

* Skeleton tests fixed

---------

Co-authored-by: yordanov <vasil@yordanov.info>
2025-08-25 11:31:34 +03:00
Vladimir Enchev
0cc50d70da Fixed RadzenPanelMenuItem will not show tooltip 2025-08-25 11:17:13 +03:00
mtboeke
c79ecddee4 Expose Responsive MaxWidth in RadzenSidebar (#2260)
* Expose ResponsiveMaxWidth

* Change property to a string to be more versatile

---------

Co-authored-by: Matt Boeke <gangolfus@hotmail.com>
2025-08-25 11:07:11 +03:00
Nopke
e929edbd53 ColorPicker: highlight selected color item (#2267) 2025-08-25 11:00:39 +03:00
Atanas Korchev
8de7a1ec70 Wrong value axis display when all values in a series are the same and negative. 2025-08-22 19:17:20 +03:00
Vladimir Enchev
0b6ae4d225 Version updated 2025-08-21 07:48:09 +03:00
yordanov
c69bb8bb2b Add MCP logo 2025-08-20 22:26:08 +03:00
yordanov
e8dda6f946 Update list of components 2025-08-20 18:21:40 +03:00
yordanov
3daebfc0c1 Update AI page layout 2025-08-20 18:09:00 +03:00
Atanas Korchev
d5fcbb97c3 Add AI page. 2025-08-20 16:47:11 +03:00
yordanov
97555e7849 FrozenColumn should have alternating rows. Resolves #2265 2025-08-20 13:43:14 +03:00
Vladimir Enchev
7eb799d2a6 DataGridLoadColumnFilterDataEventArgs Property added 2025-08-20 11:17:08 +03:00
Vladimir Enchev
d06a85a3b6 Fixed DataGrid CheckBoxFilter form id when both Property and FilterProperty are defined 2025-08-20 11:05:32 +03:00
Vladimir Enchev
f616eadccf DataGrid column AlwaysShowAllCheckBoxListData property added 2025-08-20 10:57:57 +03:00
Vladimir Enchev
b69d6c193b Fixed DataGrid endless loop in load settings with columns width 2025-08-19 16:02:57 +03:00
Josh
d12908778e RadzenDropDown/Grid: Modify bound collection in-place (#2261)
* Refactor out code that assigns and notifies for Multiple when items are Selected

* Add alternative handling to support keeping the bound collection instance unchanged. This also enables support for custom collections without default ctors, and HashSets

* Ensure ClearAll maintains collection instance, instead of setting to null

* Ensure SelectdAll uses the same new behavior

* resolve the actual type of the bound collection, in determining if to apply the ReferenceGenericCollectionAssignment

# Conflicts:
#	Radzen.Blazor/DropDownBase.cs

* fixup: Ensure non-multiple/non-collection sources are accomodated

# Conflicts:
#	Radzen.Blazor/DropDownBase.cs

* use the more tactical approach for altering the collection to match selectedItems.  This preserves ordering and will raise expected INotifyCollectionChanged events if implemented

* cleanup: naming convention
2025-08-19 07:44:31 +03:00
Vladimir Enchev
95c42f3266 Version updated 2025-08-18 10:58:09 +03:00
Vladimir Enchev
597e6de682 AIChatService HttpClient resolved runtime 2025-08-18 10:38:57 +03:00
Vladimir Enchev
406141a4f1 Injected HttpClient removed from RadzenAIChat since it's not needed 2025-08-18 10:32:28 +03:00
Ali Yousefi
0db7fe63b0 feat: make ClearFilters virtual (#2263) 2025-08-18 10:09:03 +03:00
Vladimir Enchev
e5a43ef5b6 DatePicker will not display value initially when set to midnight 2025-08-15 10:03:00 +03:00
Petar Slavov
4d9a9c9ac2 Add GetProperty that supports retrieval of interface properties. (#2255)
* Introduces a new static method `GetProperty` in the `Radzen.PropertyAccess` class to retrieve properties by name, including support for interfaces. Updates `DropDownBase.cs` to utilize this new method, enabling property retrieval for collections of interfaces in multiselect DropDowns.

* Add unit tests for property resolution in interfaces

Implemented unit tests in `PropertyAccessTests.cs` to verify
the resolution of `Description`, `Name`, and `Id` properties
from the interfaces `ISimpleInterface`, `ISimpleNestedInterface`,
and `ISimpleBaseInterface`. Defined the interfaces to support
the tests for the `GetProperty` method functionality.
2025-08-15 09:28:52 +03:00
Vladimir Enchev
3cc1f6b994 Version updated 2025-08-14 08:57:50 +03:00
Vladimir Enchev
4322361269 AIChatService added to AddRadzenComponents 2025-08-14 08:57:12 +03:00
Vladimir Enchev
44d3651aa8 chat tests fixed 2025-08-14 07:55:09 +03:00
Atanas Korchev
03423f32c8 Remove the version. 2025-08-13 20:38:23 +03:00
Atanas Korchev
bf8c950a8a Build the API reference without mono. 2025-08-13 19:12:24 +03:00
Vladimir Enchev
f16ae734cc More DocFX removed 2025-08-13 18:18:01 +03:00
Vladimir Enchev
91196dca39 DOCFX removed 2025-08-13 18:17:17 +03:00
Vladimir Enchev
ea36ff5011 update 2025-08-13 18:13:50 +03:00
Vladimir Enchev
dad418140b mono:latest updated 2025-08-13 18:11:43 +03:00
Vladimir Enchev
d5f8877768 docker updated 2025-08-13 17:54:50 +03:00
Vladimir Enchev
95f2dfa8ac docker updated 2025-08-13 17:53:10 +03:00
Vladimir Enchev
d60b14c686 various warnings fixed 2025-08-13 16:23:26 +03:00
Vladimir Enchev
fabcd7b8f4 Version updated 2025-08-13 16:16:36 +03:00
yordanov
045880c234 Update premium themes 2025-08-13 16:09:38 +03:00
Vladimir Enchev
d2071102c5 RadzenChat component added (#2254) 2025-08-13 15:37:01 +03:00
Ehab Hussein
864bc8c7f9 Add Sankey Diagram Component to Radzen Blazor (#2220)
* Add SankeyDiagram Component

---------

Co-authored-by: Atanas Korchev <akorchev@gmail.com>
Co-authored-by: yordanov <vasil@yordanov.info>
2025-08-13 15:20:06 +03:00
Nenad Kovačević
b63b861b8a Fixed a typo in IconPage.razor (#2253) 2025-08-13 13:35:58 +03:00
Vladimir Enchev
23effbb3ec Upload MaxFileCount error handling fixed 2025-08-13 09:55:42 +03:00
Vladimir Enchev
c0a87c834c all tests fixed 2025-08-13 09:29:41 +03:00
Vladimir Enchev
4d02213260 test fixed 2025-08-13 09:19:41 +03:00
Vladimir Enchev
46118964ea Added DataTable support for DataGrid 2025-08-13 09:14:59 +03:00
Vladimir Enchev
ca52c588fd Revert "feature: DataGrid Columns allow Sort and Filter when bound to Array<o… (#2233)"
This reverts commit 4503361877.
2025-08-13 08:52:41 +03:00
Vladimir Enchev
b9905e10de Revert "XML comment fixed"
This reverts commit 62cf565a09.
2025-08-13 08:52:30 +03:00
Vladimir Enchev
7ea08af177 Revert "DataGrid DataTable improved"
This reverts commit c90e3bedb1.
2025-08-13 08:52:25 +03:00
Vladimir Enchev
fa59aff6d5 RadzenDropDown ReadOnly can be bypassed with keyboard select as you type 2025-08-13 07:59:49 +03:00
Vladimir Enchev
c90e3bedb1 DataGrid DataTable improved 2025-08-12 10:39:37 +03:00
Vladimir Enchev
62cf565a09 XML comment fixed 2025-08-12 10:26:49 +03:00
EdJohnstonG9
4503361877 feature: DataGrid Columns allow Sort and Filter when bound to Array<o… (#2233)
* feature: DataGrid Columns allow Sort and Filter when bound to Array<object>[] i.e. DataRow.ItemArray[n]

* Expose Test page and fix AmbiguousMatch in test (ItemArray not Item)

* Working filters before test

* In Sorting Tests

* Filter by ChecBoxList to be done

* Better solution to filter types

* Solution for Enum in DataTable

* Tidy up and fix of Enum Null
Working Enums

* Re-enabled all data sources in tests

* Prevent display of simple filter input when fitler expects enumerable
Show correct demo code, only when merged with Master

* Fix to handle Filter lists with nullable enums
2025-08-12 10:24:53 +03:00
Vladimir Enchev
f2bc7ef3ed Version updated 2025-08-11 09:16:59 +03:00
Vladimir Enchev
f9505e42c4 Fixed DataGrid CheckBoxList Filter error when filtering ICollection property 2025-08-10 09:04:28 +03:00
GAUSS-LVS Dev
d340df758e Fixed timing problem in RadzenTreeItem OnInitializedAsync (#2246)
Fixed an issue that the order of CurrentItems could be wrong when items are expanded simultaneously.

Co-authored-by: mde <m.deppe@gauss-lvs.de>
2025-08-09 10:30:53 +03:00
Vladimir Enchev
741ecf0955 Fixed DataGrid DoesNotContains filter throws No coercion operator is defined between types ‘System.String’ and ‘System.Boolean’ 2025-08-09 10:28:33 +03:00
yordanov
90ab2e468e Preloader should have properly set opacity when the grid is loading. Resolves #2205 2025-08-08 15:01:01 +03:00
yordanov
360b9d7730 Wrong link in image URL demo. Resolves #2245 2025-08-07 18:26:12 +03:00
Vladimir Enchev
bb698dbe9d version updated 2025-08-04 08:31:12 +03:00
Vladimir Enchev
5e120a7328 DataGrid filter clear not visible, for simple FilterMode, when FilterProperty is different from Property
Fix #2237
2025-08-04 08:23:39 +03:00
Vladimir Enchev
206daba741 DataGrid simple filter should be rendered only for relevant columns 2025-08-04 08:08:33 +03:00
Mohammad Mohammadi
79e86e8b76 Improve numeric input handling for all locales (including Persian and Arabic) (#2240)
* Improve numeric input support in JS: accept all Unicode digits using `\p{Nd}`

Replaced hardcoded digit ranges with Unicode-based digit detection using `\p{Nd}‍` to ensure support for Persian, Arabic, and other locale-specific numerals.

* fix: support all Unicode digit inputs in RadzenNumeric

Replaced digit handling logic with Unicode-aware checks using `char.IsDigit` to support numeric input from any language, including Persian and Arabic.

Previously, non-ASCII digits were blocked, which caused issues for users entering Persian or Arabic numerals. This fix makes the component input-agnostic to digit origin.
2025-08-01 08:08:51 +03:00
Atanas Korchev
398c17c75a Add support for immediate changes to RadzenTextBox (enabled via Immediate=true). Closes #909. 2025-07-25 10:03:22 +03:00
Vladimir Enchev
49adc95170 Version updated 2025-07-24 10:10:15 +03:00
Dmitry Solovev
2b71bd1178 Fix IconColor in ProfileMenuItem (#2229)
Co-authored-by: Дмитрий Соловьев <dsolo@codestetic.com>
2025-07-23 10:16:49 +02:00
Frank Folsche
c53938bc0a #1761 offset when filtermenu row is active (#2223) 2025-07-16 15:26:44 +03:00
joriverm
718827d757 feature: implement disabled on panel menu items (#2222)
Co-authored-by: AI\jvermeyl <joris.vermeylen@uzgent.be>
2025-07-16 15:22:20 +03:00
Vladimir Enchev
b4c87e7e10 Role "tab" removed from a element in RadzenTabsItem 2025-07-16 11:54:52 +03:00
Vladimir Enchev
20dd0e9b2d TabsItem role set to "tab" 2025-07-16 11:53:21 +03:00
Vladimir Enchev
397e2d207e Version updated 2025-07-10 15:36:45 +03:00
Vladimir Enchev
29f7b6cb74 DropDownBase should allow filter on SPACE while still be able to select/deselect items 2025-07-10 15:33:33 +03:00
joriverm
a004b55e8c feature: make fieldidentifier settable as parameter (#2216)
Co-authored-by: AI\jvermeyl <joris.vermeylen@uzgent.be>
2025-07-10 14:48:29 +03:00
Vladimir Enchev
221d8f0697 DataGrid should set column CustomFilterExpression to null on Reset() 2025-07-10 14:36:03 +03:00
Vladimir Enchev
e7a243ab7f DataGrid LoadDataArgs.Filter should use it for instance name in case of column CustomFilterExpression 2025-07-10 14:27:45 +03:00
Vladimir Enchev
ce1ffe2070 DataGrid FilterMode.CheckBoxList crashes when selecting all items in a non string column
Fix #2213
2025-07-10 12:05:22 +03:00
Gincsai Gábor
32e2419b67 Suppott filtering List<string> like sub-property. (#2210)
* Suppott filtering List<string> like sub-property. In this case no nested property so use the collectionItemTypeParameter.

* Extend the FilterValueDemo with Awards that uses List<string> property with multiple filter.
The demo works with in memory data, but not with on backend side with Oracle database.
2025-07-09 17:59:15 +03:00
Piotr Mazur
5f7079e526 Fix type assignment in RadzenDataGrid to get the correct type (#2209)
* Add missing Type field when creating FilterDescriptors in RadzenDataGrid InvokeLoadData method

* Fix type assignment in RadzenDataGrid to get the correct type

---------

Co-authored-by: Piotr Mazur <piotr.mazur@lstsoft.com.pl>
2025-07-08 13:34:39 +03:00
Vladimir Enchev
4ffeae11e2 code fixed 2025-07-08 13:32:39 +03:00
Vladimir Enchev
7621e31d38 RadzenAutoComplete will select value on NumpadEnter 2025-07-08 11:32:29 +03:00
Gincsai Gábor
c00c751127 System.Type cannot be serialized out of the box in C# (possible security issue) (#2208)
With ignoring the Type property FilterDescriptor can be used for custom server side filtering.
2025-07-08 08:11:23 +03:00
Vladimir Enchev
a09f550b52 DataGrid double IsEmpty/IsNotEmpty filters fixed 2025-07-07 16:33:52 +03:00
Vladimir Enchev
0aeb1cfa97 Version updated 2025-07-07 14:55:49 +03:00
Piotr Mazur
46da7e45b9 Add missing Type field when creating FilterDescriptors in RadzenDataGrid InvokeLoadData method (#2207)
Co-authored-by: Piotr Mazur <piotr.mazur@lstsoft.com.pl>
2025-07-07 14:54:59 +03:00
Vladimir Enchev
83bf448bdd Add in RadzenTree with async Expand calls error 2025-07-07 10:30:14 +03:00
Atanas Korchev
5ab15fb812 Add crossorigin attribute when preloading the icon font. 2025-07-03 15:32:38 +03:00
mvoxland
0dc70f3e42 DropDownDataGrid null check to prevent error that occurs when using AllowFilteringByAllStringColumns="true" (#2201)
To replicate this bug: just add AllowFilteringByAllStringColumns="true" to the Multiple Selection example for DropDownDataGrid
2025-07-01 13:47:14 +03:00
Vladimir Enchev
5bc86a75bc DataGrid column ShowCellDataAsTooltip property added 2025-07-01 13:46:26 +03:00
Vladimir Enchev
51d3df9282 Version updated 2025-06-30 11:08:57 +03:00
Vladimir Enchev
31925ea099 DropDownBase select item as you type fixed 2025-06-28 09:22:30 +03:00
yordanov
a56e6540e8 Update premium themes 2025-06-27 11:32:34 +03:00
Cosmatevs
03bccb4cb4 DropDown, DropDownDataGrid: fix font family in filter inputs 2025-06-27 11:30:38 +03:00
yordanov
bba9b7b6ec Update Material Icons font. Resolves #2187 2025-06-26 11:47:37 +03:00
yordanov
5b8ea6e4b0 Add font-display rules 2025-06-26 11:14:41 +03:00
yordanov
91676d802c Improve ripple styles for rz-state-disabled 2025-06-25 18:54:33 +03:00
yordanov
395d343f69 Grid cell focus state should be visually distinct from selected state in Standard and Material3 themes 2025-06-25 16:36:38 +03:00
Atanas Korchev
201993ff08 RadzenTheme preloads the icon font. 2025-06-24 13:43:30 +03:00
Vladimir Enchev
f9499904f3 DataGrid simple filter menu will not show string filter operators for string columns 2025-06-24 13:26:07 +03:00
Vladimir Enchev
0a152474a2 Version updated 2025-06-23 14:39:59 +03:00
Lukas Grützmacher
8dc522e054 Function key should not trigger DropDown Change event (#2195) 2025-06-23 07:40:29 +03:00
Vladimir Enchev
eb8209d575 Missing XML comments added 2025-06-20 11:05:29 +03:00
Simon Lissack
96b3ac7435 Support deserializing unsigned integers when loading filter column values (#2190) 2025-06-20 11:00:25 +03:00
Vladimir Enchev
42d7113896 DropDownDataGrid GridLines property added 2025-06-20 07:45:17 +03:00
Vladimir Enchev
7f19786053 ContextMenu should prevent the browser context menu 2025-06-20 07:37:31 +03:00
Lee
52b121a9f4 Updating HtmlEditor methods and properties to public (#2189)
* Updating methods and properties to public, to make it easier to customise and create custom HtmlEditor buttons in your own projects.

* Putting SourceChanged back to private
2025-06-19 16:37:11 +03:00
Atanas Korchev
d191a8223e Events with zero duration are sometimes invisible in month view. 2025-06-19 15:09:52 +03:00
Vincent Schmandt
b371b43a86 fix: avoid accessing parameter view in SetParametersAsync after an async call to prevent a race condition (#2186)
* fix: avoid accessing parameter view in SetParametersAsync after an async call to prevent a race condition

Fixes: https://forum.radzen.com/t/the-parameterview-instance-can-no-longer-be-read-because-it-has-expired/18912/7
See also: https://stackoverflow.com/questions/66717054/the-parameterview-instance-can-no-longer-be-read-because-it-has-expired-paramet

* fix SetParametersAsync reordering
2025-06-18 14:35:59 +03:00
Vladimir Enchev
c243f384a5 DataGrid column filter menu not unique in case of columns with same property names 2025-06-18 14:06:16 +03:00
Vladimir Enchev
e10f8d759c Version updated 2025-06-18 11:15:21 +03:00
Vladimir Enchev
977e5b8cb6 DataGrid LoadDataArgs Filters should respect the column FilterProperty 2025-06-17 14:59:57 +03:00
yordanov
b68f95a7e7 Update main navigation 2025-06-17 10:08:37 +03:00
yordanov
e30b01de23 Update premium themes 2025-06-17 09:39:27 +03:00
Vladimir Enchev
68f87db33e DataGrid CheckBoxList filter on wrong column in some cases 2025-06-16 14:26:21 +03:00
Romaniv Volodymyr
f2bfa462a0 Fix #2167 (#2185)
Set cursor to initial for disabled RadioButtonList elements
2025-06-16 10:07:11 +03:00
yordanov
adffcf5229 RadzenLayout components should not have 100vw on mobile screens. Resolves #1956 2025-06-13 10:43:40 +03:00
yordanov
a4f37cbcfa Fix active state styles in demos navigation menu 2025-06-12 17:21:44 +03:00
Vladimir Enchev
18d8328a9c Version updated 2025-06-12 11:04:17 +03:00
Vladimir Enchev
a466578ebf ExpressionSerializer should respect the DateTime.Kind
Fix #2183
2025-06-12 11:03:51 +03:00
yordanov
c92f8833e2 Fix toc confing in home layout 2025-06-12 10:44:17 +03:00
Vladimir Enchev
2f46c58028 Enabled search on non string properties for DataGrid CheckBoxList filter
Fix #2182
2025-06-12 10:35:47 +03:00
joriverm
a1c24e346c fixes: Let all DataBoundFormComponent's expose value as the actual type that it is (#2179)
Co-authored-by: AI\jvermeyl <joris.vermeylen@uzgent.be>
2025-06-11 15:39:37 +03:00
yordanov
fb7fb62a0e Update links in main nav 2025-06-11 15:28:39 +03:00
Vladimir Enchev
7378ee1a32 Login ShowLoginButton not respected in some cases 2025-06-11 15:25:15 +03:00
yordanov
0bee5b4365 Update demos main navigation and overview layout 2025-06-11 15:23:20 +03:00
yordanov
47bfd6f539 RadzenMenu active state should be visually distinguishable 2025-06-11 15:23:20 +03:00
Erik van der Boom
1b92cb7f86 Reset select on filter (#2180)
* Add reset index on filter option

* remove unwanted spaces

* correct order
2025-06-11 09:34:31 +03:00
Vladimir Enchev
2931d47d05 AllowFilteringByWordCount default value set to 10 2025-06-09 11:12:43 +03:00
Vladimir Enchev
7668a54648 DropDownDataGrid AllowFilteringByWordCount property added 2025-06-06 10:08:03 +03:00
Vladimir Enchev
aa0aaf7c10 Version updated 2025-06-05 10:04:29 +03:00
Vladimir Enchev
4b80da96ab Shift key should not trigger DropDown Change event
Fix #2165
2025-06-05 10:03:20 +03:00
Vladimir Enchev
396fa19d7b ListBox registers two keys on focus
Fix #2172
2025-06-04 07:57:02 +03:00
Vladimir Enchev
4cd235a08e DataGrid filter menu IsEmpty/IsNotEmpty options added for string columns 2025-06-04 07:46:53 +03:00
Vladimir Enchev
edd21956c5 DateTimeWithRoundtripKind test added 2025-05-30 09:58:59 +03:00
mvoxland-MoorheadSchools
f842156253 Datetime parsing fix, stop converting to local Kind (#2171) 2025-05-30 09:44:56 +03:00
Paul Ruston
ce0ce0f229 Supply Appointment data to SchedulerSlotRenderEventArgs - #2050 (#2154)
* Supply Appointment data to SchedulerSlotRenderEventArgs

* Get appointments on demand

* Revert YearView SlotRender code to remove breaking change. Update demo
2025-05-27 10:24:37 +03:00
Vladimir Enchev
ae2e9219c3 Version updated 2025-05-27 09:14:27 +03:00
Vladimir Enchev
146b374ca8 DataGrid CheckBoxList filter not populated properly in case of self-referencing hierarchy 2025-05-27 07:54:53 +03:00
Vladimir Enchev
9264676407 Non generic IDictionary support added for expressions
Close #2169
2025-05-27 07:17:05 +03:00
Victor Ureta
eb74460fcf add icon in Title Dialog (#2170)
* add icon in Title Dialog

* fix IconColor in DialogService.cs

* fix variables
2025-05-26 18:48:47 +03:00
Vladimir Enchev
16ed582052 DataGrid column with CustomFilterExpression will not filter innitially 2025-05-23 09:26:15 +03:00
Vladimir Enchev
a7ddb81ad1 ToFilterString() should serialize only date of DateTime with zero time 2025-05-23 09:02:38 +03:00
Atanas Korchev
d09f3870b1 RadzenCompareValidator validates when the Visible property is set to true. Closes #2148. 2025-05-22 11:58:20 +03:00
Atanas Korchev
9a8e249964 RadzenScheduler throws error on window resize when placed in a hidden element. 2025-05-22 11:47:56 +03:00
Vladimir Enchev
c63d9cf0b9 DataGrid CheckBoxList filter search will work properly when binding to dynamic data 2025-05-22 09:46:06 +03:00
Vladimir Enchev
f6648f80ec Numeric null. reference exception fixed 2025-05-22 09:23:19 +03:00
Vladimir Enchev
250bff7ef3 ToCSV() export method will handle comma 2025-05-22 09:23:18 +03:00
Nopke
fa0b925aa9 TimeSpanPicker: fix missing panel fields if only Min or only Max is set (#2166) 2025-05-21 08:39:43 +03:00
Atanas Korchev
28fe2949f2 Add CloseSideAsync method to DialogService which waits for the close animation to complete. Closes #2161. 2025-05-20 11:49:50 +03:00
Vladimir Enchev
d7f46216e9 ToFilterString() and ToODataFilterString() extension methods added to IEnumerable<CompositeFilterDescriptor> 2025-05-20 11:46:24 +03:00
Vladimir Enchev
3f0d82a427 Version updated 2025-05-20 08:56:30 +03:00
yordanov
d2811c9fba Fix typo. 2025-05-16 22:20:20 +03:00
yordanov
028e26ef59 Add Accessibility Conformance Report 2025-05-16 10:19:42 +03:00
yordanov
4086332857 RadzenAccordion items should be displayed vertically in RadzenStep 2025-05-15 15:32:43 +03:00
yordanov
1eebfccf14 Remove Dialog's scale animation if it has RadzenChart inside 2025-05-15 15:03:32 +03:00
Vladimir Enchev
f1127f917d DataGrid CheckBoxList filter list not populated in some cases 2025-05-15 13:59:47 +03:00
yordanov
6cc8700bb9 Update UI blocks description 2025-05-15 10:44:16 +03:00
yordanov
3cabcd5cf9 Update info on how to use UI Blocks 2025-05-15 10:25:56 +03:00
yordanov
c5aaeb67b5 Update badges on homepage 2025-05-15 10:25:56 +03:00
Vladimir Enchev
47fcd54d1c version updated 2025-05-15 07:28:28 +03:00
Vladimir Enchev
5dd5cd8ae1 DataGrid grouping exception with wrong type discovery
Fix #2153
2025-05-15 07:28:10 +03:00
Vladimir Enchev
8ab18160a5 Demo updated to handle query that cannot be translated to SQL 2025-05-14 10:52:26 +03:00
Vladimir Enchev
b70b697f3f DataGrid column FilterProperty should be respected if specified 2025-05-14 09:18:30 +03:00
Vladimir Enchev
48eb35e20d Version updated 2025-05-13 20:57:58 +03:00
Atanas Korchev
4fd899133f Cannot parse certain expressions that include string and number comparisons. 2025-05-13 20:52:44 +03:00
Vladimir Enchev
3b134cf8b5 code fixed 2025-05-13 09:28:55 +03:00
Atanas Korchev
86bc538601 Some zero-length events appear on top of each other in month view. 2025-05-13 08:42:11 +03:00
Atanas Korchev
fb00fbc850 Add anchor for the day, week and month view demo. 2025-05-13 08:42:11 +03:00
Vladimir Enchev
309f9fcfa1 DataGrid will populate Query.Filter and LoadDataArgs.Filter only if accessed 2025-05-12 13:46:29 +03:00
Vladimir Enchev
253aa63980 Version updated 2025-05-12 13:03:28 +03:00
Vladimir Enchev
93dea13f20 Added support for indexer expressions with sub properties 2025-05-12 12:36:02 +03:00
Atanas Korchev
3d3d1718b7 Add editable source code to dashboard demo. 2025-05-12 11:00:25 +03:00
Cosmatevs
90c2a5d51f fix recognizing standard dark theme as dark by components 2025-05-12 10:34:44 +03:00
Vladimir Enchev
8846a229d8 Added support for Dictionary<string, string> for expressions 2025-05-12 09:31:12 +03:00
Pedro Constantino
acf0591adc [FEAT] - Adding the possibility to return the source in the upload event args when managing file uploads via RadzenUpload. (#2151) 2025-05-12 07:31:42 +03:00
yordanov
95bee47826 PanelMenu item expand arrow should not be displayed when child items are absent. Resolves #2147 2025-05-09 19:44:18 +03:00
Atanas Korchev
b701976356 Expanded panel menu items do not always collapse when Multiple is set to false. 2025-05-09 14:53:54 +03:00
Vladimir Enchev
2b61941e34 Version updated 2025-05-08 17:24:08 +03:00
yordanov
1526ffa3af Update premium themes 2025-05-08 17:19:02 +03:00
Cosmatevs
bb4227e537 fix the bottom border color of a hovered/focused input field in Standard themes 2025-05-08 17:08:01 +03:00
Vladimir Enchev
778691405d version updated 2025-05-08 15:04:17 +03:00
Atanas Korchev
cb7d3b91c6 Add Template property to RadzenTocItem. 2025-05-08 15:01:53 +03:00
Atanas Korchev
fd8cf16336 NullReferenceException thrown by RadzenLayout when AddRadzenComponents is not used. 2025-05-08 14:54:33 +03:00
yordanov
2403cf222f Add TOC to demos homepage 2025-05-08 14:39:31 +03:00
yordanov
20152dd8a6 Fix duration progress position in Notification. Resolves #2104 2025-05-08 11:47:42 +03:00
Vladimir Enchev
b459207b7a Links inside popup should close the popup only on left mouse button click 2025-05-08 07:48:44 +03:00
Atanas Korchev
8b009509c8 Add accordion breaking change to changelog. 2025-05-07 20:13:29 +03:00
Atanas Korchev
c456891a11 Convert to the left operand type if the right type is object during null coalescing. 2025-05-07 15:25:34 +03:00
yordanov
6b044d8086 Update demos' badges 2025-05-07 14:53:07 +03:00
Atanas Korchev
3162de84ed Update the busy dialog demo. 2025-05-07 14:32:20 +03:00
Atanas Korchev
641768240a Update the changelog. 2025-05-07 14:07:30 +03:00
Vladimir Enchev
8b7ade4b9c Version updated 2025-05-07 13:14:37 +03:00
Vladimir Enchev
c7db9394c8 V7 (#2144)
* Remove Microsoft.CodeAnalysis. Add own C# expression parser.

* Popup dialog animations (#2118)

* Experiment with popup and dialog animations.

* Move animations to a separate _animations.scss

* Remove dialog closing animation.

* Support side dialog positions. Prefix keyframes.

* Use --rz-transition for animation function and duration

* Reset site.css.

* PanelMenu animations.

* Display none is toggled a bit late.

* RadzenPanel animations.

* More animations.

* Use transitions for panel menu.

* Remove old code.

* Accordion uses transitions.

* Panel uses transitions.

* Extract expand and collapse implementation in a separate component.

* Set initial expand state earlier to prevent two renders.

* Add open animation to notifications.

* Handle onanimationend before toggling the animation classes.

* Add menu animation.

* Experiment with tree animation.

* Add animations to fieldset.

---------

Co-authored-by: yordanov <vasil@yordanov.info>

* ExpressionSerializer and tests added (#2119)

* Fix failing tests.

* various components RequiresUnreferencedCode attribute added (#2120)

* RequiresUnreferencedCode added to ExpressionSerializer

* Update premium themes

* RequiresUnreferencedCode added to ExpressionParser

* FormComponentWithAutoComplete RequiresUnreferencedCode removed

* Revert "FormComponentWithAutoComplete RequiresUnreferencedCode removed"

This reverts commit ec900a4df8.

* Revert "RequiresUnreferencedCode added to ExpressionParser"

This reverts commit f93b3b159b.

* Revert "RequiresUnreferencedCode added to ExpressionSerializer"

This reverts commit 06fecec9a6.

* Revert "various components RequiresUnreferencedCode attribute added (#2120)"

This reverts commit 2ed1a6cac1.

* Remove RadzenHtml.

* ExpressionSerializer FormatValue updated to use InvariantCulture

* Catch potential JS interop exceptions that could occur during disposing.

* Revert "Remove RadzenHtml."

This reverts commit 319085bf49.

* SelectBar made single tab stop

* RadioButtonList and CheckBoxList made single tab stop

* SelectBar accessibility improved

* RadioButtonList accessibility improved

* CheckBoxList accessibility improved

* Update radio button focus styles

* Update checkbox list focus styles

* Update Checkbox Radio and SelectBar focus styles

* SelectBar, CheckBoxList and RadioButtonList focus state improved

* Check for Multiple added

* Use non-rendering event handlers for transitionend.

* Rename css class rz-selectbutton to rz-selectbar and improve focus states

* Fix selectbar focus outline offset

* Update premium themes

* Selectbar item focus styles should not be visible if the item is disabled.

* CheckBoxList and RadioButtonList item focus should be visible only on keyboard input

* SelectBar, CheckBoxList and RadioButtonList focus logic improved

* Update animations

* RadzenText margin-block should be 0 if it is in RadzenStack. Resolves #2134

* RadzenText margin-block should be 0 if it is first level child in RadzenStack

* CheckBoxList focused fixed

* Add toggle state classes to panel menu icon.

* Update accordion styles to reflect expander changes

* Add animation styles to expand arrow in Menu and ProfileMenu

* Use a instead of NavLink as it seems to cause performance issues.

* Set @bind-Expanded.

* Revert "Set @bind-Expanded."

This reverts commit 994107367bdf09043950f8bbe701eb9edefec676.

* Revert "Use a instead of NavLink as it seems to cause performance issues."

This reverts commit 05d5bef8f421bbeb5828ba1e9c5af6793ea3d32a.

* Reduce rendering of panel menu items.

* Add panel menu component.

* Use ChildContent to render the toggle icon of the panel menu item.

* Sync panel menu item selection in the item itself.

* Rename ExpandedInternal to expanded.

* Move filtering to the panel menu component.

* Remove the transitionend handler to avoid a second rendering pass.

* Build the assets for the net9.0 framework.

* Do not trigger render when Click is used.

* Panel menu keyboard navigation renders only when needed.

* Focus reworked to use AsNonRenderingEventHandler

* Focus the first item.

* Update Panel demo

* Use a more robust algorithm for month view event rendering that handles overlapping of events across a week.

* Use RadzenStack in RadioButtonList

* Add parsing support for `&` and `|`.

* Add parsing support for `^`, `>>` and `<<`.

* Simplify expression parsing tests.

* Use RadzenStack in RadioButtonList and CheckBoxList

* Change defaults for AlignItems and JustifyContent in RadioButtonList and CheckBoxList

* Update RadioButtonList and CheckBoxList demos

* Add --rz-input-border-block-end css variables to improve Fluent theme styles

* Removed AsNonRenderingEventHandler from RadioButtonList and HtmlEditor focus and blur

* Removed AsNonRenderingEventHandler from CheckBoxList

* Simplify RadzenTable rendering.

* Optimize memory usage of the ClassList utility.

* Refactor RadzenButton to use ClassList.

* RadzenSelectBar and RadzenSplitButton use ClassList.

* Refactor RadzenBadge and RadzenAlert to use ClassList.

* Refactor RadzenCard and RadzenFormField to use ClassList.

* Refactor RadzenCardGroup and progress components to use ClassList.

* Refactor RadzenMenu to use ClassList.

* Use ClassList in RadzenBody, RadzenLayout and editor rendering components.

* RadzenDialog uses ClassList.

* RadzenDataGrid uses ClassList.

* RadzenPager uses ClassList.

* RadzenColumn uses ClassList.

* Fix RadzenSplitButtonItem focused state.

---------

Co-authored-by: Atanas Korchev <akorchev@gmail.com>
Co-authored-by: Atanas Korchev <454726+akorchev@users.noreply.github.com>
Co-authored-by: yordanov <vasil@yordanov.info>
Co-authored-by: Quentin H <67709967+quintushr@users.noreply.github.com>
2025-05-07 13:11:30 +03:00
yordanov
513e63329b Fix RadzenSplitButtonItem focused state. Resolves #2137 2025-05-05 16:36:54 +03:00
amir7800h
cfd104385d Update RadzenDatePicker.razor.cs (#2140)
When setting the project culture (e.g., to fa-IR), the year was still being displayed using the Gregorian calendar, which caused incorrect date representation in the UI.
This fix ensures that the DateTimeFormat.Calendar is properly respected, and now the year is displayed correctly based on the assigned calendar (e.g., PersianCalendar).

Before
Culture set to fa-IR

Year displayed as Gregorian (e.g., 2025 instead of 1404)

After
Year display matches the Calendar set in DateTimeFormat

Fully localized and culture-respecting date output
2025-05-05 08:09:59 +03:00
Atanas Korchev
2d9641eecf Toc preserves query string parameters. 2025-05-03 15:18:09 +03:00
Vladimir Enchev
65a78125b2 DropDownBase select item as you type fixed 2025-04-30 11:45:09 +03:00
Vladimir Enchev
28572ba4d3 version updated 2025-04-29 18:06:24 +03:00
Vladimir Enchev
28a603ca1e Dynamic Where() with parameters fixed 2025-04-29 18:06:11 +03:00
Frank
b9fa303f7f NotifyValidationStateChanged() / StateHasChanged() is only be executed if the IsValid field has actually changed. (#2127) 2025-04-28 11:14:11 +03:00
Vladimir Enchev
756dde90ab DataGrid will allow combining advanced and simple filtering for different columns
Close #2128
2025-04-25 11:40:59 +03:00
Vladimir Enchev
c2a396167e DataGrid advanced filter clear fixed 2025-04-24 16:34:23 +03:00
Vladimir Enchev
c1fd207723 Version updated 2025-04-24 13:05:03 +03:00
Vladimir Enchev
8f1fc0a164 Revert "QueryableExtension OrderBy() should not use ExpressionParser"
This reverts commit a389dc702b.
2025-04-24 13:04:31 +03:00
Evan Dixon
538ec3c744 Make OnChipRemove overridable (#2122)
Co-authored-by: Dixon, Evan <edixon@mimeo.com>
2025-04-24 08:43:47 +03:00
Victor Ureta
6fed13bf12 Add TextTemplate parameter to RadzenFormField Blazor component (#2123)
* Update RadzenFormField.razor

* Update RadzenFormField.razor.cs
2025-04-24 08:25:02 +03:00
Vladimir Enchev
104cc7c900 Version updated 2025-04-23 10:00:49 +03:00
Reinhard
8fa699a92e Fixing 1st column with sub-row expander visible not taking column.IsInEditMode callback into account for rendering edit template. (#2097) 2025-04-23 09:06:24 +03:00
Quasmo
1ab7059830 Added DisplayToolTipFor Method to RadzenChart.razor.cs. (#2115)
* Added DisplayToolTipFor Method to RadzenChart.razor.cs. Made Series property public.

* Chnaged Series public accessor back to internal. Added GetSeries Method that returns an IReadOnlyList of the Series. Added XML documentation. Made changes to DisplayTooltipFor Method. Removed null checks and try/catch block.

* removed unnessecary usings.

---------

Co-authored-by: John Tolliver <jtolliver@wbrsllc.com>
2025-04-23 07:44:50 +03:00
Greg Horvath
377b2613db Fixes bug #2113. (#2114) 2025-04-23 07:18:00 +03:00
Atanas Korchev
bc7b0a9bdb Take axis label rotation into account when measuring the category axis size. 2025-04-22 10:36:09 +03:00
Krystian Szatan
8665a351db Update RadzenSplitButton (#2103)
Added ButtonType parameter to allow EditForm submit
2025-04-18 11:29:44 +03:00
Vladimir Enchev
dd02bf8b8d Notification demo reworked with toc 2025-04-16 11:31:03 +03:00
Vladimir Enchev
487c423eef Version updated 2025-04-15 18:20:24 +03:00
Atanas Korchev
87bcfa729c RadzenMarkdown renders HTML attributes incorrectly. 2025-04-15 18:18:50 +03:00
yordanov
0332e8c671 Fix anchors on Accordion demo page 2025-04-15 15:56:37 +03:00
Atanas Korchev
7264354ce6 Soft line breaks are not rendered and strip whitespace. Fixes #2095. 2025-04-15 13:14:05 +03:00
Vladimir Enchev
bde3315994 Version updated again 2025-04-15 12:59:24 +03:00
Vladimir Enchev
7ecd08b0d8 Version raised 2025-04-15 12:58:01 +03:00
Vladimir Enchev
93feb382ca Version updated 2025-04-15 12:56:35 +03:00
yordanov
186d9b3798 Update toc demos 2025-04-15 12:27:23 +03:00
yordanov
1f3e44819d Remove selected rz-toc-item font-weight and fix width of rz-toc-link 2025-04-15 12:06:33 +03:00
Atanas Korchev
4b942f2f45 Add toc to the upload demo. 2025-04-15 11:46:29 +03:00
Vasil Yordanov
7214cd7179 Add RadzenToc component (#2094)
RadzenToc component is a table of contents based on the titles in a page allowing users to quickly navigate the page.

---------

Co-authored-by: Atanas Korchev <akorchev@gmail.com>
2025-04-15 11:14:38 +03:00
Vladimir Enchev
90c11b5c04 Version updated 2025-04-14 11:39:59 +03:00
Atanas Korchev
4007339d26 Sanitize link and image destination. 2025-04-14 11:37:18 +03:00
yordanov
8bc43443a7 Fix contrast with new styles for active filter in DataGrid's simple filter modes. Resolves #2090 2025-04-14 10:26:52 +03:00
Vladimir Enchev
a389dc702b QueryableExtension OrderBy() should not use ExpressionParser 2025-04-14 09:33:02 +03:00
Nopke
1b39fa37e0 TimeSpanPicker: fix not using last changed input value, disable autocomplete (#2089)
* TimeSpanPicker:
* fix occasionally not using last changed input value after clicking the confirmation button,
* disable autocomplete in unit fields

* TimeSpanPicker:
* store last field input and try to parse it only if needed
2025-04-14 09:03:41 +03:00
Atanas Korchev
bfa18f72fa Sanitize HTML content in RadzenMarkdown. Expose a property to disable html content (AllowHtml) and also provide means to provide a custom list of allowed HTML tags and attributes. 2025-04-13 15:58:20 +03:00
Vladimir Enchev
82c2ec0c43 Version updated 2025-04-11 10:00:14 +03:00
Pedro Constantino
3810d088b5 [FEAT] - Add Fill property to RadzenSeriesDataLabels for customizing text color, default behavior is preserved when Fill is not specified. (#2086)
Co-authored-by: Pedro Constantino <pedro.constantino@enerwatt.com.br>
2025-04-11 09:38:43 +03:00
yordanov
7b34b096fe Update premium themes 2025-04-11 08:47:20 +03:00
leon42
831b0bd2d1 Added a ShowInput property to RadzenDatePicker to allow only the button to be shown. See the demo for an example. (#2085)
Added demos for ShowInput and ShowDateBox options.

Co-authored-by: Noel <noel.s@ivoterguide.com>
2025-04-11 08:23:30 +03:00
Vladimir Enchev
5875057282 Fixed Tabs component re-rendered on every focus
Close #2087
2025-04-11 07:56:27 +03:00
Vladimir Enchev
b78df8df2a Fix Ctrl / Alt navigate in DropDownList
Fix #2084
2025-04-10 14:21:47 +03:00
Vladimir Enchev
7fa3d08e61 DataGrid expand/collapse column headers accessibility error fixed 2025-04-10 11:00:00 +03:00
Vladimir Enchev
549303a34c code improved 2025-04-10 09:50:19 +03:00
Vladimir Enchev
9d2cbae115 DropDownBase should not try to handle keypress when not bound 2025-04-09 18:57:55 +03:00
Vladimir Enchev
d1a76922c5 Version updated 2025-04-09 12:23:00 +03:00
yordanov
648889d2d2 Accordion header icon styles should not propagate accross other icons. Resolves #2081 2025-04-09 10:26:51 +03:00
Vladimir Enchev
984e566fe2 RadzenLink cannot be clicked in Popup
Fix #2083
2025-04-09 10:12:30 +03:00
Atanas Korchev
145296ee10 RadzenTheme no longer requires PersistentComponentState but uses it if available. 2025-04-09 10:03:21 +03:00
yordanov
91b91ca96f Add RealEstate app template 2025-04-09 09:46:11 +03:00
Atanas Korchev
5ea1e9d6d5 PagingSummaryFormat does not apply to the bottom pager in RadzenDataGrid. 2025-04-09 09:23:41 +03:00
Vladimir Enchev
78f83fe103 Version updated 2025-04-08 17:32:55 +03:00
Atanas Korchev
1b0ee6a757 Add specific upload examples. 2025-04-08 13:36:52 +03:00
Atanas Korchev
c185853405 Update the changelog to include 6.x changes. 2025-04-08 10:05:24 +03:00
Atanas Korchev
f50b8bceb6 Js minify (#2080)
* Minify the JavaScript.

* Update the terser package.
2025-04-08 09:32:06 +03:00
Atanas Korchev
559a10603a Update the innerHTML of the editor when source changes. 2025-04-08 07:58:48 +03:00
Atanas Korchev
defe38daaa Update the HTML content of RadzenHtmlEditor after running ValueChanged. 2025-04-07 16:54:46 +03:00
Vladimir Enchev
6acdaf0603 Version updated 2025-04-07 16:06:51 +03:00
Vladimir Enchev
e9991fc995 DialogService Alert() and Confirm() overloads with RenderFragment added 2025-04-07 14:55:22 +03:00
Vladimir Enchev
7ad14174d7 code fixed 2025-04-07 10:54:12 +03:00
Vladimir Enchev
a638387dd4 DataGrid FilterOperator changing to Contains on clear even when restricted
Fix #2074
2025-04-07 10:28:59 +03:00
Jeffrey van der Stad
3818d0e607 PR: Add PagingSummaryTemplate to RadzenDataGrid (Fixes [#2077](https://github.com/radzenhq/radzen-blazor/issues/2077)) (#2079)
* fix: added PagingSummaryTemplate as replacement for PagingSummaryFormat

* In `DataGridPagerApi.razor`, added a `PagingSummaryTemplate` within the `RadzenDataGrid` component to provide a visual summary of the current page and total records displayed.
2025-04-05 15:51:16 +03:00
Jeffrey van der Stad
3ce4f8da3a Updated unit tests in DialogServiceTests.cs to assert properties OkButtonText and CancelButtonText in ConfirmOptions and AlertOptions, with default values set to "Ok" and "Cancel". Modified DialogService.cs to initialize these properties if not specified. (#2063) 2025-03-30 10:48:45 +03:00
Vladimir Enchev
9d272a1b19 version updated 2025-03-29 16:48:58 +02:00
Atanas Korchev
3b9224b4da Parse images inside markdown links. Closes #2062. 2025-03-29 16:15:02 +02:00
Atanas Korchev
b254152746 Remove markup string (#2066)
* Remove MarkupString usage from the demos.

* Remove MarkupString from RadzenPanelMenu.

* Remove MarkupString from RadzenAccordion.

* Remove MarkupString from RadzenIcon

* Remove MarkupString from RadzenSplitButton

* Remove MarkupString from RadzenButton

* Add spaces in the keyboard navigation grid.

* Remove MarkupString from RadzenDialog

* Use literal strings for the icons in the Index page.

* Remove MarkupString from RadzenSelectbar

* Remove MarkupString from RadzenFieldset

* Remove MarkupString from everything else.
2025-03-29 12:30:41 +02:00
yordanov
a2d796476e Update premium themes 2025-03-28 15:25:46 +02:00
nielsNocore
898e744767 Fix small dot in rz-ripple on state :active (#2061) 2025-03-28 15:22:25 +02:00
Vladimir Enchev
9ef9c5b3de Numeric MaxLength property added 2025-03-28 14:25:11 +02:00
Vladimir Enchev
b734eeb252 Version updated 2025-03-28 07:39:29 +02:00
Vladimir Enchev
92d69d9053 DialogService Alert and Confirm buttons text missing when no options are specified
Fix #2060
2025-03-28 07:39:12 +02:00
Vladimir Enchev
4879c49476 Version updated 2025-03-26 17:10:50 +02:00
Vladimir Enchev
e81ea15bb0 DropDown select item with SPACE added
Closes #2011, #2054
2025-03-26 09:18:55 +02:00
Vladimir Enchev
647f174b53 Menu should be closed on location changed not toggled 2025-03-25 13:14:39 +02:00
Atanas Korchev
d79e6a7606 Escaped characters in Markdown tables display as a number. Fixes #2053. 2025-03-24 11:39:32 +02:00
Jeffrey van der Stad
3fd3916ef9 Enhance dialog options with property change notifications to support automatic UI updates (#2051)
* Enhance dialog options with property change notifications

* Update dialog properties and functionality

- Changed dialog text in `DialogPage.razor` to reflect new functionality.
- Updated button text in `DialogWithCascadingValueCaller.razor` and modified dialog title.
- Enhanced `DialogWithCascadingValueImplementation.razor` with new buttons for setting titles and toggling close options, and added methods for updating the dialog title and counter.

* Add unit tests and improve DialogService options handling

* Allow internal methods visibility for unit tests

Added an `ItemGroup` in the project file to include an
`InternalsVisibleTo` attribute for the `Radzen.Blazor.Tests`
assembly, enabling unit tests to access internal methods.
2025-03-24 08:10:57 +02:00
yordanov
b9b73d44c2 Fix titles and descriptions of UI Blocks demo pages 2025-03-21 15:01:28 +02:00
Vladimir Enchev
afa7c2030c demos update 2025-03-21 08:02:17 +02:00
Vladimir Enchev
f668a7a629 Version updated 2025-03-21 07:04:37 +02:00
Vladimir Enchev
958fb43ac2 Should not use Coalesce in OrderBy() 2025-03-21 07:04:17 +02:00
Jeffrey van der Stad
9ef8f592ba Add cascading value support to dialog components (#2046)
- Updated `DialogContainer.razor` to wrap the `Dialog` in a `CascadingValue`, enabling access to cascading parameters.
- Enhanced `DialogPage.razor` with explanatory text and a link to documentation regarding cascading values.
- Introduced `DialogWithCascadingValueCaller.razor` to provide a button for opening a dialog that uses cascading values.
- Created `DialogWithCascadingValueImplementation.razor` to implement dynamic dialog functionality with a counter that updates the title.
2025-03-21 07:01:14 +02:00
yordanov
e6feae6c68 Update premium themes 2025-03-20 17:00:43 +02:00
yordanov
9dc5810eaa Update TimeSpanPicker styles 2025-03-20 17:00:43 +02:00
Vladimir Enchev
c960d6d96a RadzenText demo description fixed 2025-03-20 14:42:44 +02:00
Nopke
45d95d7b45 New component: TimeSpanPicker (#2037)
* TimeSpanPicker: initial

* TimeSpanPicker: adjust material themes, handle long labels

* TimeSpanPicker: fix value set, move invoking Change events for consistency with other components, update demos

* TimeSpanPicker: fix preventKeyPress, adjust styles

* TimeSpanPicker: adjust demos and add new

* PopupOrInline: handle Inline parameter change

* TimeSpanPicker: change icon and improve handling Disabled/ReadMe parameters in panel

* TimeSpanPicker: update demos

* TimeSpanPicker: add to the example panel

* DatePicker: add a tag and info about time picker

* TimeSpanPicker: minor code cleanup, adjust styles, open popup on click if input not allowed

* * TimeSpanPicker: minor style and code adjustments
* DatePicker: add readonly class only if not disabled

* TimeSpanPicker: add to the index page

* TimeSpanPicker: adjust style code, use proper minus sign

* TimeSpanPicker:
* read input value without using JS
* fix Value and ConfirmedValue inconsistency

* TimeSpanPicker: always refresh the displayed value on input change

* TimeSpanPicker: add some tests (not finished yet)

* Numeric: fix culture-dependent test fail

* TimeSpanPicker: reorganize parameters

* TimeSpanPicker tests: cover input parameters, add regions

* TimeSpanPicker: tweak regions of input and panel parameters

* TimeSpanPicker tests: reorganize regions, use more specific selectors

* TimeSpanPicker: improve value change and popup toggle prevention

* TimeSpanPicker:
* use culture while parsing
* use consistent culture in tests

* FormField: add TimeSpanPicker in the demo

* TimeSpanPicker: more tests

* revert unrelated and unintended changed

* TimeSpanPicker test: move theory data to properties, add step tests

* TimeSpanPicker test: minor code cleanup, add remaining label tests

* TimeSpanPicker test: use dictionary of unit element selectors

* TimeSpanPicker test: create separate methods instead passing field expressions as theory, add more regions

* TimeSpanPicker: rename properties to match the convention and update their summaries

* TimeSpanPicker: remove UnconfirmedValueChanged param
TimeSpanPicker test: add event-related tests for the panel, simplify some tests related to timespan units

* TimeSpanPicker: pass culture to numeric fields, add panel field rendering tests

* TimeSpanPicker: unify unit fields under one RenderFragment function

* TimeSpanPicker: fix missing microseconds picker, fix classes of input fields

* TimeSpanPicker:
* prevent from changing UnconfirmedValue externally by changing Value,
* prevent from raising ValueChanged and Change events if the value haven't actually change

* revert unintended changes

* TimeSpanPicker, DatePicker: fix icon positions in FormFields having filled and flat variants

* TimeSpanPicker: make AllowClear false by default, like in DatePicker

* revert unintended change in demos project

* * remove PopupOrInline component
* revert changes in Popup component
* TimeSpanPicker: reimplement inline/popup handling
2025-03-20 10:37:43 +02:00
Vladimir Enchev
3d1c32a5b4 Version updated 2025-03-20 08:57:23 +02:00
Atanas Korchev
6a67580c33 Replace AutoLinkHeadings with AutoLinkHeadingDepth. 2025-03-20 08:49:36 +02:00
Vladimir Enchev
dbafa0a473 Should not use Coalesce in OrderBy() for non sub properties 2025-03-20 07:43:12 +02:00
Atanas Korchev
d348e73b55 Append html block elements as content during markdown rendering. 2025-03-19 19:06:43 +02:00
Atanas Korchev
3f3c1bd6e3 Add support for self-closed and void HTML elements in RadzenMarkdown. 2025-03-19 18:12:40 +02:00
Vladimir Enchev
1a3f907c62 DataGrid filtering by DateOnly and TimeOnly settings save/load fixed 2025-03-19 16:37:48 +02:00
Atanas Korchev
4f8027c6f7 Support URL fragments when matching the current URL. 2025-03-19 14:59:28 +02:00
Atanas Korchev
86cd2a976b Improve support for html tags inside RadzenMarkdown. 2025-03-19 11:51:41 +02:00
Vladimir Enchev
52a935bf09 RadzenSplitterPane class attribute not rendered 2025-03-19 11:01:58 +02:00
Atanas Korchev
ea7c3c4a5b RadzenMarkdown fails to parse image after strong node. 2025-03-19 09:15:12 +02:00
Atanas Korchev
9639d98dc3 Allow auto linking of markdown headers. 2025-03-19 08:09:04 +02:00
Vladimir Enchev
3bfc16b6a8 Version updated 2025-03-18 17:54:25 +02:00
Atanas Korchev
1e54619e81 Markdown table alignment support. 2025-03-18 17:46:31 +02:00
yordanov
fc4ac98246 Update demo pages 2025-03-18 17:40:36 +02:00
yordanov
534e3ee98f Card text styles should only affect text components that are placed directly inside RadzenCard 2025-03-18 17:40:10 +02:00
yordanov
9b8b8f020d Add App Templates 2025-03-18 16:49:27 +02:00
Atanas Korchev
aea7fb8069 Markdown (#2039)
* Add markdown parser and tests.

* Add demo.

* Add to home page.

* Add demo for nested blazor components.

* Use Radzen components for markdown rendering.
2025-03-18 16:29:32 +02:00
Vladimir Enchev
b933633cc0 code fixed 2025-03-18 15:15:38 +02:00
Vladimir Enchev
a822eb521d Version updated 2025-03-18 15:15:24 +02:00
Vladimir Enchev
b6bb19538f Fixed Popup IAsyncDisposable implementation caused errors 2025-03-18 15:14:59 +02:00
Vladimir Enchev
c0a1f86801 Version updated 2025-03-17 17:12:16 +02:00
yordanov
439d79c677 Fix Carousel scroll on touch devices 2025-03-17 16:51:38 +02:00
Vladimir Enchev
b6ee0f118e Menu should be closed on location change 2025-03-17 15:11:16 +02:00
Vladimir Enchev
ed037ca6d7 Popup IAsyncDisposable implemented 2025-03-17 13:40:35 +02:00
Vladimir Enchev
58f6239cb2 Version updated 2025-03-17 09:03:43 +02:00
Vladimir Enchev
5e7bfcb591 Accordion item Visible will not show the item if hidden 2025-03-17 07:47:09 +02:00
protoface
03cd99c43c Use RadzenDataGrid.EnumFilterTranslationFunc where applicable (#2036) 2025-03-17 07:35:48 +02:00
Vladimir Enchev
dc1742aca6 SideDialog ContentCssClass not applied 2025-03-17 07:33:53 +02:00
Atanas Korchev
a23142cc3f Scheduler navigation buttons submit containing form. Fixes #2035. 2025-03-15 08:37:27 +02:00
Vladimir Enchev
de47319b00 Version updated 2025-03-14 15:22:40 +02:00
Vladimir Enchev
c9a2549018 DatePicker ReadOnly should not allow selecting a day with keyboard
Fix #2028
2025-03-13 14:54:53 +02:00
Maks
966253f7b6 Enhanced ReloadSettings and LoadSettingsInternal methods with additional parameters and improved documentation (#2027)
- Added `forceReload` parameter to `ReloadSettings` method to allow forced reloading of settings.
- Added `forceUpdate` parameter to `LoadSettingsInternal` method to allow forced updates of settings.
- Updated XML comments for both methods to clarify their purpose, parameters, and behavior.

Co-authored-by: Sacred <Sacred>
2025-03-12 13:28:09 +02:00
Vladimir Enchev
b0ce7fb3cf DropDownDataGrid PopupStyle added 2025-03-11 15:59:03 +02:00
Vladimir Enchev
f1f85a6563 version updated 2025-03-11 13:59:56 +02:00
Vladimir Enchev
c10ee5e0a8 Avoid executing possible IQueryable code on DataGrid RowSelect 2025-03-11 13:59:39 +02:00
Joel Mandell
7e86d3128c (docs): Clarify that ShowHeader needs to be set to true if using NavigationTemplate. (#2026) 2025-03-11 13:29:30 +02:00
Frank
4f3da0ea2e Added SameSite and Secure options for theme cookie. (#2025)
* Added SameSite and Secure options for theme cookie.

* CookieThemeServiceOptionsSameSiteMode renamed to CookieSameSiteMode
2025-03-10 17:35:51 +02:00
Vladimir Enchev
406c7d8c6b Version updated 2025-03-10 10:36:01 +02:00
yordanov
809f1192f4 Update premium themes 2025-03-10 10:06:12 +02:00
Nopke
ff280d27f1 AutoComplete, Numeric: fix font family in inputs (#2022) 2025-03-10 09:37:25 +02:00
Ben Croughs
c566eb95a2 != null causing issues on KeyValuePart<string,int?> (#2021)
Co-authored-by: Ben Croughs <ben.croughs@telenet.be>
2025-03-10 07:49:19 +02:00
Vladimir Enchev
393d80600c OrderBy() by string selector improved to handle better sort strings discovery 2025-03-07 11:14:15 +02:00
Vladimir Enchev
1e44165d18 demo updated 2025-03-07 06:46:58 +02:00
Vladimir Enchev
03f4774810 version updated 2025-03-07 06:24:08 +02:00
Vladimir Enchev
b64e0446a3 DataGrid sorting of non dynamic data fixed 2025-03-07 06:23:48 +02:00
Vladimir Enchev
e51cab2418 version updated 2025-03-06 21:09:47 +02:00
Vladimir Enchev
f533d106c1 DataGrid dynamic data sort by property with space in the name fixed 2025-03-06 21:09:26 +02:00
Vladimir Enchev
2557691053 DataGrid dynamic data source fixed 2025-03-06 21:03:35 +02:00
Vladimir Enchev
5f53f95b5d Version updated 2025-03-06 15:47:04 +02:00
Vladimir Enchev
2c71574072 Revert "Fixed datagrid sort issues due to duplicate sortDescriptor lists. (#1996)"
This reverts commit 57f1417d4c.
2025-03-06 15:46:03 +02:00
Vladimir Enchev
45d38494f2 version updated 2025-03-06 10:32:31 +02:00
Vladimir Enchev
5c03d0d14c QueryableExtension.Select made internal 2025-03-06 10:30:58 +02:00
Vladimir Enchev
8404294f56 minor version raised 2025-03-06 09:14:33 +02:00
Vladimir Enchev
7f519bb71f Version updated 2025-03-06 09:13:06 +02:00
Vladimir Enchev
7a5995002d Select() by string element type discovery improved 2025-03-06 09:12:39 +02:00
Vladimir Enchev
ba8fe8e830 DataGrid SaveSettings() method made public
Fix #2016
2025-03-05 17:56:03 +02:00
Vladimir Enchev
949a5b19cc Popup focus first element made faster 2025-03-05 17:33:18 +02:00
yordanov
5a68a00f38 Optimize Material Symbols variable icon font 2025-03-05 17:06:23 +02:00
Vladimir Enchev
d52d91852a Select() by string will use first element type if source.ElementType is object 2025-03-05 16:18:08 +02:00
Vladimir Enchev
b8b39e1ebd Member access in GetNestedPropertyExpression() should support interfaces
Fix #2015
2025-03-05 13:57:51 +02:00
Vladimir Enchev
e795e63d02 Version updated 2025-03-04 13:31:31 +02:00
Vladimir Enchev
27dc58a90f Progress indicator for Duration of the Notification added (#2014)
* Notification ShowProgress added

* Style Notification with ProgressBar

---------

Co-authored-by: yordanov <vasil@yordanov.info>
2025-03-04 13:30:29 +02:00
Vladimir Enchev
d4679353af demo improved 2025-03-04 10:57:38 +02:00
Vladimir Enchev
73a53c8829 MyCustomDataFilterProperty and MyCustomEnumerableDataFilterProperty removed 2025-03-04 09:48:17 +02:00
Vladimir Enchev
eb51f78f8c Added DataFilter/DataGrid support for filtering enumerable properties with Contains operator and single value 2025-03-04 08:46:10 +02:00
Vladimir Enchev
8667443e64 RadzenDataFilterProperty FilterOperators property added similar to RadzenDataGridColumn 2025-03-03 17:20:20 +02:00
Vladimir Enchev
0650472551 code improved 2025-03-03 16:29:38 +02:00
Vladimir Enchev
7653ea683a Version updated 2025-03-03 16:28:20 +02:00
Vladimir Enchev
d633d2f424 Select() by string should support lambda expressions
Fix #2012
2025-03-03 16:23:08 +02:00
Vladimir Enchev
98ec370545 DataGrid column resize defaults to 0px width 2025-03-03 16:12:43 +02:00
Vladimir Enchev
51b9579d6e Demo update to allow only proper operators
Fix #2013
2025-03-03 16:06:33 +02:00
Vladimir Enchev
af42791fa2 Demo update to use proper operators when comparing collections 2025-03-03 16:00:18 +02:00
Atanas Korchev
f7e9a88575 RadzenStackedColumnSeries and RadzenStackedBar series support negative values. Closes #2001. 2025-03-01 15:45:09 +02:00
Vladimir Enchev
331ac4787e XML comment fixed 2025-03-01 12:20:52 +02:00
Vladimir Enchev
4ac2e0aa49 Version updated 2025-03-01 12:19:06 +02:00
Vladimir Enchev
0cb10c206a Where() method by string query cannot be translated error fixed 2025-03-01 12:18:38 +02:00
Atanas Korchev
5fd031f518 Moving appointments in month view resets their start and end time. Closes #2000. 2025-03-01 12:02:23 +02:00
Vladimir Enchev
48c204a7b0 Where() method by string simplified to avoid provider translation problems 2025-03-01 11:45:46 +02:00
Vladimir Enchev
e61fc1c84e Version updated 2025-03-01 11:10:53 +02:00
Vladimir Enchev
fb64381af9 Where() by string should handle null item 2025-03-01 11:03:07 +02:00
五味 凌一
84954f1919 Added “YearFormatter” property in RadzenDatePicker to allow custom formatting of Year (#2008)
* Added “YearFormatter” property to allow custom formatting of Year

This enhancement aims to enable immediate response to changes in the era name without relying on .NET’s built-in implementation.

* Update YearFormatter property initialization and usage

Changed the initial value of the YearFormatter property from null to the FormatYear method. Added a constructor to RadzenDatePicker where the YearFormatter property is set to the FormatYear method.

* Add xml comment.
2025-03-01 10:44:05 +02:00
Vladimir Enchev
cdabe516eb DialogService non generic open methods added
Fix #1987
2025-02-28 11:08:58 +02:00
yordanov
e5ddb2cef9 Update premium themes 2025-02-28 11:00:55 +02:00
Nopke
963185b927 FormField: fix css selectors for variants to avoid capturing variants of containers (#2002) 2025-02-28 10:58:06 +02:00
Vladimir Enchev
f7ef6a207e The ref parameter may be null in destroyChart()
Fix #1997
2025-02-27 15:52:13 +02:00
Vladimir Enchev
8088d14340 Added MaxWidth property for RadzenDataGridColumn
Fix #1993
2025-02-27 15:44:58 +02:00
Atanas Korchev
f710b782a3 RadzenDatePicker supports custom year formatting via the YearFormat property. 2025-02-27 13:48:58 +02:00
Vladimir Enchev
b13921f9aa demo improved 2025-02-26 17:16:52 +02:00
Vladimir Enchev
522191052a Tree filter demo added
Fix #1948
2025-02-26 16:20:22 +02:00
yordanov
e9e8844342 Add new UI Blocks to the online demos 2025-02-26 15:18:43 +02:00
Vladimir Enchev
ccbf7b24cf Version updated 2025-02-26 09:17:56 +02:00
nielsNocore
57f1417d4c Fixed datagrid sort issues due to duplicate sortDescriptor lists. (#1996)
* refactor datagrid sorting. to only have one ObservableCollection<SortDescriptor instead of 2

* Revert "refactor datagrid sorting. to only have one ObservableCollection<SortDescriptor instead of 2"

This reverts commit 02ef67073c.

* added sort changes without formatting

* added new unit test.

* added datagrid test with load data args.
2025-02-26 09:15:42 +02:00
Atanas Korchev
d5318e6e88 Scheduler does not show some appointments. Fixes #1995. 2025-02-26 08:51:43 +02:00
Vladimir Enchev
978e3fc610 version updated 2025-02-25 10:42:59 +02:00
Vladimir Enchev
dcb5eef814 DropDown/DropDownDataGrid case-insensitive filter cannot be translated by PG SQL provider 2025-02-25 10:42:30 +02:00
Atanas Korchev
518ad838e7 Add Select extension method for IQueryable. 2025-02-24 17:42:33 +02:00
Vladimir Enchev
ba6ced577e minor version updated 2025-02-24 16:22:37 +02:00
Vladimir Enchev
138253e728 Version updated 2025-02-24 16:21:02 +02:00
yordanov
ffd299962b Fix alternating rows color in Fluent themes 2025-02-24 16:16:52 +02:00
Vladimir Enchev
354a147155 GetBodyColumnClass and GetHeaderColumnClass renamed and made internal 2025-02-24 16:00:04 +02:00
Pedro Constantino
a623017325 [IMPROVEMENT] - Adding HeaderWhiteSpaceText and WhiteSpaceText properties to RadzenDataGridColumn. (#1999)
* [IMPROVEMENT] - Adding HeaderWhiteSpaceText and WhiteSpaceText properties to RadzenDataGridColumn.

* [IMPROVEMENT] - Improving the css and readjusting the themes folder.

* [IMPROVEMENT] - Adjusting enumerator documentation.

* [IMPROVEMENT] - Adjusting component documentation

* [IMPROVMENT] - Renaming WhiteSpace and HeaderWhiteSpace properties, renaming WhiteSpace enumerator and removing identation from csproj.

---------

Co-authored-by: Pedro Constantino <pedro.constantino@enerwatt.com.br>
2025-02-24 15:54:27 +02:00
Vladimir Enchev
654bd80abd missing cast added 2025-02-22 12:29:20 +02:00
Vladimir Enchev
3249591351 EnumerableAsString() will handle single values 2025-02-22 11:41:01 +02:00
Vladimir Enchev
40f934d7a6 version updated 2025-02-21 20:07:25 +02:00
Vladimir Enchev
53717dcc46 DataGrid CheckBoxList filter list cast exception fixed
Fix #1998
2025-02-21 20:06:59 +02:00
Vladimir Enchev
f16a00fe2e Fixed exception with DataGrid sorting and property name equal to System Type name
Obsolete code related to Dynamic LINQ deleted
2025-02-21 12:55:18 +02:00
Vladimir Enchev
ab1af0ce28 Version updated 2025-02-21 08:37:58 +02:00
Vladimir Enchev
be444bbbc4 ToFilterString() should export Boolean arrays as valid C# 2025-02-21 08:37:33 +02:00
Vladimir Enchev
e161872604 Fixed Tree is breaking after collapse
Fix ##1983
2025-02-20 18:27:34 +02:00
Vladimir Enchev
e21fa015bf version updated 2025-02-20 12:19:46 +02:00
Vladimir Enchev
fb3275d89f Fixed OrderBy() with complex lambdas 2025-02-20 12:18:05 +02:00
Monsieurvor
f42e4ffc71 fix linear scale step (#1989) 2025-02-20 11:24:39 +02:00
Vladimir Enchev
7b15c190d3 Revert "Fix OnSideClose being called on open (#1977)"
This reverts commit 75da4667b7.
2025-02-20 11:12:05 +02:00
Vladimir Enchev
73c2d27620 Saved DataGrid filter with CheckBoxList filter type will raise exception on settings load 2025-02-20 11:00:53 +02:00
nielsNocore
288db125ce added GetSelectedSources and GetSelectedTargets in the picklist to get wich items are selected. Or to get if any item is selected. (#1982) 2025-02-20 05:01:52 +02:00
Victor Ureta
0effaae435 Update RadzenDropDownDataGrid.razor.cs (#1985) 2025-02-20 05:00:34 +02:00
Vladimir Enchev
a71f1dd3c6 Version updated 2025-02-19 18:42:31 +02:00
Vladimir Enchev
c08843d587 Revert "Update RadzenDatePicker.razor.cs (#1980)"
This reverts commit b16f95a4ba.
2025-02-19 18:42:09 +02:00
Vladimir Enchev
44094cd4f4 comments fixed 2025-02-19 18:09:44 +02:00
Vladimir Enchev
a4bd9d518c Version updated 2025-02-19 17:58:41 +02:00
Vladimir Enchev
a739a6e24a Generic OrderBy<T>() method by string selector fixed to support lambda 2025-02-19 17:58:20 +02:00
Vladimir Enchev
955b52d54b duplicate test removed 2025-02-19 15:25:48 +02:00
Atanas Korchev
004293008c ExpressionParser supports typed arrays. 2025-02-19 15:23:28 +02:00
Vladimir Enchev
9f26a0b512 Should_SupportNullableCollection test added 2025-02-19 15:07:39 +02:00
CreateCode
b16f95a4ba Update RadzenDatePicker.razor.cs (#1980)
In some cultures, such as Portuguese (Portugal), the name of the day of the week appears in full, overlapping one another. This change forces the abbreviation of the name of the day of the week.
2025-02-19 15:03:41 +02:00
Vladimir Enchev
c079531d2e Fixed DataGrid CheckBoxFilter values not sorted 2025-02-19 15:00:24 +02:00
Atanas Korchev
773f2dc074 ExpressionParser supports Enumerable extension methods with IEnumerable parameters. 2025-02-19 11:35:56 +02:00
Vladimir Enchev
64d783179b Should_SupportNestedLambdasWithComplexMethod test added 2025-02-19 10:48:58 +02:00
Vladimir Enchev
3dafd6c277 Version updated 2025-02-19 09:34:05 +02:00
Vladimir Enchev
fb2fdb10b2 OrderBy() with string lambda support fixed 2025-02-19 09:33:49 +02:00
Vladimir Enchev
50dedf84d5 Where() parameters conversion between string and actual type fixed 2025-02-19 08:56:30 +02:00
Vladimir Enchev
d7b96a7dca Where() with Guid parameter fixed 2025-02-19 08:04:43 +02:00
Vladimir Enchev
1d1acdf7c8 Select improved 2025-02-18 23:14:12 +02:00
Vladimir Enchev
440bc76f08 Version updated 2025-02-18 23:10:49 +02:00
Vladimir Enchev
d2a598dbf5 Fixed DataGrid sub properties invalid expressions 2025-02-18 23:10:17 +02:00
Atanas Korchev
931f9dab6f ExpressionParser supports nested property name initializers. 2025-02-18 20:39:29 +02:00
Atanas Korchev
10ec2af398 ExpressionParser supports conditional expressions with different type. 2025-02-18 20:11:13 +02:00
Atanas Korchev
46382ef89f ExpressionParser supports DateTimeOffset.Parse. 2025-02-18 19:57:10 +02:00
Atanas Korchev
c4116feda4 Expression parsing supports the ?? operator. 2025-02-18 19:42:05 +02:00
Vladimir Enchev
4c18342cf4 Version updated 2025-02-18 17:45:21 +02:00
Atanas Korchev
92f103c1dd Support nested conditional access. 2025-02-18 17:19:02 +02:00
Vladimir Enchev
8c9374e00a Version updated 2025-02-18 11:36:53 +02:00
Vladimir Enchev
870f3d2ef9 Select expression should not create resulting type with dot in the property name 2025-02-18 11:34:51 +02:00
Vladimir Enchev
d75b3596aa ToFilterString() should convert enumerable first 2025-02-18 10:38:52 +02:00
Vladimir Enchev
c388d84f57 Version updated 2025-02-18 09:57:45 +02:00
Vladimir Enchev
782f6c9655 DataGrid FilterProperty should be used instead Property only if Property is not enumerable 2025-02-18 09:56:20 +02:00
Vladimir Enchev
078d12f2a1 DataGrid Guid column type with ToFilterStrng() support added 2025-02-18 09:42:33 +02:00
Vladimir Enchev
271e1aa26a DataGrid TimeOnly column type with ToFilterStrng() support added 2025-02-18 09:34:01 +02:00
Vladimir Enchev
c9c11c7ff7 Version updated 2025-02-18 07:51:22 +02:00
Caleb Weeks
75da4667b7 Fix OnSideClose being called on open (#1977)
Co-authored-by: Caleb Weeks <seth.weeks@carrier.com>
2025-02-18 07:50:37 +02:00
Vladimir Enchev
a2591f7f77 DataGrid FilterProperty should be used instead Property if defined 2025-02-17 19:38:13 +02:00
Vladimir Enchev
72b4e8bd39 Fixed DataGrid filtering on nullable string column will throw ReferenceNullException
Fix #1975
2025-02-17 19:05:06 +02:00
Vladimir Enchev
740b0bc3b1 Version updated 2025-02-17 16:58:30 +02:00
Vladimir Enchev
3e48b15db0 RadzenDataGridColumn FilterOperator="FilterOperator.Equals" in case of Type="typeof(string)"
Fix #1974
2025-02-17 16:56:36 +02:00
Vladimir Enchev
f1b8a22cc8 Fixed DataGrid CheckBox filtering with dynamic data 2025-02-17 16:36:03 +02:00
Pedro Constantino
02b75fcb68 [IMPROVEMENT] - Adding new option to disable radzen link, css and test added. (#1970)
* [IMPROVEMENT] - Adding new option to disable radzen link, css and test added.

* [IMPROVEMENT] - Leaving the title with lowercase letter.

* [IMPROVEMENT] - Removing version items.

---------

Co-authored-by: Pedro Constantino <pedro.constantino@enerwatt.com.br>
2025-02-17 15:10:06 +02:00
Vladimir Enchev
9b2541975f comment fixed 2025-02-17 14:38:29 +02:00
Vladimir Enchev
d3ff9a5b7c Version updated 2025-02-17 13:33:05 +02:00
Atanas Korchev
75acf7d132 Support prefix ! operator in expressions. 2025-02-17 13:27:59 +02:00
Vladimir Enchev
d6a9430c20 PrefixUnaryExpressionSyntax test added 2025-02-17 13:22:14 +02:00
Vladimir Enchev
5a89720f59 DropDown filtering by non string property fixed 2025-02-17 13:16:14 +02:00
Vladimir Enchev
bee7133e81 Fixed exception with DropDown filtering by non strong property 2025-02-17 13:01:28 +02:00
Vladimir Enchev
8522f88d66 Fixed Dropdown Filter Not Working When Binding List to Struct Class
Fix #1973
2025-02-17 12:56:57 +02:00
Vladimir Enchev
10ecc5c75d Fixed RadzenDataGrid in simple filter mode shows the date filter value at the bottom of the screen
Fix #1971
2025-02-17 12:24:43 +02:00
Atanas Korchev
cdd722c975 Refactor the ExpressionParser. 2025-02-17 11:56:01 +02:00
Vladimir Enchev
7fd9b258aa InnerException added as well 2025-02-17 11:15:20 +02:00
Vladimir Enchev
5368d398fe Where() and Select() entire exception exposed 2025-02-17 11:14:00 +02:00
Vladimir Enchev
30cc8c8711 missing comments added 2025-02-17 10:49:50 +02:00
Vladimir Enchev
f7d1fea2af Version updated 2025-02-17 10:45:30 +02:00
Vladimir Enchev
ee5674bb6d Where() and Select() methods from strings expression parsing improved (#1972)
* Add ExpressionParser and tests.

* Should_SupportNullableShortParsing test added

* Support conversion for binary operations

* Should_SupportNullablePropertiesWithArray test added

* Should_SupportDateTimeWithArray added

* code fixed

* Compilation moved to Select() only

* DataGrid columns filtering temporary switched to string expressions

* typeLocator added

* Convert arguments if needed.

* Should_SupportNestedLambdasWithEnums added

* locator improved for nested types

* ToFilterString() will not cast enums

* expression fixed

* Revert "demo reworked without strings"

This reverts commit 5e1fa61c55.

* ToFilterString() improved

* Support projections.

* ExpressionParser.ParseProjection added

* code improved

* Select by string.

* Support conditional access expressions.

* null condition added

* should add item instance name only to non indexer properties

* Array and dictionary access.

* Add editorconfig.

* Dynamic property еxpression updated to cast

* ToFilterString() removed

* Where() and Select() exception handling improved

---------

Co-authored-by: Atanas Korchev <akorchev@gmail.com>
2025-02-17 10:42:58 +02:00
Vladimir Enchev
5e1fa61c55 demo reworked without strings 2025-02-15 18:34:36 +02:00
Vladimir Enchev
92f968f933 obsolete code deleted 2025-02-15 11:07:53 +02:00
Vladimir Enchev
9eabd75864 Fixed other items not collapsed with Tree SingleExpand=true 2025-02-15 11:02:17 +02:00
Vladimir Enchev
df121e68b4 OrderBy() should return IOrderedQueryable<T> 2025-02-14 19:01:30 +02:00
Vladimir Enchev
be0721fa5d version updated 2025-02-14 18:33:36 +02:00
Vladimir Enchev
d670872d73 ToFIlterString() should output bool with proper casing 2025-02-14 18:20:40 +02:00
Vladimir Enchev
68eb9162a9 Fixed DataGrid Custom Column Filter Error With FilterCaseSensitivity="FilterCaseSensitivity.CaseInsensitive"
Fix #1969
2025-02-14 17:58:04 +02:00
Vladimir Enchev
a65ce23a10 version updated 2025-02-14 16:04:31 +02:00
Vladimir Enchev
bea9bca891 Fixed DataGrid filtering by Contains() using second filter with or 2025-02-14 16:03:31 +02:00
Vladimir Enchev
9f2c6fe8cc Fixed Empty DataGrid with FilterOperator="FilterOperator.In" and Type="typeof(IEnumerable<Enum>)">
Fix #1968
2025-02-14 15:58:06 +02:00
Vladimir Enchev
07e4276190 Accordion Refresh() method made public. 2025-02-14 15:24:41 +02:00
Vladimir Enchev
3db15c168d Version updated 2025-02-14 14:51:36 +02:00
Vladimir Enchev
7e9f66ec61 Fixed exception with filtering by string columns with null values 2025-02-14 14:51:09 +02:00
Vladimir Enchev
c7ce4ec4e3 Fixed DataGrid filtering with CustomFilterExpression column expression 2025-02-14 14:38:12 +02:00
Vladimir Enchev
ad32aed204 Fixed DataGrid grouping broken for structs
Fix #1967
2025-02-14 13:08:23 +02:00
Nopke
2df9235516 fix a test that fails or succeeds depending on the user's culture (#1963) 2025-02-14 12:09:31 +02:00
Vladimir Enchev
a0efb0b9a4 Select() should handle nested types 2025-02-14 11:38:12 +02:00
Vladimir Enchev
a244741640 version updated 2025-02-14 11:26:13 +02:00
Vladimir Enchev
e3f5360a7f ToFilterString() should not use in operator 2025-02-14 11:25:51 +02:00
Vladimir Enchev
c280bae14f ToFilterString() should cast enum value to enum type 2025-02-14 11:11:35 +02:00
Vladimir Enchev
e99671ba81 Where() should handle nested types 2025-02-14 10:49:33 +02:00
Vladimir Enchev
73338462e5 Where() should handle bools and old single = expressions 2025-02-14 10:36:12 +02:00
Vladimir Enchev
1912e69375 OrderBy() variable reference ignored if present 2025-02-14 10:28:35 +02:00
Vladimir Enchev
60a3789e9c DateTime, DateTimeOffset, DateOnly and Guid filtering by string fixed 2025-02-14 09:53:37 +02:00
Vladimir Enchev
a89bc5a5ce version updated 2025-02-14 07:16:30 +02:00
Vladimir Enchev
08f3126f46 Fixed DataGrid "Translation of method 'string.ToLowerInvariant' failed
Fix #1964
2025-02-14 07:16:14 +02:00
Vladimir Enchev
53e746146b DartSassBuilder PrivateAssets="All" added 2025-02-13 16:56:02 +02:00
Vladimir Enchev
1e7cc0d655 Version updated 2025-02-13 14:57:11 +02:00
Vladimir Enchev
b37a81b297 DataGrid filtering null reference exception fixed in some cases 2025-02-13 14:53:45 +02:00
Vladimir Enchev
6aec8118f2 DataGrid sort by dynamic type fxed 2025-02-13 14:33:53 +02:00
Vladimir Enchev
756732803f Array and List<> member access fixed 2025-02-13 14:28:08 +02:00
Vladimir Enchev
a6b8abb9ce version updated 2025-02-13 13:39:04 +02:00
Vladimir Enchev
38feb54237 Various components reworked without dynamic LINQ (#1960) 2025-02-13 13:35:41 +02:00
Vladimir Enchev
ee828de086 version updated 2025-02-12 18:05:26 +02:00
Vladimir Enchev
bc82638fea DataGrid ReloadSettings() method added 2025-02-12 18:04:20 +02:00
Lynkle
edb6f58f66 Allow AutoComplete with OpenOnFocus to show items even without user input (#1957)
* fix(autocomplete): OpenOnFocus now lets you view items in the dropdown even if you have not provided any searchText. This is for the case where you want the autocomplete but the user does/may not know what it is they want to complete.

* fix(autocomplete): Adjusted it so that removing search text back to null/empty string will reset autocomplete suggestions.
2025-02-11 18:19:59 +02:00
nielsNocore
23b9a6e7bf Fix IsAllSelectedInDropdown is correct when disabled items exists (#1953)
added unit tests for it.
2025-02-10 12:03:52 +02:00
Vladimir Enchev
0b3c6058e2 Fixed Tree recursion error during expand with SingleExpand=true 2025-02-07 14:47:12 +02:00
yordanov
cb6572980e Add demo video for Radzen Blazor for Visual Studio 2025-02-06 11:18:11 +02:00
Vladimir Enchev
78e5bbb9dc version updated 2025-02-06 10:58:16 +02:00
Vladimir Enchev
12b52b3e79 ShowVideoDialog updated 2025-02-06 10:57:41 +02:00
yordanov
e226749388 Add input width: 100%; for rz-helper-hidden-accessible class 2025-02-06 10:47:44 +02:00
yordanov
001cd0cdcd Remove input width: 0; for rz-helper-hidden-accessible class as it breaks default DropDown width 2025-02-06 10:00:52 +02:00
Vladimir Enchev
c3806348a0 Fixed FileInput breaks if both MaxWidth and MaxHeight is set and a non image is selected
Fix #1922
2025-02-06 09:28:56 +02:00
nielsNocore
c6a8d80d45 add DisabledProperty to radzenPickList (#1946)
* add DisabledProperty to radzenPickList

* moved picklist icons to be properties, to be able to custimze the icons in the picklist
2025-02-05 17:23:29 +02:00
nielsNocore
2babacd15a moved picklist icons to be properties, to be able to custimze the icons in the picklist (#1947) 2025-02-05 17:22:51 +02:00
nielsNocore
456ab29a34 added parameter to set "AllowSelectAll" in de radzenPicklist (#1945)
* added parameter to set "AllowSelectAll" in de radzenPicklist

* added default value to radzenPickList.AllowSelectAll to be true
2025-02-05 15:00:25 +02:00
Vladimir Enchev
1de201841a DataGrid CheckBoxList filter mode with EF Core data source crashes application when using keyboard
Fix #1943
2025-02-05 09:14:36 +02:00
yordanov
a5586fd4ea Add demo of RadzenIcon using FontAwesome icons 2025-02-04 17:30:01 +02:00
Vladimir Enchev
a14ac78957 Dynamic and version updated 2025-02-03 14:36:04 +02:00
yordanov
1193ede1ca Update FormField demos 2025-02-03 14:23:47 +02:00
yordanov
8ad75a1773 Update premium themes 2025-02-03 13:58:41 +02:00
rklfss
9ea1b44e64 RadzenDatePicker floating label and RadzenFormField support (#1933)
* Added support to use RadzenDatePicker in RadzenFormField

- added rz-state-empty css class to RadzenDatePicker if there is no value
- added css to handle floating labels for any form field component within RadzenFormField

* RadzenDatePicker minor code fixes and improvements

* RadzenDatePicker Demo show time part
2025-02-03 13:39:40 +02:00
Josh
b92ef7922d Add Notify overload that accepts a Timespan for duration, for improved clarity (#1936) 2025-02-03 13:20:26 +02:00
Vasil Yordanov
3d6eff639f Unify styles and behavior of forms components when invalid css class is present (#1938) 2025-02-03 10:25:13 +02:00
Atanas Korchev
011e761d7f RadzenTheme could throw a null reference exception during dispose in rare cases. 2025-02-03 09:31:52 +02:00
Atanas Korchev
a2fdb687a1 Setting the Value of RadzenHtmlEditorBackground makes it impossible to pick a color. 2025-01-31 17:21:53 +02:00
jamesalainheffer
ff846e0cc1 Added a parameter called "Size" to the "RadzenGravatar" component. (#1932)
* Added a parameter called "Size" to the "RadzenGravatar" component. This will allow for users to adjust the size of the gravatar image coming in, so that they are not stuck with just a 32px image.

* Corrected the default value from 32 to 36, and remove the width variable in favor of the parametised Size variable. (As per suggestion from akorchev - thanks)

* Corrected a typo where the "value" attribute was inside the summary, it is now outside, where it should be.
2025-01-31 09:57:22 +02:00
Vladimir Enchev
df0ad0d9f1 DropDownDataGrid item not selected after change outside of the component. 2025-01-30 16:20:35 +02:00
Vladimir Enchev
716d1a6cba Version updated 2025-01-29 08:58:01 +02:00
Frank
3e7468177d Added ReadOnly parameter for RadzenSwitch component (#1927)
* Added ReadOnly parameter for RadzenSwitch component

* Formatting
2025-01-29 08:57:29 +02:00
Vladimir Enchev
d4113e6715 Dynamic LINQ ParsingConfig initialization moved to RadzenComponent 2025-01-29 08:56:35 +02:00
Vladimir Enchev
7f7ce06d0e Version updated 2025-01-28 06:51:39 +02:00
nielsNocore
7cfea596fd fixed InvokeAsync(Reload); not awaited in datagrid en pagedDataBoundComponent (#1926) 2025-01-28 06:49:29 +02:00
Vladimir Enchev
7eae5d0f6e DataGrid sorting with dynamic data fixed 2025-01-28 06:48:29 +02:00
Vladimir Enchev
a390658ad9 DynamicLinqCustomTypeProvider RestrictOrderByToPropertyOrField set to false 2025-01-27 18:20:03 +02:00
Vladimir Enchev
ecc403cbbc Dynamic LINQ settings improved 2025-01-27 15:59:15 +02:00
Paul Ruston
e870ca856c Add DaySelect event to Day, Week and Month Views (#1910)
* Add DaySelect event to Day, Week and Month Views

* Resolution of comments

* Resolve incorrect code example. Also anomolies in Month example

* Changed AppointmentsInSlot call as per comment
2025-01-27 10:12:27 +02:00
Vladimir Enchev
e7b8fec063 version updated 2025-01-27 08:02:07 +02:00
Vladimir Enchev
7767878c4c System.Linq.Dynamic.Core updated 2025-01-27 07:54:17 +02:00
Vladimir Enchev
63de20fe36 DropDownBase multiple selection fixed 2025-01-26 19:55:06 +02:00
Vladimir Enchev
6114a9a8ed version updated 2025-01-26 15:37:56 +02:00
Vladimir Enchev
d5514ca0cd Dynamic LINQ AllowEqualsAndToStringMethodsOnObject set to true by default 2025-01-26 15:37:38 +02:00
Vladimir Enchev
8cf0565211 System.Linq.Dynamic.Core updated to latest preview 2025-01-26 15:14:10 +02:00
Vladimir Enchev
32246b1d69 code fixed 2025-01-26 15:06:31 +02:00
Vladimir Enchev
418dbf09ec System.Linq.Dynamic.Core updated 2025-01-24 22:45:47 +02:00
Vladimir Enchev
a198d09b71 System.Linq.Dynamic.Core updated to preview 2025-01-24 13:53:00 +02:00
yordanov
f3bb0e7b90 Timeline point icon size should not impact ChildContent icon size. Resolves #1919 2025-01-24 11:24:40 +02:00
Vladimir Enchev
b3917e19a2 Avoid using ToString() and Equals() methods with Dynamic LINQ 2025-01-24 11:09:18 +02:00
yordanov
e7d8b7454f Update Material theme secondary color value to meet WCAG AA contrast ratio criteria. Resolves #1923 2025-01-24 10:54:57 +02:00
yordanov
4d4660eed9 Update Material Symbols fonts 2025-01-23 13:53:39 +02:00
Vladimir Enchev
b80e47672d Version updated 2025-01-23 10:54:45 +02:00
Vladimir Enchev
3b370841cc System.Linq.Dynamic.Core updated 2025-01-23 10:43:02 +02:00
Atanas Korchev
7ec2a9a0a5 Update table demo descriptions. 2025-01-23 10:39:05 +02:00
Vladimir Enchev
e340a376ef code updated 2025-01-23 10:35:10 +02:00
Vladimir Enchev
a2709afc5c text fixed 2025-01-23 10:25:58 +02:00
Vladimir Enchev
9c7ed95f23 Table demos descriptions added 2025-01-23 10:21:59 +02:00
Vladimir Enchev
524f1f99cb missing comment added 2025-01-23 10:11:20 +02:00
yordanov
2ac6d7f2bb Add Table component to the demos homepage and Data section in main nav 2025-01-23 09:43:18 +02:00
Vladimir Enchev
6b3fd9efae Table with merged cells demo added 2025-01-23 09:40:19 +02:00
Vladimir Enchev
d99daa6538 demo updated 2025-01-23 09:27:41 +02:00
Vladimir Enchev
13e0bba379 Table demos reworked 2025-01-23 09:25:53 +02:00
Vladimir Enchev
ed7c5bc537 various Table fixes 2025-01-23 09:04:38 +02:00
Josh
03b7968b99 Expose Visible and IFormFieldContext on IRadzenFormComponent (#1920) 2025-01-23 08:55:32 +02:00
Vladimir Enchev
274d64246b Fixed DataGrid Enum Column Filter with Filtermode CheckBoxList not working
Fix #1918
2025-01-22 19:15:59 +02:00
Vladimir Enchev
4450053fd3 CustomText property added to localize DataGrid and DataFilter Custom filter operator 2025-01-22 19:01:07 +02:00
Vladimir Enchev
8c321f18e1 demos keyboard navigation details reworked with RadzenTable 2025-01-22 10:26:38 +02:00
Vladimir Enchev
e015807edc method name improved 2025-01-22 10:17:03 +02:00
Vladimir Enchev
4ebcd2f214 RadzenTable improved 2025-01-22 10:15:21 +02:00
Vladimir Enchev
67cd8b7a61 Demos keyboard support updated with RadzenTable 2025-01-21 17:55:48 +02:00
Vladimir Enchev
0a802ca73b RadzenTableHeader, RadzenTableHeaderRow and RadzenTableBody added 2025-01-21 15:31:18 +02:00
Vladimir Enchev
097f37bfbc Table GridLines and AllowAlternatingRows added 2025-01-21 15:12:38 +02:00
Vladimir Enchev
524e42980a RadzenTable component added 2025-01-21 11:09:08 +02:00
Vladimir Enchev
34eebc9406 version updated 2025-01-20 17:49:41 +02:00
Atanas Korchev
65f20c232c Linking to an anchor does not scroll to the anchor. 2025-01-20 17:46:25 +02:00
Andrey Dmitrienko
d742fdae86 Text shifting fix for RadzenDropDown (#1915)
* Text shifting fix for RadzenDropDown
- Add an input width: 0; configuration for rz-helper-hidden-accessible class

---------

Co-authored-by: Andrey Dmitrienko <andrey.dmitrienko@flexbricks.com>
2025-01-20 11:02:04 +02:00
Vladimir Enchev
397e2baf6c Fixed RadzenAutoComplete Value is not displayed in the input field when using Value and Change event
Fix #1914
2025-01-20 09:39:54 +02:00
Vladimir Enchev
4b1d951083 Version updated 2025-01-17 22:05:24 +02:00
ivan-rosales-rieloff
ab65a5a975 Add empty string support, culture based cast (#1912)
* add is valid decimal value validation  on ConvertToDecimal to avoid errors when decimal format is invalid, ie. double comma

* Support culture to convert strings, add support to empty string as zero value

* Culture specific number conversion test

* Add Specific culture, and default cuture numeric test

---------

Co-authored-by: Ivan Rosales <kanibal68@hotmail.com>
2025-01-17 22:04:45 +02:00
Vladimir Enchev
9947cbf47b RadzenDropDown with filtering on Android closes on open
Fix #1913
2025-01-17 10:10:09 +02:00
Vladimir Enchev
f781ba0c6a Version updated 2025-01-16 12:25:27 +02:00
Vladimir Enchev
e3c605a7a9 Version updated 2025-01-16 12:23:51 +02:00
Vladimir Enchev
849e6761b8 Revert "add is valid decimal value validation on ConvertToDecimal to avoid errors when decimal format is invalid, ie. double comma (#1911)"
This reverts commit fef5ceb36d.
2025-01-16 12:21:27 +02:00
Vladimir Enchev
407ef36b70 Version updaed 2025-01-16 11:26:33 +02:00
ivan-rosales-rieloff
fef5ceb36d add is valid decimal value validation on ConvertToDecimal to avoid errors when decimal format is invalid, ie. double comma (#1911)
Co-authored-by: Ivan Rosales <kanibal68@hotmail.com>
2025-01-16 11:23:37 +02:00
Atanas Korchev
2e22f556d8 Update DartSassBuilder. 2025-01-16 11:15:32 +02:00
Atanas Korchev
95b833402f Exception is thrown when all series values are 0 in certain value axis configuration. 2025-01-16 08:53:37 +02:00
Vladimir Enchev
c0e7418e7c RadzenAutoComplete SelectedItem property added 2025-01-15 19:52:03 +02:00
Vladimir Enchev
4d72ef1efe comment fixed 2025-01-15 16:04:58 +02:00
Vladimir Enchev
a00bce399f DialogService OpenSide() method added 2025-01-15 16:03:17 +02:00
yordanov
2b8658b233 Add info block for Radzen Blazor for Visual Studio 2025-01-15 15:31:34 +02:00
Vladimir Enchev
fc2784450b version updated 2025-01-14 17:11:52 +02:00
Vladimir Enchev
896d9bd3ae various warnings fixed 2025-01-14 17:11:42 +02:00
yordanov
9199096f69 Fix RadzenDatePicker input padding when trigger button is hidden 2025-01-14 11:44:45 +02:00
yordanov
bdb2694734 Make RadzenRating hover color more prominent and add focus outlines 2025-01-14 10:49:34 +02:00
Vladimir Enchev
98ab3cd3d0 Accordion dynamic items demo added 2025-01-14 10:33:43 +02:00
Vladimir Enchev
22f7d3f9f4 Accordion item Selected logic improved 2025-01-14 09:21:52 +02:00
Nopke
7f27dafe32 rating: (#1909)
* make stars filled when they're selected
* update hover styles to make them different from selected styles and similar to focus styles
2025-01-14 08:58:27 +02:00
Vladimir Enchev
37a1e6d4b5 Version updated 2025-01-13 15:05:37 +02:00
Pierluigi Mari
91d5473bf2 Bug fix present in RadzenDropDownDataGrid from version 5.7.0 (#1907)
When RadzenDropDownDataGrid is set to allow multi-selection and virtualization with LoadData, it doesn't keep all items selected as you scroll through the list. Optimized the initialization of selectedItems in DropDownBase, so that selectedItems is reinitialized only if empty, thus preserving existing items.

Co-authored-by: Pierluigi.Mari <pierluigi.mari@iqera.it>
2025-01-13 15:02:21 +02:00
yordanov
b883cccb30 Update premium themes 2025-01-13 14:58:14 +02:00
Nopke
2ca7b3ba5f Select bar orientation parameter (#1905)
Select bar:
* add 'orientation' param
* update styles
* reimplement item border duplication prevention (instead of negative margins just remove borders)
* add 'orientation' param example
* add 'updated' annotation
* add whitespace in .razor file to make it more comprehensible
2025-01-13 14:51:27 +02:00
Josh
faada7ae7b adds Disabled, from RadzenFormComponent<T>, to the IRadzenFormComponent interface, for better integration with cross-cutting form behavior (#1903) 2025-01-13 10:52:48 +02:00
Vladimir Enchev
3910fb778f All popups will be closed on window resize 2025-01-13 10:46:26 +02:00
Vladimir Enchev
4577d063cc Fixed Accordion cannot be collapsed using Selected property of the item 2025-01-13 10:37:50 +02:00
Vladimir Enchev
1f5c70166e Fixed RadzenDataFilter.ToFilterString() returns invalid filter for string does not contain
Fix #1906
2025-01-13 10:27:17 +02:00
Vladimir Enchev
f920f9f08d demo updated 2025-01-10 14:15:37 +02:00
Vladimir Enchev
e6272e88e6 text fixed 2025-01-10 11:27:01 +02:00
Vladimir Enchev
4be24abf7f Version updated 2025-01-10 10:56:33 +02:00
Vladimir Enchev
85cc05a144 Added Simple and SimpleWithMenu FilterMode support for DataGrid composite columns 2025-01-10 10:55:53 +02:00
yordanov
7f726c4e2a Fix RadzenTree icon margin should not propagate to treenode label's child content 2025-01-09 12:16:07 +02:00
Paul Ruston
5c86ffd2ac Add SelectedView to SchedulerLoadEventArgs (#1900) 2025-01-09 10:44:56 +02:00
Vladimir Enchev
257444b640 DataGrid sort order not set properly when SortProperty is different from Property 2025-01-09 09:39:08 +02:00
yordanov
c61d453de4 Remove end-of-year promo 2025-01-07 10:43:26 +02:00
Atanas Korchev
4b88b18e78 RadzenChart throws an exception when all series data is zero. Fixes #1885. 2025-01-06 11:49:09 +02:00
Vladimir Enchev
1125894e7a version updated 2025-01-06 10:29:24 +02:00
Vladimir Enchev
e8894360fa DataGrid CheckBoxList filter loading indicator added 2025-01-06 10:29:10 +02:00
David Kohout
168c071ac3 Support for inserting after specific row in DataGrid (#1894)
* Support to insert new row after specific row

* Demo page updated to show insert after row
2025-01-06 10:03:14 +02:00
zjelev
d6dd67951e keep your enums values in English & export in excel their description (#1895) 2025-01-06 09:39:01 +02:00
Bendegúz Török
c7e4470a60 Include link to excess appointments in the month check (as in YearPlannerView) (#1888) 2025-01-04 16:51:48 +02:00
Paul Ruston
cb6789504a Ability to Show / Hide Scheduler Header (#1891) 2025-01-04 15:30:58 +02:00
Vladimir Enchev
314664c4e2 Fixed Nullable Integer RadzenNumeric allows decimals
Fix #1880
2025-01-04 08:42:43 +02:00
Vladimir Enchev
58794f806c Numeric input not updated when Value is set to null 2025-01-04 08:28:32 +02:00
Nopke
6a470a6448 Standard dark theme base flag fix (#1889)
* Standard dark theme: remove incorrect 'base' flag

* Standard dark base theme: add missing 'base' flag
2025-01-02 18:59:12 +02:00
yordanov
27bf1713a0 Fix background colors of right inline frozen columns 2025-01-02 17:01:59 +02:00
Atanas Korchev
c1e428dd3e RadzenTree throws collection modified exception when SingleExpand is set to true. 2025-01-02 16:58:46 +02:00
yordanov
661e5b50f8 Update copyright year 2025-01-02 15:25:56 +02:00
Paul Ruston
749c2cf600 Update Scheduler Title when StartMonth changes in Year Views (#1873)
* Update Scheduler Title when StartMonth changes in Year Views

* Update to the Demo page

* Slight update to XML comment on SchedulerYearViewBase->StartMonth
2024-12-27 16:27:34 +02:00
Atanas Korchev
153e9e01bc Fix broken link. Closes #1881. 2024-12-27 16:26:14 +02:00
Vladimir Enchev
c1797cc215 Version updated 2024-12-27 04:16:26 +02:00
jakubiszon
00eb31cd88 refactor(demos): simplify DataGridColumnPicking example (#1883) 2024-12-27 07:18:58 +07:00
AndreikaKanareika
bd4b1e485b Added ShowHeader parameter for RadzenDataGrid component (#1882) 2024-12-26 17:28:48 +07:00
Vladimir Enchev
387eacf5ff Steps aria-label attribute fixed
Fix #1877
2024-12-25 03:39:42 +02:00
Vladimir Enchev
5d00e79e0b Catched possible sporadic exception invoking 'RadzenTooltip.CloseTooltip'
Fixed #1871
2024-12-20 12:21:05 +02:00
yordanov
3aac6a785d End-of-year promotion CHEERS2025 2024-12-20 09:11:00 +02:00
Christian Storb
3506256dff Prevent decimal insertion in integer-only fields (#1868)
Added a condition to check if the value is not an integer before allowing the insertion of a decimal separator when the 'NumpadDecimal' key is pressed. This ensures that decimal points are not inserted in fields restricted to integer values, maintaining their integrity.

Co-authored-by: Christian Storb <c.storb@wibutler.io>
2024-12-19 18:05:31 +02:00
Atanas Korchev
5c49ab32e5 Sort appointments by length greater than one day. Fixes #1864. 2024-12-19 11:24:39 +02:00
Vladimir Enchev
f128209c3a Version updated 2024-12-19 09:28:40 +02:00
Nenad Kovačević
4a4254847a Fixed a typo in cookie name in ThemeServicePage.razor (#1865) 2024-12-19 09:28:04 +02:00
Vladimir Enchev
d21697367c Fixed DataGrid CheckBoxList filtering with LoadData for enums 2024-12-19 09:24:23 +02:00
Vladimir Enchev
1ceaab2788 Accordion item Disabled property added
Close #1861
2024-12-18 15:51:39 +02:00
Paul Ruston
0c56f20f55 New Property - RadzenMultiDayView->AdvanceDays (#1855) 2024-12-17 11:06:08 +02:00
Vladimir Enchev
261339c7e9 Fixed DataGrid CheckBoxList filtering with LoadData and In/NotIn operator 2024-12-16 10:02:10 +02:00
Vladimir Enchev
1d1335fed5 Version updated 2024-12-16 09:11:53 +02:00
Josh
c9b5a53be3 Introduce ItemComparer parameter to DropDownBase, for IEqualityComparer support (#1854)
* Introduce ItemComparer parameter to DropDownBase. Use HashSet to track selectedItems.

* include summary for ItemComparer Parameter
2024-12-16 09:09:53 +02:00
Reinhard
11a037aeec Add customizable RadzenTreeItem css classes (#1856)
- Add ContentCssClass to RadzenTreeItem
- Add IconCssClass to RadzenTreeItem
- Add LabelCssClass to RadzenTreeItem
- Add ItemContentCssClass to RadzenTree
- Add ItemIconCssClass to RadzenTree
- Add ItemLabelCssClass to RadzenTree
2024-12-16 09:02:05 +02:00
yordanov
0743bb5f54 Fix Scheduler Planner and Timeline view z-index. Resolves #1815 2024-12-13 16:39:13 +02:00
yordanov
9fe5163d86 Add responsive utility classes for sizing, overflow, and alignment in flexbox. Resolves #1756 2024-12-13 16:16:57 +02:00
Paul Ruston
acd107b1a2 Scheduler New View - MultiDay (#1852)
* Scheduler New View - MultiDay

* Clean up. Remove comment marker
2024-12-13 14:47:17 +02:00
kerajel
1ff96df224 RadzenDataFilter.DrawNumericFilter to use ValueChanged (#1850)
Co-authored-by: Dmitrii Botov <dmitrii.botov@rokolabs.com>
2024-12-12 09:09:27 +02:00
Vladimir Enchev
fb537c46d4 Fixed Scheduler exception when navigating away 2024-12-11 18:32:41 +02:00
Vladimir Enchev
a588b454ae Version updated 2024-12-11 17:00:15 +02:00
Vladimir Enchev
0f145800fa DataGrid will close column filter after open in case of hidden column runtime 2024-12-11 16:59:08 +02:00
Vladimir Enchev
44dfa72f16 PickList SelectAllText added
Fix #1832
2024-12-11 09:00:40 +02:00
Vladimir Enchev
19152f498c Version updated 2024-12-10 14:05:14 +02:00
Vladimir Enchev
056a61c9fe Numeric stringValue set for OnChange as well 2024-12-10 10:56:57 +02:00
Vladimir Enchev
a0cfc5d267 Fixed Numeric component input lost in some cases 2024-12-10 10:11:24 +02:00
Vladimir Enchev
eb6dbf0c67 DataFilter numeric input errors handled 2024-12-09 16:43:44 +02:00
Vladimir Enchev
af2083120e DataFilter oninput added for numeric filtering (#1846)
code improved

ApplyFilter removed
2024-12-09 16:34:18 +02:00
Vladimir Enchev
95d4c0e992 DataGrid column should not be visible if all child columns are not visible 2024-12-09 13:33:07 +02:00
Vladimir Enchev
b14f67685a Version updated 2024-12-09 11:48:42 +02:00
Vladimir Enchev
b82fa04aec DataGrid non numeric advanced filtering fixed
Fix #1844
2024-12-09 09:16:34 +02:00
Vladimir Enchev
93d1e8604a PickList ItemRender event added 2024-12-06 10:36:26 +02:00
Atanas Korchev
53d32dbcc2 Rounded corners in stacked bar and column chart sometimes do not display. Closes #1675. 2024-12-05 17:35:40 +02:00
Vladimir Enchev
da43d91b5a PickList AllowMoveAll, AllowMoveAllSourceToTarget, AllowMoveAllTargetToSource properties added 2024-12-05 15:39:01 +02:00
Jaap-Jan de Wit
0694ab0777 Fix null ref exception when column is null on GroupsCollectionChanged (#1836) 2024-12-05 15:14:37 +02:00
Vladimir Enchev
207940426d DatePicker DateRender will not apply class attribute 2024-12-05 15:08:56 +02:00
Vladimir Enchev
58a204ed56 Version updated 2024-12-05 10:07:23 +02:00
Vladimir Enchev
f68a2719f4 DataGrid cell editing validation fixed 2024-12-05 10:07:03 +02:00
kerajel
4311b019f4 RadzenDataGridHeaderCell to handle nullable types in ApplyFilter (#1834)
* RadzenDataGridHeaderCell to handle nullable types in ApplyFilter

* code clean up

* code clean up

---------

Co-authored-by: Dmitrii Botov <dmitrii.botov@rokolabs.com>
2024-12-04 09:08:22 +02:00
Vladimir Enchev
c1b7ce0bcc Version updated 2024-12-03 15:39:45 +02:00
yordanov
fe0ca5403c Remove Cyber Monday promo 2024-12-03 11:55:58 +02:00
Vladimir Enchev
c5c33ebfeb Check if TextProperty is set when attempting to use it for filter 2024-12-03 11:38:52 +02:00
Atanas Korchev
2c24843e4d Scheduler does not render some events in month view. Closes #1828. 2024-12-03 10:48:01 +02:00
Vladimir Enchev
b0e17e572c Fixed DataGrid advanced numeric filter input issues caused by Blazor server latency 2024-12-03 09:17:20 +02:00
yordanov
7cd5727ccc Add info for Radzen Blazor for Visual Studio 2024-12-02 17:22:33 +02:00
Dimi Catrysse
d02bafc7a6 Update RadzenPager.razor.cs (#1827)
Adjust default value of `FirstPageTitle` to have consistent value with other titles (no dot).
2024-12-02 15:42:28 +02:00
Vladimir Enchev
ca4bdad32a Missing DateOnly check added
Close #1826
2024-12-02 11:28:53 +02:00
yordanov
4fab7f9180 Add Cyber Monday promo 2024-12-01 11:12:40 +02:00
yordanov
224f54c676 Add UI Blocks intro video 2024-12-01 11:11:48 +02:00
Vladimir Enchev
fbc1dbb443 Fixed DataGrid advanced numeric filter second input Issue
Fix #1824
2024-12-01 10:38:25 +02:00
Atanas Korchev
4da4e532c5 RadzenColorPicker is not fully integrated with the EditContext API.
Closes #1822.
2024-11-30 18:20:59 +02:00
Vladimir Enchev
a16447faa2 Version updated 2024-11-30 15:31:08 +02:00
Vladimir Enchev
a883b26dda DataGrid CheckBoxList filter for numerics and enums fixed.
Fix #1823
2024-11-30 15:30:48 +02:00
Vladimir Enchev
b9937ee6ca Fixed parameter is not of type node with AutoComplete 2024-11-29 16:04:35 +02:00
simonlübker
40ed1d5841 adds missing non-nullable DateOnly typecheck (#1820)
Co-authored-by: Simon Lübker <simon.luebker@equicon.de>
2024-11-29 14:30:22 +02:00
Vladimir Enchev
0d3b86d06b Fixed Tabs OnKeyPress out of range exception 2024-11-29 14:09:26 +02:00
Vladimir Enchev
f8464d6f23 Version updated 2024-11-29 10:19:54 +02:00
Vladimir Enchev
d2995e3b6c employeeID should be set to null on clear 2024-11-29 09:28:26 +02:00
Vladimir Enchev
eda37027d5 Force DataGrid advanced numeric filter value on apply only for default UI 2024-11-29 09:27:11 +02:00
Vladimir Enchev
11f9e5cfa4 DataGrid advanced numeric filter second value fixed
Fix #1817
2024-11-29 09:13:06 +02:00
Vladimir Enchev
a59a02a6a7 Fixed DataGrid, advanced filter with Settings on column with a Enum type
Fix #1816
2024-11-29 09:01:07 +02:00
Vladimir Enchev
26db867bd5 Filtering of DropDownBase will be able to handle null values 2024-11-28 13:40:09 +02:00
Vladimir Enchev
18a92cbaca Version updated 2024-11-28 09:59:52 +02:00
Chenxiang
62ac151847 Update RadzenDatePicker.razor (#1814)
fix: button text
2024-11-28 09:58:20 +02:00
Vladimir Enchev
0b3628e085 DataGrid numeric advanced filter input improved 2024-11-28 09:56:57 +02:00
Vladimir Enchev
ffb23e7f34 demo updated 2024-11-27 09:12:34 +02:00
Vladimir Enchev
678d861e22 DataGrid filtering sub properties should handle null values 2024-11-25 22:33:46 +02:00
Vladimir Enchev
652e08ebbe Attempt to fix possible bug with numeric filter not submitting value caused by Blazor server lag 2024-11-25 09:37:04 +02:00
Vladimir Enchev
95672569c5 Version updated 2024-11-22 16:49:09 +02:00
Vladimir Enchev
c9bedc9315 Tooltip generates console error when RadzenTooltip.CloseTooltip called
Fix #1808
2024-11-22 16:48:49 +02:00
Vladimir Enchev
dbaeb39564 Version updated 2024-11-22 09:50:36 +02:00
yordanov
1e9801b0d4 Remove duplicate rz-layout styles from the demos 2024-11-22 09:19:18 +02:00
Vasil Yordanov
eed82f2b6e UI Blocks (#1806)
Add UI Blocks
2024-11-21 16:56:17 +02:00
Vladimir Enchev
a0f1545421 Tooltip position updated when forced to change 2024-11-21 14:47:42 +02:00
Atanas Korchev
a69909ff23 Add another info message in the getting started. 2024-11-21 14:00:59 +02:00
Atanas Korchev
65c99d3fbd Add .net 9 to getting started. 2024-11-21 13:23:17 +02:00
Atanas Korchev
687094fec0 Revert "Remove unsupported .NET versions from the getting started."
This reverts commit 6d84bafa2e.
2024-11-21 13:23:17 +02:00
simonlübker
757debaecc fixes missing DateOnly Type check in if statement (#1803)
Co-authored-by: Simon Lübker <simon.luebker@equicon.de>
2024-11-21 08:52:24 +02:00
Vladimir Enchev
6d5dda80ee Version updated 2024-11-20 15:56:18 +02:00
Vladimir Enchev
b9d9e965d5 DropDownDataGrid should not request items on clear if not needed 2024-11-20 15:48:51 +02:00
Vladimir Enchev
e845df2a10 DropDownDataGrid should not request items on clear 2024-11-20 15:43:01 +02:00
Vladimir Enchev
93cfc0e15d obsolete code deleted 2024-11-20 14:34:28 +02:00
Vladimir Enchev
7a35bc2340 Tooltip should call openTooltip only once 2024-11-20 14:24:47 +02:00
Vladimir Enchev
dc7eebb8ae DataGrid advanced filter popup position fixed 2024-11-20 14:17:23 +02:00
Vladimir Enchev
1dfc967900 Slider step not working properly when equal to min 2024-11-20 14:08:21 +02:00
Vladimir Enchev
bb5217948d Tooltip top/left position fixed 2024-11-20 14:00:11 +02:00
Vladimir Enchev
c2269711c5 SplitButton popup overlaps the button in some cases 2024-11-20 11:50:58 +02:00
Vladimir Enchev
e707b99860 demo marked as new 2024-11-19 16:02:44 +02:00
Vladimir Enchev
ec43241ccc Version updated 2024-11-19 16:00:13 +02:00
Vladimir Enchev
c45436dcf4 DataGrid FilterOperators column property added, FilterValueTemplate enabled for SimpleWithMenu and CheckBoxList filter modes (#1800)
* DataGrid FilterValueTemplate support for SimpleWithMenu FilterMode

* demo updated
2024-11-19 15:44:04 +02:00
Vladimir Enchev
d41c3ee72b Popup positioning improved 2024-11-19 15:41:54 +02:00
yordanov
0058d0aa56 Update responsive classes to reduce white space on smaller screens. Resolves #1798 2024-11-19 10:17:26 +02:00
Vladimir Enchev
868638f031 Version updated 2024-11-18 13:02:00 +02:00
Marat Chiraev
a8250f17c3 Fix missing element reference for RadzenSplitterPane (#1796) 2024-11-18 12:50:40 +02:00
yordanov
c3bbc7e31c BlackFriday2024 2024-11-18 12:43:02 +02:00
Vladimir Enchev
5d5565b832 DataGrid IsValid property added 2024-11-18 11:19:15 +02:00
Vladimir Enchev
5da0ff61b2 Version updated 2024-11-18 10:34:22 +02:00
Maks
79efa87d39 Fix FilterString generation for the FilterOperator.In and FilterOperator.NotIn (#1794)
Co-authored-by: Sacred <s>
2024-11-18 10:30:43 +02:00
Vladimir Enchev
a56981bc70 RadzenDataFilterProperty FilterProperty property added similar to DataGrid columns to be able to filter collection sub property
Fix #1792
2024-11-18 10:28:53 +02:00
Vladimir Enchev
24f30bf18f RadzenDropZoneItemEventArgs DataTransfer property added to handle files drop 2024-11-18 09:45:54 +02:00
Vladimir Enchev
0fa843fd78 Fixed touch not working properly on page with Slider component 2024-11-18 09:26:21 +02:00
Vladimir Enchev
aecee331a4 Version updated 2024-11-15 15:55:13 +02:00
Vladimir Enchev
c1b7cc6d65 Fixed popup can cause scroll in some cases 2024-11-15 15:54:40 +02:00
Atanas Korchev
b8ddfa6537 Check if document.body is available to prevent JS errors when Radzen.Blazor.js is incorrectly included in the <head>. 2024-11-15 14:54:38 +02:00
Atanas Korchev
fd4bd631e5 Update the NumericRangeValidator demo to mention numeric suffixes that hint the Blazor parser what type to infer. 2024-11-15 14:53:02 +02:00
Atanas Korchev
96b8901cde Allow the developer to set the Fill of RadzenSeriesAnnotation. Closes #1789. 2024-11-15 14:40:14 +02:00
Vladimir Enchev
124033d122 DataGrid column numeric advanced filter improved 2024-11-15 09:11:50 +02:00
Vladimir Enchev
cbb292b828 Fixed disabled SplitButton tabindex not correct
Fix #1788
2024-11-14 18:16:30 +02:00
Vladimir Enchev
22b5fc2452 DataGrid advanced filter FilterValueTemplate demo added with Numeric 2024-11-14 10:46:29 +02:00
yordanov
d549a314bc Set dynamic viewport height to RadzenLayout on screen widths less than 768px 2024-11-13 18:33:38 +02:00
Vladimir Enchev
f32fe71dbc test fixed 2024-11-13 17:44:10 +02:00
Vladimir Enchev
169cf14fa6 bunit.web updated 2024-11-13 17:30:01 +02:00
Atanas Korchev
3befe007fd Update ci.yml 2024-11-13 17:22:04 +02:00
Atanas Korchev
6d84bafa2e Remove unsupported .NET versions from the getting started. 2024-11-13 17:20:15 +02:00
Vladimir Enchev
f3badc0ad4 DataGrid OData demo fixed
Fix #1786
2024-11-13 15:55:46 +02:00
Vladimir Enchev
df9887b629 Edit/run of demos fixed 2024-11-13 11:29:21 +02:00
Vladimir Enchev
cbecf5b954 Version updated 2024-11-13 09:04:43 +02:00
Vladimir Enchev
040cccebe2 NET9 support added (#1785) 2024-11-12 22:21:55 +02:00
Vladimir Enchev
efffdf54c3 Vertical slider added (#1781)
* Slider Orientation property added

Vertical range slider keyboard navigation fixed

* Update slider styles

* Vertical slider rendering fixed

* Add Updated badge to Slider

---------

Co-authored-by: yordanov <vasil@yordanov.info>
2024-11-11 10:29:38 +02:00
Atanas Korchev
c3cb0c8968 Update the getting started instructions for WASM standalone. 2024-11-09 11:13:29 +02:00
yordanov
d676c67b50 Add demo for filled icons 2024-11-08 14:16:25 +02:00
Vladimir Enchev
9316170c89 Fixed DataGrid CheckBoxList filter exception with Enum sub property 2024-11-08 08:55:51 +02:00
Vladimir Enchev
9101614d35 Version updated 2024-11-06 18:14:36 +02:00
Vladimir Enchev
7312b2859d GoogleMap UpdateMap() fixed 2024-11-06 18:14:17 +02:00
Vladimir Enchev
bf7d99ccba Fixed Carousel Auto=true does not repeat cycle
Fix #1774
2024-11-06 10:08:29 +02:00
Vladimir Enchev
fb0d588cbf Fixed DataGrid will not show EmptyTemplate when AllowVirtualization=true 2024-11-06 10:05:33 +02:00
Vladimir Enchev
8e7bd6323a Version updated 2024-11-05 12:21:20 +02:00
Vladimir Enchev
8bebd1933d Fixed "The ParameterView instance can no longer be read because it has expired." error with virtualized DropDownDataGrid 2024-11-05 11:57:35 +02:00
Vladimir Enchev
2429b2c027 Missing summary added 2024-11-05 11:23:05 +02:00
Vladimir Enchev
769820792f Fixed DataGrid Object must implement IConvertible with DateOnly filtering for OData
Fix #1772
2024-11-05 10:52:32 +02:00
Jake Mauch
36f39b5023 Add callback for Open and Close to RadzenDropDown (#1771)
Co-authored-by: jmauch <jmauch@webstaurantstore.com>
2024-11-05 09:51:28 +02:00
Vladimir Enchev
bb675ee040 Fixed Carousel out of range exception when navigating to out of range index
Close #1769 #1770
2024-11-05 09:45:48 +02:00
Vladimir Enchev
9b4aff7a3f Fixed DataGrid LoadColumnFilterData paging arguments not passed correctly 2024-11-05 08:57:53 +02:00
Vladimir Enchev
e312d71286 Carousel swipe should not prevent touch of other nested components 2024-11-04 18:21:57 +02:00
Atanas Korchev
a397c686b8 Avoid using new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase). Should fix #1705. 2024-11-04 09:21:04 +02:00
Atanas Korchev
9b92005810 Load assemblies in parallel. 2024-11-04 09:21:04 +02:00
Atanas Korchev
d4e0c8c3bb Compilation error when trying to edint the realtime data example. 2024-11-04 09:21:04 +02:00
Vladimir Enchev
ae1ec9aaa2 Version updated 2024-11-04 09:16:34 +02:00
Vladimir Enchev
e811bb9213 DataGrid will close column filter after open in case of hidden column with FilterPopupRenderMode="PopupRenderMode.OnDemand" 2024-11-01 19:49:08 +02:00
Vladimir Enchev
7de5d90c82 DataGrid Reset() should reset to original columns order 2024-11-01 19:43:45 +02:00
Vladimir Enchev
bf5265c15b Fixed boolean fields in advanced filter auto-apply without pressing 'Apply'
Fix #1766
2024-11-01 09:07:49 +02:00
Vladimir Enchev
49b111a0e9 Fixed RadzenCarousel Navigation will skip one item forward on manual navigation with Auto=true
Fix #1764
2024-11-01 08:53:34 +02:00
Vladimir Enchev
85964d9f17 Version updated 2024-10-31 10:27:58 +02:00
Vladimir Enchev
4f9075fa77 Demo updated to reinitialize DataGrid columns when switching between filtering modes 2024-10-31 10:24:03 +02:00
Vladimir Enchev
0856c9005c Fixed the ParameterView instance can no longer be read because it has expired with virtualized DropDownDataGrid 2024-10-31 10:01:13 +02:00
Vladimir Enchev
31d8bccfcf version updated 2024-10-29 11:21:09 +02:00
Vladimir Enchev
9213e3d3ef Fixed DataGrid column FilterOperator will always default to what set initially 2024-10-29 11:20:54 +02:00
Vladimir Enchev
3665079cc9 Version updated 2024-10-29 09:47:31 +02:00
Vladimir Enchev
44881e521c Changing Carousel Auto from false to true will not restart the timer properly 2024-10-29 09:47:02 +02:00
yordanov
c136d8050b Update premium themes 2024-10-29 09:41:00 +02:00
Vladimir Enchev
a5cc04b46f carousel demos fixed 2024-10-29 09:40:26 +02:00
Vladimir Enchev
a9a8b6314b Carousel swipe support fixed 2024-10-29 09:36:00 +02:00
Jan Biehl
5c7be3bcfc Update DataAnnotationValidatorConfig.razor (#1759)
The proper full width class should be rz-w-100 instead of w-100
2024-10-29 09:20:50 +02:00
yordanov
e3893198af Update Chart label rotation demos 2024-10-29 07:42:35 +02:00
yordanov
6a4e6dc5a1 Update premium themes 2024-10-29 07:41:40 +02:00
Atanas Korchev
643916f733 Chart label rotation. 2024-10-28 16:57:28 +02:00
yordanov
e964851d53 Update premium themes 2024-10-28 10:11:26 +02:00
Vladimir Enchev
79e495dc14 Version updated 2024-10-28 10:07:36 +02:00
Maxim Becker
13326879f0 Render chart tooltips in the same way as standard tooltips (#1745)
* Render chart tooltips in the same way as standard tooltips

* Move OpenChartTooltip method to TooltipService to avoid code duplications

* Avoid partially hiding of chart tooltip near top of page

* Make some of the types internal.

---------

Co-authored-by: Atanas Korchev <akorchev@gmail.com>
2024-10-28 10:01:13 +02:00
Vladimir Enchev
293a871db4 DropDownDataGrid sorting when virtualized fixed 2024-10-28 08:48:30 +02:00
Vladimir Enchev
4c9dc6350d demo source code fixed 2024-10-28 07:22:32 +02:00
Vladimir Enchev
4c54afdc55 PickList Placeholder, SourcePlaceholder and TargetPlaceholder added 2024-10-26 11:42:43 +03:00
Vasil Yordanov
d60841b040 Add CardGroup component. Resolves #1658 (#1753)
Add RadzenCardGroup component
2024-10-25 16:17:47 +03:00
yordanov
7e640f47a5 Hide icons until icon font is loaded. Resolves #1752 2024-10-25 16:00:27 +03:00
Vladimir Enchev
f3d1b273f1 Real-time data demo added for the DataGrid 2024-10-24 15:54:26 +03:00
Vladimir Enchev
e80f5b85e9 ApiKey defined for updateMap method 2024-10-24 13:35:31 +03:00
Atanas Korchev
1b5725caee Use wasm files to avoid firewall issues. 2024-10-23 11:02:58 +03:00
Vladimir Enchev
820e8f8323 unpkg.com added to script-src 2024-10-23 09:49:11 +03:00
mcgovern-ellsworth
30672e52bb added autocomplete parameters to RadzenDropDown. (#1748)
* added autocomplete parameters to RadzenDropDown.

* removed the InputAutoCompleteType setting since that input control is hidden but the outer div.
2024-10-22 18:37:24 +03:00
Vladimir Enchev
ac9796f50d demo updated 2024-10-22 16:40:43 +03:00
Vladimir Enchev
66b7b4cad0 Version updated 2024-10-22 09:50:36 +03:00
Vladimir Enchev
f417b9cc73 PreserveRowSelectionOnPageing renamed to PreserveRowSelectionOnPaging 2024-10-22 09:50:21 +03:00
Greg-MM
a304d4643c Fixed bug when navigating RadzenDropDownDataGrid with keyboard, down worked, but up would focus 2 rows above the selected index (#1747)
Added PreserveRowSelectionOnPageing to RadzenDropDownDataGrid which will keep the currently selected row index, defaults to false so there are no breaking changes

Co-authored-by: TSE <Administrator@TranExec.com>
2024-10-22 09:44:38 +03:00
Vladimir Enchev
8386e5a2b5 Version updated 2024-10-22 09:40:49 +03:00
Vladimir Enchev
27f57b96c0 DataGrid wrong number of rows rendered in some cases with composite columns 2024-10-21 17:43:50 +03:00
Vladimir Enchev
d9a049d523 version updated 2024-10-21 16:19:25 +03:00
Vladimir Enchev
f53f724b04 DataGrid duplicate rows fixed 2024-10-21 16:19:02 +03:00
Vladimir Enchev
a41105656a Version updated 2024-10-21 13:05:46 +03:00
Vladimir Enchev
54269abfd1 GoogleMap should respect Culture language 2024-10-21 12:51:34 +03:00
Vladimir Enchev
e812ff1337 DataGrid composite columns span not properly calculated in case of non visible columns 2024-10-21 11:48:42 +03:00
Vladimir Enchev
ae28f8f239 DataGrid group footers demo updated 2024-10-17 12:19:31 +03:00
Vladimir Enchev
470f261dc0 titles fixed 2024-10-17 11:04:30 +03:00
Vladimir Enchev
80cfda23b6 demo improved 2024-10-17 10:45:35 +03:00
Vladimir Enchev
5321c4d52b Version updated 2024-10-17 10:14:44 +03:00
Vladimir Enchev
0466912f3e Carousel Navigate() method will reset timer 2024-10-17 10:13:24 +03:00
Vladimir Enchev
3d3932e657 EmployeeTerritorysData added 2024-10-17 10:04:55 +03:00
Vladimir Enchev
d63117a17a DataGrid wrong column grouped in some cases with composite columns 2024-10-17 09:39:12 +03:00
Vladimir Enchev
ba06a72326 Carousel manual navigation should reset the auto-rotate timer
Fix #1741
2024-10-16 16:06:37 +03:00
Vladimir Enchev
2671f6ca61 Carousel pager not updated on auto rotate in some cases
Fix #1740
2024-10-16 15:26:07 +03:00
yordanov
8dddfcbc92 Remove obselete tabs styles. Resolves #1742 2024-10-16 14:58:05 +03:00
yordanov
ebc5793f36 Fix label overlapping when RadzenFileInput is in RadzenFormField. Resolves #1716 2024-10-16 11:17:59 +03:00
yordanov
4946221651 Fix rz-column-title overflow if it has a checkbox inside. Resolves #1683 2024-10-15 15:52:23 +03:00
Vladimir Enchev
de9817a97f DataGrid should not show two expand icons in case of both self-reference hierarchy and Template defined
Fix #1737
2024-10-14 16:36:08 +03:00
yordanov
1218c4f385 Disabled text color in material theme should be lighter. Resolves #1736 2024-10-14 11:07:52 +03:00
Vladimir Enchev
e9cee62d03 demo improved 2024-10-14 09:31:37 +03:00
yordanov
fa7cf37eab Update Documentation link to API reference 2024-10-14 09:25:29 +03:00
Vladimir Enchev
b9ecb7556f Version updated 2024-10-14 09:07:42 +03:00
Vladimir Enchev
661b38e1e6 DataGrid column picking demo improved with context menu option
Close #1735
2024-10-14 08:53:06 +03:00
Vladimir Enchev
769f4ba589 Tooltip smart position will take into account scrollbar width 2024-10-12 18:00:40 +03:00
Vladimir Enchev
6118253ebf DataFilter LoadData demo improved 2024-10-12 10:43:19 +03:00
Vladimir Enchev
0f7f717330 DataGrid/DataFilter ToFilterString() enumerable type discovery improved 2024-10-12 10:37:18 +03:00
yordanov
0b16f1eb97 Buttons in Tooltip position demo should wrap 2024-10-11 15:44:37 +03:00
Atanas Korchev
e733894c02 RadzenBody sometimes triggers JS exception after navigation. 2024-10-10 19:38:41 +03:00
Vladimir Enchev
c47dcfbe27 warnings fixed 2024-10-10 18:24:46 +03:00
Vladimir Enchev
8ae008ec9d Carousel component added (#1732)
* Carousel component added

* Carousel with Pager demo added

* Carousel demos improved

* Update carousel

* Carousel improved

* Carousel demos reworked with database data

* Add carousel pager overlay styles

* Update carousel demos

* Add Carousel to homepage and update icon

* Add Carousel styles to themes

* Update Carousel styles and demos

* Update Carousel markup and styles

* Update Carousel demos

* Update ExampleService

---------

Co-authored-by: yordanov <vasil@yordanov.info>
2024-10-10 18:21:22 +03:00
Vladimir Enchev
45ef0c78a3 docker updated 2024-10-10 15:33:05 +03:00
Vladimir Enchev
3ac46f239e Version updated 2024-10-10 14:56:48 +03:00
Vladimir Enchev
1e106f7ada DataPicker rz-readonly should be added only when ReadOnly=true 2024-10-10 14:56:32 +03:00
Vladimir Enchev
09738b2dd7 added version to blazor.web.js 2024-10-10 13:48:00 +03:00
Vladimir Enchev
dc67a0b0fc Version updated 2024-10-10 08:57:59 +03:00
Atanas Korchev
1258bbc770 RadzenDataAnnotationValidator supports nested properties. 2024-10-09 18:59:27 +03:00
Victor Ureta
5960318a60 Add same color to datepicker button as text (#1730)
* Update RadzenDatePicker.razor

* Update RadzenDatePicker.razor

* add ButtonClass
2024-10-09 13:33:37 +03:00
Vladimir Enchev
d4faf758f4 DataGrid will not render items when virtualized and grouped in some cases 2024-10-09 13:33:07 +03:00
Vladimir Enchev
f88216b9a0 ReadOnly Datepicker with PopupRenderMode Initial allows user to open popup and select date
Fix #1727
2024-10-09 11:41:04 +03:00
Vladimir Enchev
e21d648588 Closing tooltip should not try to restore focus 2024-10-09 09:04:33 +03:00
Vladimir Enchev
dbcbdc9bbc comment fixed
Fix #1729
2024-10-08 16:17:28 +03:00
Vladimir Enchev
c5d16e8381 FormatString added to DateTime column in Dialog demo 2024-10-08 16:13:36 +03:00
Vladimir Enchev
ac1aa6f3b1 dates updated 2024-10-08 16:09:20 +03:00
Vladimir Enchev
866c222c74 DropDown will not select item on Enter is some cases 2024-10-08 13:34:39 +03:00
Vladimir Enchev
06843477cb Index property added to DataGrid RowRenderEventArgs 2024-10-08 13:34:39 +03:00
Vladimir Enchev
9a7a6fc6ab DataGrid will group by wrong column in case of invisible columns 2024-10-08 13:34:38 +03:00
Atanas Korchev
4986da415f Some data grid grouping demos are not editable. 2024-10-08 08:10:09 +03:00
Vladimir Enchev
cdbd20b794 Version updated 2024-10-07 10:34:43 +03:00
Vladimir Enchev
49567ade65 DataGrid CheckBoxList filter values ordered by default 2024-10-06 10:23:28 +03:00
Vladimir Enchev
4d857449d2 DataGrid CheckBoxList filter boolean localization example added 2024-10-04 11:36:10 +03:00
Vladimir Enchev
dc03621a14 DataGrid column FormatString can be used to localize boolean in CheckBoxList filter 2024-10-04 09:03:16 +03:00
Vladimir Enchev
b83cca17e2 Fixed DropDown will focus disabled items in some cases 2024-10-03 15:06:49 +03:00
Vladimir Enchev
343afffd40 Fixed DatePicker can select disabled date if focused 2024-10-03 11:44:59 +03:00
Vladimir Enchev
163eac9511 Version updated 2024-10-03 10:11:32 +03:00
Vladimir Enchev
167bfcb0b3 Tabs focus logic with Visible=false tabs fixed
Fix #1722
2024-10-03 09:48:19 +03:00
Vladimir Enchev
f0f94eb84c Popup with DataGrid demo improved 2024-10-03 09:14:52 +03:00
Vladimir Enchev
7123c9ca12 SplitButton PopupID fixed 2024-10-03 09:01:23 +03:00
Vladimir Enchev
41e12d8e54 More focusTableRow improvements 2024-10-02 22:00:34 +03:00
Vladimir Enchev
473ab14ae6 focusTableRow improved 2024-10-02 21:57:43 +03:00
Vladimir Enchev
127ffd451c Keyboard navigation added to Popup with DataGrid demo 2024-10-02 18:16:53 +03:00
Vladimir Enchev
32bb43b66f DataFilter InText and NotInText added
Fix #1721
2024-10-02 17:53:31 +03:00
Vladimir Enchev
765f5acbcc Upload should not raise change if file is not selected 2024-10-01 16:54:22 +03:00
Vladimir Enchev
8ac137f22d Fixed FileInput error when canceled
Fix #1720
2024-10-01 16:51:07 +03:00
Vladimir Enchev
10bbf6b157 Version updated 2024-10-01 16:17:41 +03:00
ax-meyer
390dc0605b Use ToString() on property to filter in DataGrid CheckBoxList to check for empty strings (#1718)
The change in 35c9f55c41 broke filtering when the property to be filtered was not a string.
2024-10-01 16:17:06 +03:00
Vladimir Enchev
6fda9f0691 Version updated 2024-10-01 14:47:38 +03:00
Vladimir Enchev
0a1c5830d2 Fixed DataGrid enum filtering in simple mode 2024-10-01 14:47:21 +03:00
Vladimir Enchev
33efa2316d Version updated 2024-10-01 11:12:48 +03:00
Vladimir Enchev
b3de9374a7 Popup AutoFocusFirstElement property added
Popup demos updated.
2024-10-01 11:12:15 +03:00
Victor Ureta
1d869e8d2b Added AdditionalContent Parameter to Scheduler (#1717)
* feat: add AdditionalContent parameter for rendering custom content next to year, month, and day buttons in RadzenScheduler

* Change name variable
2024-10-01 08:49:10 +03:00
Atanas Korchev
56156dd5ff RadzenHtmlEditor applies valid and invalid classes during validation. 2024-09-30 20:01:23 +03:00
Vladimir Enchev
35c9f55c41 DataGrid CheckBoxList filter should use null instead empty string 2024-09-30 16:26:01 +03:00
Vladimir Enchev
e70e3559eb tests fixed 2024-09-30 10:26:58 +03:00
Vladimir Enchev
5957439475 Version updated 2024-09-30 10:13:44 +03:00
yordanov
322ed552ed Update premium themes 2024-09-30 09:37:59 +03:00
Antoine Gagné
bf848d5ef8 Fixed input width in RadzenFormFields (#1715) 2024-09-30 09:03:35 +03:00
Vladimir Enchev
285057a9df Filtering by nullable enum fixed 2024-09-30 07:58:15 +03:00
fallen576
4de62ffa55 Enum filtering using underlying types other than Int32 is now supported. (#1714) 2024-09-30 07:43:25 +03:00
Vladimir Enchev
f97fde1387 Update DataGridMixedAdvancedFilterPage.razor 2024-09-28 08:46:49 +03:00
Vladimir Enchev
8a5bba625c DataGrid will group wrong column in case of Visible=false columns 2024-09-27 08:07:04 +03:00
yordanov
108a209ac8 Update buttons' hover state in material3-dark. Resolves #1655 2024-09-26 17:10:34 +03:00
yordanov
8390a4aba9 Use forced-colors media query instead of -ms-high-contrast. Resolves #1712 2024-09-26 16:28:27 +03:00
yordanov
9740416e56 Hide unwanted focused outline around the table in RadzenDataGrid 2024-09-26 15:57:46 +03:00
yordanov
8cc82642f9 Update Popup demo 2024-09-26 14:40:30 +03:00
Vladimir Enchev
5f4804f4cf maps.googleapis.com added to font and styles csp exceptions 2024-09-25 13:35:44 +03:00
Vladimir Enchev
24dbee5d3d googleapis added to csp 2024-09-25 13:26:55 +03:00
Vladimir Enchev
298f84d25e DataGrid simple DateTime filter popup button will show active filter state 2024-09-25 10:02:46 +03:00
Vladimir Enchev
182c66f0a9 Added debug symbols to nuget package and updated the version 2024-09-24 15:44:41 +03:00
Vladimir Enchev
fd11c34646 Version updated 2024-09-24 15:20:16 +03:00
Vladimir Enchev
6bcc7388bb RadzenNumeric prevents tab out when up/down key pressed before
Fix #1711
2024-09-24 15:15:14 +03:00
Vladimir Enchev
60da0c0082 Added 'notranslate' CSS class to all icons 2024-09-24 15:11:09 +03:00
Vladimir Enchev
2b2b48bec4 DataGrid column filters not cleared properly 2024-09-24 13:24:01 +03:00
Vladimir Enchev
d579f79399 DatePicker with Inline=true should not close or toggle popup 2024-09-23 11:43:17 +03:00
Vladimir Enchev
bf85df68b3 DatePicker as calendar, disappears when press escape key
Fix #1706
2024-09-23 08:56:40 +03:00
Vladimir Enchev
e6e7ec49df Mask component value not updated on change in Safari 2024-09-20 09:34:27 +03:00
Vladimir Enchev
e7801e1222 Version updated 2024-09-19 10:11:28 +03:00
Vladimir Enchev
3327254022 DataGrid filter aria label properties misspelled 2024-09-19 10:10:49 +03:00
Vladimir Enchev
d53d09e358 Version updated 2024-09-19 08:54:23 +03:00
Vladimir Enchev
34c02ac391 Upload will unable to upload empty file
Fix #1702
2024-09-19 08:51:26 +03:00
Atanas Korchev
cf4eb0c9cd Chart series annotations are sometimes duplicated. 2024-09-18 16:22:42 +03:00
Atanas Korchev
ee6220b1fe DataGrid row drag and drop works in day and month view. 2024-09-18 14:43:51 +03:00
Vladimir Enchev
a264638726 demo improved 2024-09-18 10:47:32 +03:00
Atanas Korchev
3e6a10a57d DataAnnotationValidator throws exception when used with double properties. Fixes #1689. 2024-09-18 09:55:55 +03:00
Vladimir Enchev
5258816770 SecurityCode input not focused after count change
Close #1700
2024-09-18 09:27:41 +03:00
Vladimir Enchev
fb4457f9a1 Dialog closes on ESC even if CloseDialogOnEsc = false in some cases
Fix #1699
2024-09-17 20:01:25 +03:00
Vladimir Enchev
627a74038c demos improved 2024-09-17 14:59:47 +03:00
Tcsaba66
54c297e898 create optional parameters for radzenhtmleritorimage (#1691) 2024-09-17 14:22:08 +03:00
Vladimir Enchev
a4d7201f7d DataFilter ToFilterString() should traverse filters exactly like Where() extension method 2024-09-17 09:51:15 +03:00
Atanas Korchev
b04cf69b90 Change the documentation link to point to the API reference. 2024-09-16 17:26:56 +03:00
Atanas Korchev
ea654f0b8d Remove the guides and redirect to the demos. 2024-09-16 17:14:03 +03:00
Vladimir Enchev
9b16aaf9e4 Version updated 2024-09-16 16:16:50 +03:00
yordanov
87672de761 Add utility css classes for display, overflow, sizing and borders 2024-09-16 16:13:02 +03:00
Vladimir Enchev
171a8def6d DataGrid KeyDown event added 2024-09-16 16:07:32 +03:00
Equitis
f09179f4cd Insert NumpadDecimal at cursor position. (#1693)
Co-authored-by: Patrick Fuhr <p.fuhr@solutit.de>
2024-09-16 16:01:54 +03:00
Vladimir Enchev
03f62068b3 DatePicker year DropDown should respect Culture 2024-09-16 14:59:51 +03:00
Atanas Korchev
828b4230e3 Required validation triggers unnecessarily for RadzenHtmlEditor. 2024-09-16 14:45:55 +03:00
Vladimir Enchev
2b23e5d472 demo fixed 2024-09-16 12:56:40 +03:00
Vladimir Enchev
17dbe70460 Pager will focus clicked button if not disabled 2024-09-13 16:38:45 +03:00
Atanas Korchev
587c3a0647 Remove outdated getting started instructions from the documentation. 2024-09-13 13:49:08 +03:00
Vladimir Enchev
83f0879b11 demo update to use Change instead onblur event 2024-09-13 10:53:38 +03:00
Vladimir Enchev
212b741828 demo updated 2024-09-13 10:26:23 +03:00
Vladimir Enchev
ee81b608f9 AutoComplete property deleted. All cases will be supported trough custom attribute 2024-09-12 16:06:23 +03:00
Vladimir Enchev
ad17080ee8 AutoComplete parameter type changed from bool to object to comply with .NET9
In .NET 9 it's not longer possible to have custom attribute and parameter with similar names - casing is ignored.
Details: https://github.com/dotnet/razor/issues/8854
2024-09-12 15:01:51 +03:00
Atanas Korchev
6a8611c348 Implement UploadComplete event in RadzenHtmlEditor. 2024-09-12 13:06:47 +03:00
Vladimir Enchev
3ba3610b21 DataGrid CheckBoxList column filter not refreshed on search when AllowCheckBoxListVirtualization="false" 2024-09-12 10:36:02 +03:00
Vladimir Enchev
8deed23e01 PropertyAccess.GetDynamicPropertyExpression() method added 2024-09-11 17:04:11 +03:00
Monsieurvor
356106263b NumericRangeValidator: AllowNull (#1686)
* AllowNull range validator

* Change comment

* Add AllowNull test case

* Fix test assertion

* Update RadzenNumericRangeValidator.cs
2024-09-11 15:25:10 +03:00
Vladimir Enchev
0566244b61 CSP tab added 2024-09-11 11:02:47 +03:00
Vladimir Enchev
17d76b4e6f Version updated 2024-09-11 09:57:55 +03:00
Vladimir Enchev
9c3490f275 Content-Security-Policy added to demos 2024-09-11 09:56:24 +03:00
Vladimir Enchev
b1b6499d7c DataGrid column AllowCheckBoxListVirtualization property added 2024-09-10 18:07:51 +03:00
Vladimir Enchev
a36a74091f Fixed RadzenDataGrid Grouping very slow on the first render
Fix #1684
2024-09-10 17:16:12 +03:00
Vladimir Enchev
4dfbd676af Fixed DatePicker logic for HoursStep, MinutesStep and SecondsStep 2024-09-10 08:24:19 +03:00
Vladimir Enchev
f72f8b3e39 Version updated 2024-09-09 12:36:34 +03:00
Vladimir Enchev
45cc6880f9 DataGrid should close other columns filter popups when FilterPopupRenderMode == PopupRenderMode.OnDemand 2024-09-09 11:04:35 +03:00
Vladimir Enchev
17281cd3b1 Numeric inputmode attribute can be defined using InputAttributes 2024-09-09 10:28:47 +03:00
Vladimir Enchev
332b452b56 Numeric inputmode attribute support fixed 2024-09-09 09:32:44 +03:00
Vladimir Enchev
c647515186 DataFilter IsEmoty/IsNotEmpty operators logic fixed 2024-09-08 15:15:54 +03:00
Vladimir Enchev
6faf0ed9b9 DataFilter 'Is Null' & 'Is Not Null' filter options do not produce correct filter via ToFilterString()
Fix #1682
2024-09-08 15:08:53 +03:00
Lynkle
fad024d9bb fix(FileInput): Modified FileInput.razor to handle rendering the preview of an image correctly when using byte[] as the TValue instead of string. Added a corresponding demo to highlight this. (#1680) 2024-09-08 08:29:45 +03:00
Vladimir Enchev
67718df278 Version updated 2024-09-06 09:26:34 +03:00
Christoph
273c3283c2 Add Reload method to RadzenTree (#1678)
* Added demo to illustrate the refresh problem with dynamic loading.

* Added RadzenTree.Reload public API.

* Documentation added.
2024-09-06 09:24:01 +03:00
Vladimir Enchev
aa7306ebd1 DropDownDataGrid OpenOnFocus logic fixed 2024-09-06 09:16:27 +03:00
Vladimir Enchev
56cb173ad5 DataGrid will not render colgroup if there are child columns
Fix #1674
2024-09-05 14:50:06 +03:00
Vladimir Enchev
174f0a9393 demo updated 2024-09-05 09:26:50 +03:00
Vladimir Enchev
a1dbc1a6fb DataGrid exception when trying to filter DateTimeOffset 2024-09-04 09:02:39 +03:00
Vladimir Enchev
d9de2ee0bc Version updated 2024-09-03 17:45:31 +03:00
Vladimir Enchev
cf1e0eda27 Fixed DataGrid string column will always apply Contains for initial filter 2024-09-03 17:40:37 +03:00
Vladimir Enchev
ccc82e5a61 DropDownDataGrid @bind-SelectedItem can cause endless loop in some cases 2024-09-02 14:08:43 +03:00
Vladimir Enchev
0859f939dd DataGrid CheckBoxList filter breaks cells value from enum description 2024-09-02 10:25:11 +03:00
Atanas Korchev
519c133c0c Update the descriptions and content of the RadzenHtmlEditor demos. 2024-09-02 10:22:48 +03:00
Atanas Korchev
9f62860821 The user can insert images and links in RadzenHtmlEditor by pressing Enter. 2024-09-02 09:51:24 +03:00
Atanas Korchev
238ed1ac2c The user can select an image in RadzenHtmlEditor by clicking it. Then use the Insert image tool to set its attributes. Closes #1209. 2024-09-02 09:51:24 +03:00
Vladimir Enchev
cd5903b358 Version updated 2024-09-02 09:08:33 +03:00
Vladimir Enchev
f78125c4fb DropDownDataGrid focus of selected item fixed 2024-09-02 09:06:54 +03:00
Atanas Korchev
6394241b9f Shared tooltips do not work in some cases. 2024-09-01 20:54:57 +03:00
Vladimir Enchev
d4dfc9bbab Fixed Slider with Min="1" change value with click 2024-08-31 09:32:27 +03:00
Vladimir Enchev
cf668be964 Version updated 2024-08-30 18:41:03 +03:00
Vladimir Enchev
6ef443d724 DropDownDataGrid Cannot read properties of undefined (reading 'classList') error fixed 2024-08-30 18:40:36 +03:00
Vladimir Enchev
75af217864 demo title fixed 2024-08-30 11:46:48 +03:00
Vladimir Enchev
7a7343c3c8 demo updated 2024-08-30 11:39:59 +03:00
Vladimir Enchev
18bfa8f562 DataGrid will allow mixed Simple and SimpleWithMenu modes per column 2024-08-30 11:38:46 +03:00
Vladimir Enchev
a76a0815a0 DataGrid column FilterMode property added
Fix #1672
2024-08-30 11:07:18 +03:00
Vladimir Enchev
332f384a65 DropDown selected item not highlighted on initial popup open 2024-08-29 09:52:38 +03:00
Vladimir Enchev
3c5e1216c8 Version updated 2024-08-29 09:17:42 +03:00
Vladimir Enchev
c7c11a1c1e DropDownDataGrid keyboard navigation fixed 2024-08-29 09:17:23 +03:00
Vladimir Enchev
0dd993c1d0 version updated 2024-08-28 10:09:36 +03:00
Vladimir Enchev
c977e9b59c DropDownDataGrid row not selected on initial selection 2024-08-28 10:09:16 +03:00
Vladimir Enchev
81055b5500 DataGrid composite column GroupFooterTemplate fixed 2024-08-28 09:53:00 +03:00
Vladimir Enchev
c8df446846 demo fixed 2024-08-28 09:15:36 +03:00
Vladimir Enchev
97ac4621b9 DataList ShowEmptyMessage disabled by default 2024-08-26 13:07:38 +03:00
Vladimir Enchev
9346c474cf DataGrid simple filter input autocomplete disabled 2024-08-26 13:06:24 +03:00
Vladimir Enchev
d9a55965d3 DataList EmptyMessage, EmptyTemplate and ShowEmptyMessage added
Fix #1666
2024-08-26 13:03:10 +03:00
Vladimir Enchev
50306343a8 Version updated 2024-08-23 11:48:55 +03:00
Vladimir Enchev
08d7457620 Fixed Numeric floating-point value loss of precision
Fix #1667
2024-08-23 11:32:02 +03:00
Vladimir Enchev
b80a382d2f Fixed DropDown collapse when inside Popup 2024-08-23 09:58:38 +03:00
Vladimir Enchev
ab066bb441 DataGrid column FooterTemplate not rendered when only for composite columns 2024-08-23 09:20:03 +03:00
Vladimir Enchev
4a64260d6e Version updated 2024-08-22 07:51:39 +03:00
Vladimir Enchev
9390077007 DropDownDataGrid HeaderTemplate duplicated
Fix #1664
2024-08-22 07:44:34 +03:00
yordanov
baf5386e34 Hide RadzenButton's hover state on touchscreen devices 2024-08-21 10:27:31 +03:00
Vladimir Enchev
86e72b2f7f PanelMenu will use PanelMenuItem.Match if not default (#1662) 2024-08-21 10:06:35 +03:00
Vladimir Enchev
70bc02b12e DataGrid Bool and Bool? filters not handled correctly
Fix #1663
2024-08-21 10:05:56 +03:00
Vladimir Enchev
6bce8b0195 RadzenTreeItem rendering fixed
Close #1660
2024-08-20 16:31:14 +03:00
yordanov
dd4afb1d0a Fix DropDown chips padding within a flat or filled FormField. Resolves #1654 2024-08-16 08:56:29 +03:00
Vladimir Enchev
95493fe157 version updated 2024-08-16 07:54:09 +03:00
Vladimir Enchev
42b9ef3956 CheckBoxListItem does not update aria-checked selected
Fix #1653
2024-08-16 07:51:19 +03:00
Vladimir Enchev
97ee7b7a7a DatePicker not closed when date is picked without time 2024-08-16 07:26:33 +03:00
Atanas Korchev
230860f773 Preload the icon font to test loading. 2024-08-15 13:04:37 +03:00
Atanas Korchev
5f7f6d975e Update the Sparkline demo. 2024-08-15 12:58:17 +03:00
yordanov
e7c95fdcc1 Components are now more than 90 2024-08-15 11:24:13 +03:00
Vladimir Enchev
933367a685 Version updated 2024-08-15 10:03:51 +03:00
yordanov
4857307533 Update demos homepage 2024-08-15 09:53:06 +03:00
Atanas Korchev
1ee50e42ca Raise the Paste event when an image is pasted. Closes #1652. 2024-08-15 09:50:26 +03:00
Vladimir Enchev
5bbc108331 DropDown OpenOnFocus behavior improved 2024-08-15 09:05:50 +03:00
Vladimir Enchev
11d62516d9 DataGrid column FormatProvider property added
Fix #1649
2024-08-15 08:39:14 +03:00
yordanov
ef714a8bfc Update premium themes 2024-08-14 19:13:14 +03:00
yordanov
c6b8441a79 Update demos homepage 2024-08-14 19:13:14 +03:00
Atanas Korchev
200ad86575 Exception is thrown when using bar series with empty data. 2024-08-14 12:29:12 +03:00
Vasil Yordanov
54fe2f260f New Shared chart tooltips and Sparkline component (#1651)
* Implement shared tooltips.

* Style Chart tooltips.

* Initial Sparkline implementation.

* Support axes in the Sparkline.

* Add Sparkline demo.

---------

Co-authored-by: Atanas Korchev <akorchev@gmail.com>
2024-08-14 12:20:06 +03:00
Vasil Yordanov
e056cf743d Fix progressbar value color. Resolves #1641 (#1650)
* Fix progressbar value color
* Fix failing ProgressBar tests
2024-08-14 12:01:19 +03:00
yordanov
8dbc747928 Update icons on homepage 2024-08-13 17:40:14 +03:00
Vladimir Enchev
969b37e4e9 Version updated 2024-08-12 08:31:35 +03:00
Vladimir Enchev
79a111668e Fixed Splitter exception when all panes Resizable=false 2024-08-12 08:25:45 +03:00
yordanov
9c90e3110b Fix padding-inline-end spacing utility classes 2024-08-09 17:49:03 +03:00
yordanov
59237fb9c6 Improve links' focus state on homepage 2024-08-09 16:29:14 +03:00
yordanov
fc3705f019 Update demos homepage, icons and links 2024-08-09 16:00:27 +03:00
Vladimir Enchev
15adbc0823 Fixed DataFilter ToFilterString() wrong expression for dates
Fix #1642
2024-08-09 10:04:40 +03:00
Vladimir Enchev
ca6472f5f2 DropDownDataGrid HeaderTemplate and FooterTemplate support added
Fix #1643
2024-08-09 08:53:39 +03:00
Vladimir Enchev
de38322f34 DataGrid ColumnReordering event added
Fix #875
2024-08-08 18:54:26 +03:00
Vladimir Enchev
ed45d30639 Version updated 2024-08-08 14:06:19 +03:00
Vladimir Enchev
f99fc6f15f SideDialogOptions AutoFocusFirstElement added 2024-08-08 11:49:53 +03:00
Vladimir Enchev
56aaa082da DataGrid custom filtering demo fixed
Fix #1614
2024-08-08 10:51:02 +03:00
Vladimir Enchev
0aaa2f20bd ProfileMenu keyboard navigation improved
Fix #1636
2024-08-08 10:30:51 +03:00
Vladimir Enchev
bac589e3ec DataGrid column null propagation for filtering will be used only for nullable types
Fix #1633
2024-08-08 10:02:29 +03:00
Vladimir Enchev
1dc7b02a3c SplitButton not cleared from DOM after disposed
Fix #1630
2024-08-08 09:43:08 +03:00
Vladimir Enchev
83965afe68 DataGrid CheckBoxList Filter is not showing all values
Fix #1640
2024-08-07 17:57:50 +03:00
Wolfowy
0e9b110023 Check fireChangeEvent before invoking Change event in RadzenUpload (#1638) 2024-08-07 17:42:27 +03:00
yordanov
44f01a77fd Fix SplitButton spacing issue between icon and text. Resolves #1639 2024-08-07 17:18:27 +03:00
yordanov
58552b7a50 Fix Panel's toggle icon colors in Standard Dark theme 2024-08-07 16:43:07 +03:00
Vladimir Enchev
ddf3feac51 Version updated 2024-08-06 12:33:02 +03:00
Vladimir Enchev
c2d59fcee1 DatePicker should not close the popup when setting the day if ShowTimeOkButton is true 2024-08-06 12:31:41 +03:00
yordanov
ee3b2592aa Disable rz-ripple pointer events 2024-08-05 15:59:52 +03:00
yordanov
ed79dfb220 Fix TextAlign css class not properly applied to rz-numeric 2024-08-05 13:06:21 +03:00
yordanov
6fbb942ad9 Fix TextAlign not applied in RadzenNumeric 2024-08-05 12:47:13 +03:00
yordanov
94a9340ee3 Fix #1631 IconColor property not applied in RadzenSplitButtonItem 2024-08-02 19:02:34 +03:00
yordanov
ef6d2b7d2b Restrict box-sizing to .rz- selectors and their children, and disable box-sizing inheritance. Resolves #1632 2024-08-02 09:58:59 +03:00
Vladimir Enchev
7f0b603f60 version updated 2024-08-01 17:48:29 +03:00
Vladimir Enchev
04ec31ea5c GoogleMap custom marker fixed 2024-08-01 17:48:07 +03:00
Vladimir Enchev
d1ff36c44a . 2024-08-01 17:29:36 +03:00
Vladimir Enchev
d703443469 . 2024-08-01 16:48:53 +03:00
Vladimir Enchev
5455a02c4d version updated 2024-08-01 16:11:44 +03:00
yordanov
4bbb186f63 Fix disabled state of AutoComplete and DatePicker in FormField 2024-08-01 15:22:10 +03:00
Vladimir Enchev
b62e8bf976 DropDownBase should not raise ContextMenu event if disabled 2024-08-01 11:04:38 +03:00
Vladimir Enchev
7ccc4fe33a GoogleMap will use default marker label if not set custom 2024-08-01 08:08:33 +03:00
Vladimir Enchev
b52d1cf1e2 ApiKey and MapId info added 2024-08-01 07:58:44 +03:00
Vladimir Enchev
6ee9db0eb8 DataGrid CheckBoxList filtering support improved for collection sub properties 2024-07-29 16:42:16 +03:00
Vladimir Enchev
36ac2a5bfb Missing Include("Customer") added 2024-07-29 13:33:59 +03:00
Vladimir Enchev
e1841c652a Version updated 2024-07-29 10:04:01 +03:00
Vladimir Enchev
6fc2c88482 sorting disabled 2024-07-29 10:03:14 +03:00
Vladimir Enchev
b8a13a5ba4 Filtering sub properties demo added 2024-07-29 09:45:49 +03:00
Vladimir Enchev
d36623c1fb Added DataGrid Contains/DoesNotContain support for collection sub properties 2024-07-29 09:01:21 +03:00
Adam Hewitt
06ab88556c Set 'disabled' attribute on RadzenPager links when on the first/last page (#1627)
* Set 'disabled' attribute on RadzenPager buttons

* add tests

* fix pager test

---------

Co-authored-by: Adam Hewitt <ahewitt@glasswall.com>
2024-07-29 07:42:35 +03:00
Vladimir Enchev
b552790035 Added marker label content for GoogleMap demo
Fix #1624
2024-07-29 07:42:06 +03:00
Atanas Korchev
6610dd22df Show how to use CookieThemeService in .NET 6 & 7. 2024-07-26 19:22:45 +03:00
Atanas Korchev
04dddf92d8 Remove @code{} from the heading. 2024-07-26 17:49:10 +03:00
Atanas Korchev
bedd9c97c2 Add missing step for theme persistence. 2024-07-26 17:33:26 +03:00
Atanas Korchev
81c859ba31 Fix typo in cookie service registration. 2024-07-26 16:51:13 +03:00
Vladimir Enchev
041e662e07 Version updated 2024-07-26 16:14:18 +03:00
yordanov
65c7c66b50 Update premium themes 2024-07-26 16:07:47 +03:00
yordanov
287f2762f9 Update ThemeService demo 2024-07-26 11:39:53 +03:00
yordanov
3750e94ff5 Update icon demos 2024-07-26 10:34:26 +03:00
Atanas Korchev
e127d60345 Append the assembly version to CSS file url to prevent caching of old themes. 2024-07-26 10:21:17 +03:00
Atanas Korchev
5189298884 Add ThemeService demo. 2024-07-26 09:48:20 +03:00
Vladimir Enchev
5a9c370b29 Class changed to class 2024-07-26 08:50:50 +03:00
yordanov
ec4f370f29 Update changelog 2024-07-25 11:18:55 +03:00
yordanov
da194dd88d Update premium themes 2024-07-25 11:06:55 +03:00
yordanov
91e6b86eb3 Update sample dashboard layout 2024-07-25 10:55:58 +03:00
Cosmatevs
550e2d59b4 DataGrid: fix textbox and checkbox indents in simple filters (#1620)
* DataGrid: fix textbox and checkbox indents in simple filters

* use :has(.rz-filter-button) only to change elements other than .rz-filter-button
2024-07-25 10:15:51 +03:00
Vladimir Enchev
80b7ef08c8 TextArea demo updated with auto-resize example
Fix #1501
2024-07-24 10:15:41 +03:00
Vladimir Enchev
7c9ddf0c3f TextArea demo updated with char count example
Fix #1604
2024-07-24 09:53:22 +03:00
Vladimir Enchev
9abdb1d47b Readme updated 2024-07-24 09:16:29 +03:00
Vladimir Enchev
a5171dd9b4 Version updated 2024-07-24 08:31:50 +03:00
Vladimir Enchev
4e7c04efbe Warnings fixed 2024-07-24 08:31:31 +03:00
Vladimir Enchev
d3c66dc750 NET5_0_OR_GREATER preprocessor removed 2024-07-24 08:28:35 +03:00
Vladimir Enchev
7e14357902 Dialog Drag event fixed
Close #1612
2024-07-24 08:11:35 +03:00
Cosmatevs
92f6c2448f RadzenMask: fix string duplication on typing when a character allowed by the pattern (e.g. 2 is in [0-9]) is in the mask (e.g. "+22 *** *** ***") (#1618) 2024-07-24 07:38:35 +03:00
Vladimir Enchev
b05ebe8bdf GoogleMap MapId property added 2024-07-23 18:34:34 +03:00
Vladimir Enchev
0b62390a54 DataGrid CheckBoxList Filter Values repeat values when scroll down
Fix #1616
2024-07-23 18:17:39 +03:00
mayoismyfavoritespice
8c9b5f2a18 added disableSmartPosition option support to enforce style 'top' properties from being corrected automatically (#1613) 2024-07-23 07:21:17 +03:00
Vladimir Enchev
960894c329 Version updated 2024-07-22 18:23:25 +03:00
Vladimir Enchev
a5786ecccf DataGrid cannot insert new row when bound to empty collection
Fix #1610
2024-07-22 18:23:00 +03:00
Atanas Korchev
33a83928e7 Include getting-started as a URL. 2024-07-22 11:25:51 +03:00
Vladimir Enchev
149c6271b3 Made Dialog client-draggable to avoid unwanted content rendering during dragging.
Close #1590
2024-07-22 10:10:59 +03:00
Eric McGaha
031d23df0c HtmlEditor exception when editing previously uploaded image (#1605) (#1606) 2024-07-22 09:04:23 +03:00
Maks
30134bf3b5 Fixed the issue where the DatePicker popup not appeared in RadzenDatePicker when the ShowButton parameter was set to false. (#1607) 2024-07-22 08:46:54 +03:00
yordanov
7907150f17 Fix #1579 Right sidebar does not show on smaller screens and ignores Responsive attribute 2024-07-19 16:23:51 +03:00
yordanov
e5f9639d1e Remove unused css variables in RadzenPager. Resolves #1351 2024-07-19 12:01:01 +03:00
yordanov
47bad16b54 Update to latest Material Symbols Outlined font 2024-07-18 18:58:21 +03:00
yordanov
efa944ef8c Update drop style in DataGridRowDragScheduler demo 2024-07-18 18:00:43 +03:00
Atanas Korchev
68d4cfff16 Update the changelog. 2024-07-18 18:00:34 +03:00
Atanas Korchev
c9c6c4c5ea Remove hash parameters before parsing the query string. 2024-07-18 17:52:56 +03:00
Atanas Korchev
792b3a1267 Tell that AppearanceToggle requires RadzenTheme. 2024-07-18 17:50:01 +03:00
Atanas Korchev
5b64cf6925 Avoid NavigationException on first redirect. 2024-07-18 17:29:51 +03:00
Atanas Korchev
097878b4b2 Query string parsing does not work on Windows. 2024-07-18 17:11:49 +03:00
yordanov
32eca9aabf Update spacing on Get Started page 2024-07-18 16:45:57 +03:00
Vladimir Enchev
7a27432885 Version updated 2024-07-18 16:25:41 +03:00
Vladimir Enchev
92e4249eec 5.0 (#1603)
* Initial commit

Update spacing css classes in demos

Update spacing css classes in demos

Improve Notification layout and styles

Fix Notification with custom position in RTL mode

Update spacing css classes in demos

Add box-sizing: border-box to components

Remove bootstrap css from App.razor

Fix text-align in tabs demos

Rename CSS classes and update markup in RadzenDatePicker

Remove bootstrap scss

Tabs anchor element should inherit the text color

Update margins in typography

Remove bootstrap instructions from get started page

Remove bootstrap css from demos

Update premium themes

Add variable fonts

Remove legacy color tokens and token maps

Remove --rz-form-group-margin-bottom as it is not used

Add base color tokens

Add Base style values

Remove -styles scss map and use  and  styles maps instead

Remove -styles scss map and use  and  styles maps instead

Remove -styles scss map and use  and  styles maps instead

Remove -styles scss map and use  and  styles maps instead

Format button's styles

Reset body margin to 0

Splitter icons should use --rz-icon-font-family

Add styles for image and svg

Replace MaterialIcons font with MaterialSymbols variable font

Update RadzenButton's demos

Update RadzenBadge's demos

Update Colors demo page

Update RadzenProgressBars' demos

Use Base instead of Secondary button style in Confirm Dialog

Update DataGrid Hierarchy demos

Unify DataGrid filter buttons

Replace light with base button styles

Replace secondary with base button style

RadzenTheme, RadzenThemeSwitch and ThemeService.

Reorder base color variables

Add rtl mode animation to ProgressBar

Update SpeechToTextButton default button style and animation

Add CookieThemeService.

Fix base color variable value in software theme

Add Software Dark and Humanistic Dark themes

Update RadzenThemeSwitch

Default base text button should inherit color from its parent element

Update ColoPicker background for transparent color preview

Add Material Dark theme

Material Dark theme is now free

Remove ambiguous method name.

Update demos configurator

Update premium themes

Update the services to follow the options pattern for DI registration.

Improve RadzenThemeSwitch to use the current theme.

Rename ThemeSwitch to AppearanceToggle and add a demo page

Update SplitButton's dropdown icon demo

Create getting-started.html

Update getting-started.html

Update getting-started.html

Add --rz-grid-group-header-item-color and fix column footer color

Fix demos code snippet colors

Add changelog and update demo status badges

Update Changelog

Persist the current theme.

Update getting-started.html

Rename getting-started.html to md.

Render the theme CSS class at RadzenLayout level.

Hide the right sidebar by default.

Isolate CSS variables in a single rule

Revamp the getting started help article.

Remove nested README.md. Link getting started instructions.

Add Scheduler highlight background color css variable

Sidebar border right should be inline-end

Inputs should inherit font-family

Buttons in code viewer and event console should use base button style

Add Standard Dark theme

Update Changelog

Sidebar border right in themes should be inline-end

Render RadzenTheme only when needed.

Add cursor pointer to SidebarToggle

Fix AppearanceToggle margin

Update default theme colors

Update standard theme colors

Fix filter color in humanistic dark theme

Update software dark theme colors

Add humanistic dark wcag theme

Add software dark wcag theme

Add standard dark wcag theme

Buttons for add and remove now use base button style

Update Get Started styling

Update Dark WCAG theme colors

Update SideBar transition styles

Remove theme name css class

Add premium themes

code fixed

more code fixes

* Update Icon demo page content

* Fix --rz-grid-filter-buttons-background-color in Standard theme

* Remove obsolete fonts

* tests fixed

---------

Co-authored-by: yordanov <vasil@yordanov.info>
2024-07-18 16:24:20 +03:00
Vladimir Enchev
6fac0aa0f5 DataGrid filter popup should be always lazy if FilterMode == FilterMode.CheckBoxList 2024-07-18 14:28:05 +03:00
Vladimir Enchev
cd2ede5ce8 DataGrid CheckBoxList filter type filtering fixed 2024-07-18 13:32:08 +03:00
Vladimir Enchev
ac407375ab Dialog Resize and Drag events added 2024-07-18 10:32:18 +03:00
Vladimir Enchev
1730effc55 Version updated 2024-07-17 11:31:14 +03:00
Vladimir Enchev
21c063ac53 Fixed DropDown/ListBox select as you type selects second item first 2024-07-17 11:19:47 +03:00
Vladimir Enchev
2ba2ef9617 Version updated 2024-07-17 10:59:59 +03:00
Vladimir Enchev
cfe2424cff DataGrid LoadColumnFilterData event added to load column filter data for DataGrid FilterMode.CheckBoxList filter mode (#1600)
* DataGrid LoadColumnFilterData event added

* CheckBoxList with OData support added
2024-07-17 10:58:55 +03:00
Vladimir Enchev
397fe2a0c8 DataGrid EnumFilterTranslationFunc not applied to second filter
Fix #1599
2024-07-17 08:45:52 +03:00
TGasimov
e846cc532c RadzenCompareValidator fails when validated RadzenDatePicker value cleared (#1598)
Co-authored-by: Gasimov, Teymur <GasimovT@bv.com>
2024-07-16 16:47:05 +03:00
Vladimir Enchev
d273f99940 DataGrid column GetSortIndex() method added
Fix #1595
2024-07-16 14:07:29 +03:00
Vladimir Enchev
f0763c2b67 Version updated 2024-07-15 17:47:34 +03:00
Justyna Sienkiewicz
48d6293ab6 Fixed inserting to CurrentItems (#1596) 2024-07-15 17:46:37 +03:00
yordanov
0e270595df Add responsive styles to DataGrid simple filter mode with menu. Resolves #1586 2024-07-15 16:43:38 +03:00
yordanov
db6770159e Fix ability to set width and height of a SplitButton 2024-07-15 14:33:47 +03:00
Vladimir Enchev
e6bf1ed6f7 DataGrid CheckBoxList filter demo FilterPopupRenderMode set to PopupRenderMode.OnDemand 2024-07-12 10:53:06 +03:00
Vladimir Enchev
996dd11e24 Version updated 2024-07-11 11:12:04 +03:00
Krystian Szatan
4ea1f20022 RadzenSteps - Added AllowStepSelect parameter (#1591) 2024-07-11 11:10:16 +03:00
Vladimir Enchev
a56cfc5688 DropDown, DropDownDataGrid and ListBox code updated (#1593) 2024-07-11 10:58:33 +03:00
Paul Ruston
d71d05374f MonthSelect event on all Year Views (#1587)
* MonthSelect event on all Year Views in rendering

* Resolve initial PR oversights

* Resolve initial PR oversights 2
2024-07-10 17:59:29 +03:00
Barry
99b82b24d0 Add RadzenDataAnnotationValidator to Support Data Annotation Validation (#1588)
* implement data annotation validator

* Rebase to latest `master` branch. Update the demo. Use PropertyAccess.Getter instead of reflection.

---------

Co-authored-by: Atanas Korchev <akorchev@gmail.com>
2024-07-10 17:58:40 +03:00
Vladimir Enchev
5cfe624e25 Dialog focus trap will cycle between first and last focusable elements
Fix #1585
2024-07-10 11:29:40 +03:00
Vladimir Enchev
62066e04e3 PickList Disabled property added 2024-07-10 10:59:44 +03:00
Vincent Schmandt
5478c014f1 Add PackageLicenseExpression (#1578)
* Add PackageLicenseExpression

* Remove PackageLicenseFile as only PackageLicenseFile or PackageLicenseExpression can be provided

See also https://github.com/microsoft/vstest/issues/4816
2024-07-10 10:07:55 +03:00
Vladimir Enchev
aea3147454 DataGrid column col element width not reset properly
Fix #1582
2024-07-09 13:41:17 +03:00
Daniel Jonsson
e466de4d0e Fix a spelling error in StepsCanChange.razor (#1581) 2024-07-05 13:39:44 +01:00
Vladimir Enchev
0de3cf72b8 demo updated 2024-07-03 11:15:51 +03:00
Vladimir Enchev
41fa97994e Version updated 2024-07-03 10:21:05 +03:00
Vladimir Enchev
d03a563e0d Merge branch 'master' of https://github.com/radzenhq/radzen-blazor 2024-07-03 10:10:45 +03:00
Vladimir Enchev
0f89c0b112 Tree Checkable delegate fixed
Fix #1580
2024-07-03 10:10:42 +03:00
Atanas Korchev
07ae096af2 Ignore chart series radius if it exceeds the series size. Fixes #1576. 2024-07-01 18:52:59 +03:00
Zagidin Selimov
11e4d482f4 fix (#1575)
Co-authored-by: Zagidin Selimov <zselimov@adeptik.com>
2024-07-01 18:49:47 +03:00
Vladimir Enchev
f959e3b869 version updated 2024-07-01 17:33:16 +03:00
Vladimir Enchev
ec19bfb556 Dialog AutoFocusFirstElement will always focus first HtmlEditor 2024-07-01 17:31:10 +03:00
Vladimir Enchev
fa4edf9845 Drag from DataGrid to Scheduler demo added
Drag & Drop demos combined in separate category
2024-06-28 14:53:06 +03:00
Vladimir Enchev
ab52430846 DataGrid should clear filter values for other columns on ClearFilter 2024-06-28 10:50:50 +03:00
Vladimir Enchev
6045869260 Version updated 2024-06-28 10:18:04 +03:00
Vladimir Enchev
c08a598658 DataGrid CheckBoxList filter values collection will respect filters applied to other columns 2024-06-28 10:16:50 +03:00
Vladimir Enchev
340483bf7f DataGrid CheckBoxList filter should clear the column filter if no values are checked 2024-06-28 10:01:56 +03:00
Vladimir Enchev
87395e0ec4 Fixed DataGrid wrong column/rowspan in some cases with composite columns 2024-06-28 09:52:15 +03:00
Atanas Korchev
694194dd01 Allow developers to specify drag-and-drop events via SlotRender. 2024-06-28 09:23:38 +03:00
Vladimir Enchev
aa6935820d Version updated 2024-06-27 12:01:25 +03:00
Vladimir Enchev
57c038dca6 Added Checkable/CheckableProperty similar to Text/TextProperty in the RadzenTreeItem/RadzenTreeLevel 2024-06-27 12:00:57 +03:00
Vladimir Enchev
fe69b1419f Version updated 2024-06-27 11:36:21 +03:00
Vladimir Enchev
0cf7365755 Menu cannot open sub item with ClickToOpen=true 2024-06-27 11:35:54 +03:00
efinder2
7e96f776ff Changes aria-live regions for better screen reader (#1571)
* changed aria for screen reader

* fix div

* reverted RadzenAlert
2024-06-27 11:34:18 +03:00
Vladimir Enchev
e5ce3d46de Version updated 2024-06-26 10:15:11 +03:00
Vladimir Enchev
f097cb3c3a @nameof() used to set various property names across all demos 2024-06-26 10:13:54 +03:00
Vladimir Enchev
23aea7b794 Fixed DataGrid column picker filtering exception with columns without Title 2024-06-25 10:35:57 +03:00
Vladimir Enchev
c2839fdc29 Menu items not reachable in some case with ClickToOpen=false 2024-06-25 09:28:20 +03:00
Vladimir Enchev
3fbd64338c Fixed DataGrid UpdateRow() method for items with overridden Equals/GetHashCode() 2024-06-24 18:10:07 +03:00
Vladimir Enchev
36a2917b17 Version updated 2024-06-24 16:20:35 +03:00
Vladimir Enchev
9f3fc43791 DataGrid should not request all IQueryable data when virtualization is enabled in some cases 2024-06-24 16:20:10 +03:00
Vladimir Enchev
4774d2d1fd Version updated 2024-06-24 09:32:31 +03:00
Vladimir Enchev
91de8a5a8f Numeric tests fixed 2024-06-24 09:10:36 +03:00
Vladimir Enchev
652005264b Fixed DataGrid composite column wrong colspan when child column has no children
Fix #1568
2024-06-24 08:36:42 +03:00
Simon Pawlowski
98967410cb prevent numeric overflow on step up/down (#1570) 2024-06-24 08:16:03 +03:00
Vladimir Enchev
55b2e3f1ff Fixed Numeric overflow exception with byte as TValue
Fix #1567
2024-06-21 07:45:29 +03:00
Vladimir Enchev
cf8ddc98af DropDown and ListBox should not select items with SelectAll() if ReadOnly
Fix #1566
2024-06-21 07:33:58 +03:00
Atanas Korchev
f259fa85a5 Hide the right sidebar by default. 2024-06-19 16:24:12 +03:00
Atanas Korchev
5ea6c7739f Enable properly automatic layout of the Monaco editor. 2024-06-18 17:43:08 +03:00
Atanas Korchev
eac071af9d RadzenArcGauge does not use the Max scale value in some cases. 2024-06-18 17:37:03 +03:00
Vladimir Enchev
2b0f424af6 Version updated 2024-06-17 07:36:57 +03:00
Vladimir Enchev
fcbfd28025 DataGrid composite columns column span fixed in some cases 2024-06-17 07:36:36 +03:00
yordanov
37982fe416 Fix focus states in Scheduler day view 2024-06-14 12:10:49 +03:00
Vladimir Enchev
6824c85820 Fixed DataGrid advanced filter with empty/not empty operators 2024-06-14 09:02:32 +03:00
Vladimir Enchev
bd9f76222a DataGrid Conditional Columns render demo added 2024-06-13 11:32:44 +03:00
Paul Ruston
349e771f74 Fix DaySlotEvents rendering (#1531)
* Fix DaySlotEvents rendering

* Revert "Fix DaySlotEvents rendering"

This reverts commit 4982cd14bf.

* Day Rendering Process

* Updated comments regarding algorithm

* Changes as per https://github.com/radzenhq/radzen-blazor/pull/1531#issuecomment-2160029819
2024-06-13 11:23:43 +03:00
Vladimir Enchev
83c2993cef Version updated 2024-06-12 08:21:24 +03:00
Vladimir Enchev
dbb91fa140 AutoComplete OpenOnFocus added
Fix #1560
2024-06-12 08:09:11 +03:00
Vladimir Enchev
849ca6803d DataGrid should not set rowspan/colspan less than 1 2024-06-12 07:57:36 +03:00
bert-algoet
f41288f441 When using multiselect dropdown with chips, stop dropdown van repositioning when there is enough room below the dropdown. (#1559) 2024-06-12 07:55:20 +03:00
Robert McLaws
9e974d5c30 Adds CalculatedCssClass Func to RadzenDataGridColumn to allow users to style the cell based on properties of the underlying object. (#1561) 2024-06-12 07:55:02 +03:00
Vladimir Enchev
62d25ee917 DataGrid composite columns column span fixed 2024-06-11 19:13:53 +03:00
Milo Davis
652a5dd27d Add support for proper OData filtering of numeric data grid columns with null or not null options (#1558)
Co-authored-by: Milo Davis <DavisM@steelers.nfl.com>
2024-06-11 08:45:34 +03:00
Rudolf de Schipper
1051bfa661 Rename linq filtering data filter (#1557)
* Update QueryableExtension.cs to add ToLinqFilterString

Add ToLinqFilterString extension method plus 2 supporting methods, allowing RadzenDataFilter to create Linq-compatible filter strings

* Update QueryableExtension.cs - rename ToLinqFilterString

rename ToLinqFilterString into ToFilterString, to align with common practice.
2024-06-11 08:44:35 +03:00
Robert McLaws
3a3c481e3b [DataGrid] Enhanced DataGridColumn EditMode control (#1550)
* Adding RadzenGridColumn.IsInEditMode property, updating render check in RadzenDataGrid, and updating associated demo.

* Removed unnecessary usings.
2024-06-10 17:56:08 +03:00
Vladimir Enchev
9642c58d94 DataGrid CheckBoxList filter will check if Property/FilterProperty is defined 2024-06-10 17:55:06 +03:00
Sean Martz
72d37ab218 Add ability for RadzenDataGrid.Query to filter DateOnly datatypes (#1548)
Co-authored-by: seanmartz <smartz@smart-union.org>
2024-06-10 17:40:57 +03:00
Atanas Korchev
a2047f9498 RadzenHtmlEditor does not update the EditorContext state when its value changes. 2024-06-10 12:06:45 +03:00
Atanas Korchev
22a94130f2 Version updated 2024-06-07 15:04:43 +03:00
Vladimir Enchev
6a907ff0c2 Revert "Add filter capabilities for DateOnly in RadzenDataGrid (#1545)" (#1546)
This reverts commit 25572a9d57.
2024-06-07 14:43:45 +03:00
Vladimir Enchev
11e0ca29d4 Version updated 2024-06-07 09:05:08 +03:00
Vladimir Enchev
47cd4ef790 DataGrid CheckBoxList filtering improved 2024-06-07 09:04:43 +03:00
Sean Martz
25572a9d57 Add filter capabilities for DateOnly in RadzenDataGrid (#1545)
* Add DateOnly functionality

* Undo mass formatting

---------

Co-authored-by: seanmartz <smartz@smart-union.org>
2024-06-07 08:53:55 +03:00
Vladimir Enchev
02b94e5672 CheckBoxList should not select disabled items on select all 2024-06-07 07:41:04 +03:00
Vladimir Enchev
23790fefd6 DataGridCheckBoxListFilter demo updated 2024-06-06 16:48:13 +03:00
Vladimir Enchev
3c8e4a24c6 more obsolete code deleted 2024-06-06 16:39:22 +03:00
Vladimir Enchev
0f754055ab obsolete method removed 2024-06-06 16:37:52 +03:00
Vladimir Enchev
ac7c2612b2 DataGrid InCell Editing demo added
Fix #1543
2024-06-06 16:28:29 +03:00
Vladimir Enchev
7b54ff2046 DataGrid cannot expand/collapse group items when virtualized 2024-06-06 11:04:57 +03:00
Vladimir Enchev
c7743ffdbe DropDown grouping with multiple select demo imroved 2024-06-06 10:17:56 +03:00
Vladimir Enchev
7a604d39bd Version updated 2024-06-04 09:30:01 +03:00
nitrouscookies
7c67f8bba1 Add FilterOperator null check so SetParametersAsync doesn't override initial values (#1542)
Co-authored-by: dstillwell <dstillwell@moorheadschools.org>
2024-06-04 08:53:34 +03:00
Vladimir Enchev
6f2ca41eb6 Fix DropDownDataGrid Chips render to use ValueTemplate/Template if defined exactly like DropDown
Close #1539
2024-06-03 10:21:34 +03:00
Vladimir Enchev
b26ac16201 RadzenDropDownDataGrid Reset() does not work when Multiple= true
Fix #1540
2024-06-03 09:37:54 +03:00
Vladimir Enchev
71b7ba70d1 SecurityCode will use autocomplete="one-time-code" 2024-06-03 08:55:44 +03:00
bert-algoet
96bd62e0cc Check if SelectItem is null before calling disabledPropertyGetter (#1538) 2024-06-03 08:51:58 +03:00
Atanas Korchev
c2ce598d0f Update the SSRSViewer documentation. 2024-05-31 11:37:55 +03:00
Vladimir Enchev
cf56069804 Version updated 2024-05-31 10:54:25 +03:00
Vladimir Enchev
7834b535d6 DatePicker cannot set hour to 0 when bound to TimeOnly 2024-05-31 10:11:10 +03:00
Vladimir Enchev
4b440199a2 Demo style updated
Fix #1535
2024-05-30 14:51:43 +03:00
Vladimir Enchev
4facfa5c7a Added custom style for drag over DataGrid row 2024-05-30 09:59:16 +03:00
Vladimir Enchev
99ab247c06 Version updated 2024-05-29 15:50:39 +03:00
Kasun Jalitha
5cf12fced5 Modified the RadzenSplitButton to allow customizing its dropdown icon. (#1530)
* Modified the RadzenSplitButton to allow customizing its dropdown icon.

* Changed the text in demo page.
2024-05-29 15:49:41 +03:00
Vladimir Enchev
5abc92308a DatePicker DateTime Kind not set properly in some cases 2024-05-29 10:15:33 +03:00
Vladimir Enchev
ed50ca5b53 RadzenMask caret position kept during input
Fix #1529
2024-05-28 10:10:34 +03:00
Atanas Korchev
3e8eb1a6eb Implement TodaySelect event in RadzenScheduler 2024-05-26 10:54:03 +03:00
Vladimir Enchev
d360c584c1 Version updated 2024-05-24 12:34:58 +03:00
Vladimir Enchev
55482bf28a DataGrid CheckBoxList filtering fixed to work properly with enums and FilterTemplate 2024-05-24 12:33:59 +03:00
Vladimir Enchev
bcf5b4c1b2 unused demos deleted 2024-05-24 10:49:55 +03:00
Vladimir Enchev
7098e28532 code updated 2024-05-23 15:15:03 +03:00
Vladimir Enchev
ab8aa2e1ae demo fixed 2024-05-23 15:13:50 +03:00
Vladimir Enchev
97fc9a8b37 more demo updates 2024-05-23 15:12:42 +03:00
Vladimir Enchev
5f91a4561b DropDown demos group items start margin defined 2024-05-23 15:09:41 +03:00
Vladimir Enchev
b5dd56f187 ValueTemplate improved 2024-05-23 14:47:20 +03:00
Vladimir Enchev
819f0b7d7e Version updated 2024-05-23 13:11:20 +03:00
Vladimir Enchev
16399d4512 HeaderTemplate added to DropDownDataGrid, HeaderTemplate and ItemRender added to DropDown and ListBox
DropDown grouping demos improved, ListBox item Disabled fixed
2024-05-23 13:10:41 +03:00
Vladimir Enchev
86df184463 Cannot read properties of null (reading 'querySelector') at Object.createDatePicker
Fix #1523
2024-05-22 08:37:16 +03:00
Vladimir Enchev
a4a2d66b85 Version updated 2024-05-21 11:05:53 +03:00
Vladimir Enchev
1fb972cf2a DatePicker will not select with PopupRenderMode="PopupRenderMode.OnDemand"
Fix #1473
2024-05-21 09:35:28 +03:00
Krystian Szatan
f1ab0e3449 Added missing ContentCssClass set in DialogService (#1521)
* Dialog - custom container class

New parameter ContentCssClass

* Update DialogContainer.razor

* Revert rz-dialog-titlebar

* Update DialogService.cs

Added ContentCssClass
2024-05-21 09:33:02 +03:00
Vladimir Enchev
5032646090 Version updated 2024-05-20 15:17:58 +03:00
Atanas Korchev
2facce9633 Include text measurement data for cyrillic characters. Closes #1505. 2024-05-20 13:47:42 +03:00
Krystian Szatan
bce50b991e Dialog - custom container class (#1518)
* Dialog - custom container class

New parameter ContentCssClass

* Update DialogContainer.razor

* Revert rz-dialog-titlebar
2024-05-20 12:57:23 +03:00
Atanas Korchev
bd1a5ef046 Provide parsing config when using Dynamic Linq methods in order to improve initial performance. 2024-05-20 10:55:21 +03:00
stlufred
47e9b4b587 Fix exception if TreeLevel has no Text nor TextProperty (#1515)
This can happen when using template.
2024-05-19 17:21:16 +03:00
Vladimir Enchev
676e6127cd Version updated 2024-05-16 16:45:50 +03:00
Vladimir Enchev
7b192a4e14 demo updated 2024-05-16 16:15:22 +03:00
Vladimir Enchev
e3239ed0b3 Tree ItemContextMenu event added 2024-05-15 11:03:03 +03:00
Marco Papst
1423454191 Add a Footer template to RadzenDropZone (#1503)
* Add a Footer template to RadzenDropZone

* Add header over the Footer Template Demo

* rename FooterTemplate to Footer
2024-05-15 09:53:08 +03:00
Vladimir Enchev
285b6367ed RadzenDataGrid EmptyTemplate alignment/colspan is incorrect when Data Grid uses Grouping
Fix #1504
2024-05-15 09:52:02 +03:00
Vladimir Enchev
2907403f82 Version updated 2024-05-13 18:06:06 +03:00
Vladimir Enchev
9a735639d4 DataGrid crosstab example added 2024-05-13 12:00:10 +03:00
Vladimir Enchev
375e3c4636 SecurityCode backspace support added 2024-05-13 09:41:31 +03:00
Vladimir Enchev
ab3d7078bf demo updated 2024-05-10 16:09:06 +03:00
Vladimir Enchev
3b191b917b Tree drag & drop demo added 2024-05-10 15:46:57 +03:00
Vladimir Enchev
4be129917a DataGrid group should not be collapsed if set Expanded = true in GroupRowRender 2024-05-09 16:18:22 +03:00
Vladimir Enchev
507f508497 demo fixed 2024-05-09 15:20:41 +03:00
Vladimir Enchev
4b063b3493 Drag row between two DataGrids demo added 2024-05-09 10:43:46 +03:00
Vladimir Enchev
8e457a20bc DataGrid rows reorder demo updated 2024-05-08 18:28:31 +03:00
Vladimir Enchev
b9716cf2a3 DataGrid rows reorder demo added 2024-05-08 17:10:24 +03:00
Vladimir Enchev
b05a4ab83a version updated 2024-05-08 09:32:41 +03:00
Vladimir Enchev
ca75eb651d Fixed DropDownDataGrid steal focus in some cases 2024-05-08 09:32:17 +03:00
Vladimir Enchev
a6329fd3c0 Numeric and Android SecurityCode input improved 2024-05-07 12:11:30 +03:00
Atanas Korchev
89e33e984b Use the Culture set for RadzenScheduler when displaying the month name in year view. 2024-05-07 10:19:55 +03:00
Atanas Korchev
40c0b85a10 Use the Culture set for RadzenScheduler when displaying the title of the "More" dialog in month view. 2024-05-07 10:13:25 +03:00
Vladimir Enchev
7cdb199855 MaxFileCount default value changed to 10 2024-05-07 10:05:39 +03:00
Vladimir Enchev
8c165dc17f Upload MaxFileCount property added 2024-05-07 09:55:55 +03:00
Vladimir Enchev
43fe21a87d version updated 2024-05-06 17:50:19 +03:00
Vladimir Enchev
4b7559f2ec Various button title and aria-label attributes added 2024-05-06 16:52:29 +03:00
Vladimir Enchev
9e026034d7 DropDownBase EmptyAriaLabel property added 2024-05-06 16:24:10 +03:00
Vladimir Enchev
9466ccb12a Fixed "Anchor element found with no link content and no name and/or ID attribute." accessibility error 2024-05-06 11:09:57 +03:00
Vladimir Enchev
f53f314f0b Title set to DataGrid advanced filter apply and clear buttons 2024-05-06 09:59:30 +03:00
Vladimir Enchev
9b53a3a052 various input attributes added 2024-05-06 09:32:14 +03:00
Vladimir Enchev
7f8a95646a Fixed error in RadzenDataGrid FilterMode="FilterMode.CheckBoxList"
Fix #1498
2024-05-06 09:21:58 +03:00
Paul Ruston
88d452a9fa Don't set filterOperator if Custom (#1497) 2024-05-03 17:45:55 +03:00
Vladimir Enchev
ee2e1412d6 Version updated 2024-05-02 08:42:54 +03:00
melfon
f2ea6af1c3 Uses pointer event instead of mouse event to track splitter movements (#1496)
Co-authored-by: Tomas Wiell <tomas.wiell@scientaomicron.com>
2024-05-02 08:41:47 +03:00
Vladimir Enchev
76bd5d7518 DropDownBase indexer property binding imporved 2024-05-02 08:33:46 +03:00
Vladimir Enchev
70626ccb79 DropDownDataGrid should check column Type 2024-05-02 08:07:10 +03:00
Vladimir Enchev
124fca6d1f DropDownDataGrid selected row not cleared on value clear 2024-05-01 09:31:56 +03:00
Vladimir Enchev
37154cc1ef Version updated 2024-04-30 19:53:19 +03:00
Vladimir Enchev
9f42ad5746 DropDownDataGrid binding to dynamic data demo added 2024-04-30 19:53:00 +03:00
Vladimir Enchev
94c19c8724 DataGrid SetFilterValue for enums fixed
Fix #1493
2024-04-30 19:06:26 +03:00
Atanas Korchev
c3dd9a5f14 Uploading an image when UploadUrl is not set would insert the image as base64 encoded data. 2024-04-30 15:06:38 +03:00
yordanov
8f2a6acb7b Update DropZone demos 2024-04-30 09:37:19 +03:00
Vladimir Enchev
821817fc89 DropZone component added (#1492)
* DropZone component added

* DropZone and DropZoneItem rendering improved

* rz-can-drop/rz-no-drop css classes added

* Update DropZone styles and demo

* dragCssClass added

* Update DropZone styles and demo

* Update premium themes

* Update navigation items

* DropZoneCanDropNoDropStyles  demo added

* item styles added

* Allow drop over zone no matter if has items

* Update styles in DropDzone demos

* Use dragover instead dragenter to apply css class

---------

Co-authored-by: yordanov <vasil@yordanov.info>
2024-04-30 09:08:46 +03:00
Vladimir Enchev
0f3097590f Version updated 2024-04-29 16:18:04 +03:00
Vladimir Enchev
20826fff54 Drag and drop files to upload demo added 2024-04-29 14:39:31 +03:00
Vladimir Enchev
9067e1d8d1 Fixed Cast() exception with DataGrid FilterMode CheckBoxList 2024-04-29 13:32:52 +03:00
Vladimir Enchev
dbf983e287 DataGrid should not render <col> element for group expand column when ShowGroupExpandColumn=false
Fix #1490
2024-04-29 10:16:38 +03:00
Vladimir Enchev
f81043133a RadzenCompareValidator ValidateOnValueChange property added
Fix #1487
2024-04-29 10:04:02 +03:00
Vladimir Enchev
cab9b0bd1e Fixed DataGrid initial enum filter not selected in the filtering DropDown
Fix #1489
2024-04-29 09:28:08 +03:00
Vladimir Enchev
d9b42016dc Improved DataGrid grouping performance
Fix #1486
2024-04-26 09:30:59 +03:00
Vladimir Enchev
5ee5a23b29 Version updated 2024-04-25 10:06:07 +03:00
Vladimir Enchev
a1f33d93c1 Chart CartesianSeries DateOnly exception fixed
Fix #1484
2024-04-25 10:05:04 +03:00
Vladimir Enchev
1f9a19c37a Fixed virtualized DropDown null ref. exception on ENTER key press
Fix #1483
2024-04-24 19:23:51 +03:00
Vladimir Enchev
9e9d371a3f Version updated 2024-04-24 11:25:09 +03:00
Vladimir Enchev
b97136a606 Issue drag scrolling Dialog content on mobile after moving dialog
Fix #1480
2024-04-24 11:23:43 +03:00
Vladimir Enchev
f1df463a07 RadzenDropDown SelectedItemChanged keeps repeating forever
Fix #1479
2024-04-24 10:58:45 +03:00
Vladimir Enchev
e59c335cac DataGrid dynamic data demo updated with enum 2024-04-24 10:50:32 +03:00
Vladimir Enchev
a9280edf97 Version updated 2024-04-23 19:03:43 +03:00
Vladimir Enchev
68eca70a31 version updated 2024-04-23 19:01:39 +03:00
Vladimir Enchev
dd68c35295 DataGrid ungrouping in virtualized mode throws error 2024-04-23 19:01:16 +03:00
Vladimir Enchev
57530af792 DateOnly supported added to DataGrid component
Fix #1478
2024-04-23 10:32:32 +03:00
Vladimir Enchev
4947fa91ef Column FormatString used for Excel filter 2024-04-22 18:51:51 +03:00
Vladimir Enchev
c605cc77d5 GetFilterValues() improved 2024-04-22 18:51:29 +03:00
Vladimir Enchev
6fe6b681ac DataGrid FilterMode.CheckBoxList (Excel like) filtering added 2024-04-22 18:51:03 +03:00
Vladimir Enchev
08884af624 Version updated 2024-04-22 17:15:39 +03:00
Vladimir Enchev
2adfbb5169 Revert "Implement OpenPopup and ClosePopup Events for Radzen Dropdown (#1471)" (#1477)
This reverts commit f6e05a27d8.
2024-04-22 14:10:47 +03:00
Atanas Korchev
831c3c4fa4 Column and bar radius is not applied in some cases. Fixes #1464. 2024-04-22 12:52:19 +03:00
Vladimir Enchev
df87b51e63 ClosePopup() renamed to PopupClose 2024-04-22 11:03:41 +03:00
Atanas Korchev
a17fceac39 Stacked bar and column series do not work with negative values. Closes #1475. 2024-04-22 10:58:24 +03:00
luis507pty
f6e05a27d8 Implement OpenPopup and ClosePopup Events for Radzen Dropdown (#1471)
* Add Parameters OnOpenPopup and OnClosePopup to handler events

* Add CheckAndTriggerPopupStateChange method

* Add RadzenDropDown Action Methods OnOpenPopup And  OnClosePopup.

* Radzen.closePopup send DotNetObjectReference

* -Use EventCallBack
- Change property name OnOpenPopu to OpenPopupCallback
- Change property name OnClosePopup to ClosePopupCallback

* validate and invoke delegate

* -Change name the internal method OpenPopup to TogglePopup

---------

Co-authored-by: Desarrollador 04 04 <develop04@smrey.com>
2024-04-22 10:27:19 +03:00
Atanas Korchev
19cb4ee7a4 Stacked area series do not support negative values. 2024-04-22 10:23:52 +03:00
Vladimir Enchev
8d4f853432 Pager aria-current attribute added for current page 2024-04-19 11:17:15 +03:00
nielsNocore
76eaac5d31 add ability to add custom button content to a split button (#1470) 2024-04-19 09:46:43 +03:00
Atanas Korchev
5c02943ab3 Clicking a link in RadzenHtmlEditor sometimes navigates. Closes #1467. 2024-04-19 09:43:13 +03:00
Atanas Korchev
09a38e2dcd Exception is thrown when updating the data of pie or donut series and a tooltip is shown. 2024-04-19 09:29:20 +03:00
Vladimir Enchev
4a772953dd DropDownBase SelectedItemChanged changed from Action to EventCallback 2024-04-18 15:07:47 +03:00
Vladimir Enchev
be544e09cf Version updated 2024-04-18 11:52:24 +03:00
Vladimir Enchev
8a817980db Draggable requires single touch to start drag after first drag end
Fix #1469
2024-04-18 11:49:56 +03:00
Vladimir Enchev
1dbfbe5d5f Tab cannot be selected in some cases when TabRenderMode.Client after add/remove
Fix #1466
2024-04-18 10:47:55 +03:00
Vladimir Enchev
53ed0dc12d RadzenDropDownDataGrid is not displaying empty text
Fix #1465
2024-04-18 09:57:52 +03:00
nielsNocore
1bbff65f5d add method to collapse all items, which allow collapse all rows in a datagrid, whithout iterating all items in the page. (#1468)
small refactoring duplicate code to correctly collapse an aitem.
2024-04-18 09:49:44 +03:00
Vladimir Enchev
8e5e9ab517 CascadingTypeParameter added for DataFilter, DataList, DataGrid and TemplateForm components 2024-04-17 15:41:15 +03:00
yordanov
c2d37932e1 Replace padding in Scheduler's view header with auto scroll width 2024-04-16 17:33:00 +03:00
Vladimir Enchev
7e7bbd4591 Pager navigate to page with ENTER/SPACE index fixed 2024-04-15 14:28:05 +03:00
Vladimir Enchev
6d2d3c4c3b Version updated 2024-04-15 13:19:40 +03:00
yordanov
a1ba7f9e5f Pager focus styles should be visible only when needed 2024-04-12 12:57:49 +03:00
yordanov
b89949e361 Fix disabled state of DatePicker in FormField 2024-04-11 14:52:40 +03:00
yordanov
72ad111198 Remove redundant border property 2024-04-11 14:28:35 +03:00
yordanov
00b4e9a9b4 Fix disabled state of buttons in Upload and FileInput 2024-04-11 12:55:06 +03:00
Vladimir Enchev
a460fe12a1 DropDownBase should not loose focus on select all 2024-04-10 16:15:58 +03:00
yordanov
7e4fdcd9a3 Update Scheduler responsive styles. Adds container media queries and resolves #1445 2024-04-10 16:11:12 +03:00
Vladimir Enchev
0f4d06b4d4 Version updated 2024-04-10 10:26:39 +03:00
Marat Chiraev
bfbf6edc87 Fixed a bug where it was possible to apply a filter on an empty string (#1458) 2024-04-10 10:21:15 +03:00
Vladimir Enchev
5027e2f03a TextBox, TextArea and Password components will unable to show ContextMenu if Name is set 2024-04-10 10:20:25 +03:00
yordanov
70ea05c0ca Hide clear icon in disabled DropDown and DatePicker and unify disabled color of trigger icon 2024-04-09 18:06:15 +03:00
yordanov
5e9d9abe10 Fix DropDown and DatePicker icon and text colors in disabled and hover states 2024-04-09 17:36:19 +03:00
Vladimir Enchev
128495dd91 Version updated 2024-04-09 16:43:08 +03:00
Stefan
314a8c0741 Make MaxLength a parameter (#1456) 2024-04-09 08:59:08 +03:00
Vladimir Enchev
8c6ca6f8f7 PickList invalid cast exception fixed 2024-04-09 08:58:33 +03:00
yordanov
421bb3b701 Fix layout of SelectBar bind value demo 2024-04-08 15:47:59 +03:00
Vladimir Enchev
a8e9ef49f4 Fixed RadzenDropDown EnterKey ArgumentOutOfRangeException 2024-04-08 15:35:53 +03:00
Vladimir Enchev
2474ad8d1d Version updated 2024-04-08 15:15:51 +03:00
Vladimir Enchev
dd58ac01ed DataGrid simple filter mode by string properties fixed 2024-04-08 15:15:40 +03:00
Vladimir Enchev
fd4fc377a1 Version updated 2024-04-08 11:26:20 +03:00
Vladimir Enchev
3b31cec3e7 DataGrid will clear column filters on escape and will not allow set or filter value if empty operator type is selected
Close #1454
2024-04-08 10:08:49 +03:00
Vladimir Enchev
28fc95dd1f DataGrid Reset() should not call SaveSettings() 2024-04-08 09:28:16 +03:00
Vladimir Enchev
d7dc51980a Version updated 2024-04-04 09:41:44 +03:00
Vladimir Enchev
1fd1f08f33 DataGrid LoadSettings event should mark Settings as changed 2024-04-04 09:28:47 +03:00
Vladimir Enchev
f43ec50369 Update DataGridColumnResizingPage.razor 2024-04-03 17:12:06 +03:00
Vladimir Enchev
d4b6b5744d DatePicker will show popup when clicking on input field when AllowInput set to false
Fix #1449
2024-04-02 21:30:24 +03:00
Vladimir Enchev
3ae9ddf0f9 Version updated 2024-03-29 18:05:03 +02:00
Vladimir Enchev
4a61e5cbdb Fixed DropDownBase display description 2024-03-29 18:04:55 +02:00
Vladimir Enchev
44b031af15 Version raised 2024-03-29 13:47:07 +02:00
Vladimir Enchev
ad197f85de Version updated 2024-03-29 13:44:57 +02:00
Atanas Korchev
e7c2990b79 RadzenCompareValidator throws error when put inside RadzenFormField. 2024-03-29 12:40:25 +02:00
Vladimir Enchev
21aa33c862 demo updated 2024-03-29 10:50:40 +02:00
Vladimir Enchev
3f8cd143b6 Tree TreeItemRender event added 2024-03-28 19:06:30 +02:00
Vladimir Enchev
5d25fec242 Version updated 2024-03-28 16:13:21 +02:00
yordanov
8aec9f3f25 Update premium themes 2024-03-28 15:33:28 +02:00
Vladimir Enchev
81d14cbecc Selection in Dialog title disabled 2024-03-28 14:50:25 +02:00
Vladimir Enchev
6f1f4cc576 DropDownBase will fallback to PropertyAccess.GetItemOrValueFromProperty() if strongly typed property getters are not initialized 2024-03-28 14:35:55 +02:00
Vladimir Enchev
f81be0a075 RadzenCompareValidator should not validate on first render
Fix #1446
2024-03-28 14:29:00 +02:00
Vladimir Enchev
2aa57404f2 Close of nested popups fixed 2024-03-28 14:11:23 +02:00
Vladimir Enchev
d43cb4b097 Version updated 2024-03-27 16:38:17 +02:00
Vladimir Enchev
7d69100d2d DatePicker Disabled change not working properly when inside FormField 2024-03-27 16:37:58 +02:00
Vladimir Enchev
c04a975dba CompareValidator Value change logic improved 2024-03-27 10:46:56 +02:00
Vladimir Enchev
59f920445c CompareValidator should be revalidated on Value change 2024-03-27 10:28:48 +02:00
Marcel Siegel
72425b243b avoid add invalid items in InsertInCurrentItems (#1442)
Co-authored-by: Marcel Siegel <marcel@siegelnet.de>
2024-03-27 08:57:02 +02:00
MitchKuijpers
8af777fac4 Made it so the ValueTemplate will also be applied when using multiselect. (#1441) 2024-03-27 08:56:30 +02:00
yordanov
510d94b21c Tabs selected color and bg color should be applied to the same element. Addresses comments in #1303 2024-03-26 18:26:14 +02:00
Vladimir Enchev
476cfec461 Version updated 2024-03-26 11:29:16 +02:00
Vladimir Enchev
642869ffed PickList buttons disabled state fixed 2024-03-26 11:29:07 +02:00
Vladimir Enchev
4e6a552689 Version updated 2024-03-26 11:03:20 +02:00
Vladimir Enchev
707581f103 PickList invalid cast exception when selecting all items in multiple mode 2024-03-26 11:03:03 +02:00
Vladimir Enchev
ef68d43acb TextBox, Mask and Numeric aria-autocomplete custom attribute value support added
Close #1440
2024-03-26 09:50:16 +02:00
Vladimir Enchev
50f15f7539 RadioButtonListItem InputAttributes added 2024-03-25 15:45:30 +02:00
Vladimir Enchev
9f2ae92236 DatePicker popup should be destroyed only on Visible property change 2024-03-25 15:37:21 +02:00
Vladimir Enchev
854f14a014 version updated 2024-03-25 10:53:23 +02:00
Elias-Constantin Regber
cdeef6aae0 Fix (#1438) 2024-03-25 09:48:17 +02:00
Vladimir Enchev
5000a56620 Fixed wrong Tabs item selected after visible change when TabRenderMode.Client 2024-03-25 09:24:39 +02:00
Vladimir Enchev
e5438a7c37 DatePicker input will be focused on calendar tab key 2024-03-22 16:16:47 +02:00
Vladimir Enchev
ed984a0642 Version updated 2024-03-22 15:55:48 +02:00
Vladimir Enchev
077c88b778 upload demo layout improved 2024-03-22 15:55:24 +02:00
Vladimir Enchev
2077b0a35f Upload component support for client-side file read added (#1439)
* Upload component support for client-side file read added

* maxFileSize defined

* stream closed
2024-03-22 15:45:53 +02:00
Vladimir Enchev
8cbffd7c11 DatePicker keyboard navigation fixed 2024-03-22 15:36:20 +02:00
Vladimir Enchev
3bc3038c2f DatePicker should not focus first element in popup when opened from input 2024-03-22 10:31:22 +02:00
yordanov
ee3c54ecd0 Fix RadzenListBox and DropDown multiple selection item content not stretching to full width 2024-03-21 17:42:24 +02:00
Atanas Korchev
89b10a8ccf Pass the ListBox template directly to reduce duplication. 2024-03-21 13:16:59 +02:00
Atanas Korchev
31d702c550 Use latest available C# version. 2024-03-21 13:16:07 +02:00
warpor
a5f98cb46b Add the ability to change the text in the scheduler (#1434)
Add ability to change the popup text when clicking on a day with no events on the scheduler in year view
2024-03-21 13:05:45 +02:00
V45370
b88156a672 Scheduler drag and drop with mobile support (#1395)
* Appointment drag and drop functionality for Scheduler component.

* Added drag support for mobile devices.

* Remove DragDropTouch.js.

* Remove touch events. Set ondragstart as an attribute (required for mobile support).

* Remove some views.

---------

Co-authored-by: Atanas Korchev <akorchev@gmail.com>
2024-03-21 13:03:20 +02:00
Atanas Korchev
311a53e4ce Create SECURITY.md 2024-03-21 10:34:14 +02:00
Vladimir Enchev
bd55bb88b9 Version updated 2024-03-21 10:09:36 +02:00
Vladimir Enchev
7461c5ee1f SecuritCode FocusAsync fixed 2024-03-21 10:07:06 +02:00
Vladimir Enchev
6daf5b6afa SecurityCode OnValueChange should be invoked on paste 2024-03-20 21:07:26 +02:00
Vladimir Enchev
32c9678513 code improved 2024-03-20 21:03:19 +02:00
Vladimir Enchev
2f74296de6 Fixed RadzenSecurityCode form support 2024-03-20 20:23:37 +02:00
Vladimir Enchev
2d32d53075 Assembly version used for Radzezn.Blazor.js 2024-03-20 11:40:41 +02:00
Vladimir Enchev
9fa389bb99 Version updated 2024-03-20 10:30:32 +02:00
Vladimir Enchev
c9151306da DatePicker focused date not updated properly when interacting with mouse
Fix #1429
2024-03-20 10:29:45 +02:00
Vladimir Enchev
5d11777dd8 DatePicker PopupID will use id attribute of the component if set
Fix #1430
2024-03-20 10:17:45 +02:00
Vladimir Enchev
eab9ced72f Added support for SelectedIndex two-way binding to Accordion 2024-03-19 13:52:44 +02:00
Vladimir Enchev
929a72be79 obsolete code deleted 2024-03-19 12:50:52 +02:00
Vladimir Enchev
c62c8d338e SecurityCode should not update value if not needed 2024-03-19 12:43:06 +02:00
Vladimir Enchev
524af22cb0 summary fixed 2024-03-19 11:14:41 +02:00
Vladimir Enchev
b7f891ce39 Version updated 2024-03-19 11:11:33 +02:00
Vladimir Enchev
178a20c6d4 Custom autocomplete attribute support added to TextBox, Mask, Password and Numeric. AutoComplete properties reverted to boolean. 2024-03-19 11:11:11 +02:00
Vladimir Enchev
83e13ae782 SecurityCode input lost value if same value is entered 2024-03-18 18:05:02 +02:00
Vladimir Enchev
dc654b89fb version updated 2024-03-18 15:27:50 +02:00
yordanov
bee2e084ba Fix height of PickList target wrapper 2024-03-18 15:21:11 +02:00
yordanov
9ea3f9fd80 Update SecurityCode styles 2024-03-18 14:54:22 +02:00
Vladimir Enchev
5d78740f6f PickList ButtonJustifyContent default value set to Center 2024-03-18 14:31:13 +02:00
Vladimir Enchev
9cda942dea number of components updated 2024-03-18 14:23:05 +02:00
Atanas Korchev
2b728114a2 Change the rendering of RadzenStackedAreaSeries to no longer require RenderingOrder and cause overlaps. 2024-03-18 12:20:34 +02:00
Vladimir Enchev
6f1ab140a6 Version updated 2024-03-18 12:17:35 +02:00
Vladimir Enchev
8655349f00 Tab should not close DropDownDataGrid if on search input or search and add buttons
Fix #1426
2024-03-18 12:17:19 +02:00
Vladimir Enchev
d75edae498 Fixed DataGrid column resize sticking on after click
Close #1425
2024-03-18 11:50:18 +02:00
Vladimir Enchev
6d5970adcb SecurityCode component added (#1428)
* SecurityCode component added

* Methods for create/destroy SecurityCode improved

* Bind value demo added for SecurityCode

* SecurityCode will use space instead empty string for invalid value

* SecurityCode will use size=1 for inputs instead width

* text-align: center added for .rz-security-code-input

* padding: 0.3rem added to .rz-security-code-input

* Update SecurityCode styles

* Update SecurityCode demos

---------

Co-authored-by: yordanov <vasil@yordanov.info>
2024-03-18 11:38:10 +02:00
Vladimir Enchev
40f925e660 DatePicker will not use online scripts to open/close popup
Close #1427
2024-03-18 11:35:09 +02:00
Atanas Korchev
d9aab7db19 Update chart demos. 2024-03-15 19:00:20 +02:00
Vladimir Enchev
6f7a12c8be Splitter runtime size not updated on Size change 2024-03-15 16:27:17 +02:00
Vladimir Enchev
48d7d5a0b9 TextBox, Mask, Password, Numeric and Login components AutoComplete property made dynamic to allow custom string values
Close #1424
2024-03-15 12:09:22 +02:00
Vladimir Enchev
d459270d7d Fixed DataGrid with virtualization crashes when ungrouping 2024-03-15 10:54:30 +02:00
Vladimir Enchev
9e7a7ad920 Added aria-hidden="true" to CheckBoxList label 2024-03-15 10:01:27 +02:00
Vladimir Enchev
ffcd3aa3c2 Version updated 2024-03-14 19:21:44 +02:00
Vladimir Enchev
ecd933f94a Splitter mask not removed after first resize 2024-03-14 19:21:09 +02:00
Vladimir Enchev
9db8365930 Version updated 2024-03-14 14:33:46 +02:00
Vladimir Enchev
64187169a0 PickList component added (#1423)
* PickList component added

* Properties Buttons* changed to Button*

* PickList Multiple property added

* PickList ButtonJustifyContent added

* PickList demo improved

* PickList single selection fixed

* PickList SourceStyle and TargetStyle properties removed

* PickList buttons updated

* PickList main Stack Wrap set to FlexWrap.Wrap

* Wrap="FlexWrap.Wrap" removed

* PickList Multiple set to false by default

* PickList reworked to not use directly Source and Target parameter properties

* Update PickList demo

* Add PickList styles

* PickList Orientation property added

* Orientation bound

* Buttons Stack Orientation will depend on Orientation

* Update PickList styles

* Update PickList item in demos navigation

* PickList changing Multiple should reset selection

* Update premium themes

---------

Co-authored-by: yordanov <vasil@yordanov.info>
2024-03-14 14:30:07 +02:00
Vladimir Enchev
f016ba700c AutoComplete in RadzenTextBox not always working
Fix #1422
2024-03-12 18:37:38 +02:00
Vladimir Enchev
02076b680e Splitter mask added during resize to avoid problems with frames 2024-03-12 18:30:49 +02:00
Vladimir Enchev
a6e16ad99f file updated 2024-03-12 17:22:24 +02:00
Vladimir Enchev
3f2de363c9 Splitter IsResizing property added 2024-03-12 16:51:27 +02:00
Vladimir Enchev
511d8d0cb4 Version updated 2024-03-12 16:12:50 +02:00
Markus Lenz
4798d6b7e5 Correct using scheduler year view rz-other-month class (#1421) 2024-03-12 15:26:04 +02:00
Vladimir Enchev
47775d2758 DataGrid column HeaderTemplate should not propagate keydown event 2024-03-12 15:12:08 +02:00
Vladimir Enchev
789e22ea08 DataGrid RowSelect not raised when selecting a row with SPACE or ENTER keys 2024-03-11 18:25:58 +02:00
Vladimir Enchev
fb8badbfd9 RadzenSteps are not shown anymore, after hiding using Visible
Fix #1420
2024-03-11 15:09:17 +02:00
Vladimir Enchev
1c36f33a69 Potential null ref. exception fixed 2024-03-11 09:20:21 +02:00
Vladimir Enchev
58dd31611d Version updated 2024-03-11 09:02:07 +02:00
Vladimir Enchev
7d9033a212 Infinite reload loop in RadzenDataGrid with empty data when AllowVirtualization is true and Settings are applied.
Fix #1416
2024-03-11 09:01:34 +02:00
Vladimir Enchev
564255978d Null. ref. exception fixed 2024-03-09 09:50:53 +02:00
Vladimir Enchev
cc87b603fb unused code removed 2024-03-09 09:46:22 +02:00
Vladimir Enchev
118a0b4214 demo updated 2024-03-08 13:24:27 +02:00
Vladimir Enchev
b56580e3d1 DropDown will focus item starting with typed key 2024-03-08 11:12:38 +02:00
Vladimir Enchev
2a1b77ff6b Update RadzenDropDownDataGrid.razor.cs
NumpadEnter support added
2024-03-07 19:56:49 +02:00
Vladimir Enchev
d94a54e392 Update DropDownBase.cs
Fix #1415
2024-03-07 19:53:52 +02:00
Vladimir Enchev
1ab5db3183 version updated 2024-03-07 10:58:56 +02:00
Vladimir Enchev
560348fcfe Virtualized DropDownDataGrid not properly refreshed after search when scrolled 2024-03-07 10:56:43 +02:00
Vladimir Enchev
e9f74bfb4d DataGrid save/load settings will handle composite columns as well
Close #1412
2024-03-07 10:16:30 +02:00
Vladimir Enchev
13eec1c31a DataGrid keyboard navigation will scroll into view focused row/cell only if needed 2024-03-07 09:42:26 +02:00
Vladimir Enchev
aa64ca58f4 DataGrid columns state should not be reset on Data change if AllowColumnPicking, AllowColumnReorder or AllowColumnResize is true 2024-03-07 09:09:36 +02:00
Vladimir Enchev
018c3a1cc6 Filter by CompanyName added to demos 2024-03-05 16:48:42 +02:00
Vladimir Enchev
e0bf4394b7 DropDown virtualization with LoadData demo code imroved 2024-03-05 15:30:16 +02:00
Vladimir Enchev
d684a3ede2 DropDownDataGrid virtualization with LoadData demo code imroved 2024-03-05 15:25:22 +02:00
Vladimir Enchev
0bb1ab04d3 Version updated 2024-03-05 13:44:05 +02:00
Vladimir Enchev
f35f5ccfe4 Dialog mask will not receive pointer events only when CloseDialogOnOverlayClick=false 2024-03-05 13:43:33 +02:00
Vladimir Enchev
dc58737310 DataGrid column CustomFilterExpression inluded in save/load settings
Close #1408
2024-03-05 11:23:39 +02:00
Vladimir Enchev
f246415f27 Dialog mask should not receive mouse events 2024-03-05 11:17:58 +02:00
nielsNocore
e7badbf124 DatePicker add specific css selectors for week number (#1409)
* added specific scss selector for week number in the date picker
added unittest for the week number in date picker

* restored existing class name for calendarweeks for beter compatibility
made unit test more specifick to test the week number class name
2024-03-05 11:11:43 +02:00
Vladimir Enchev
caddb16b53 Input from the keyboard freezes inside RadzenLayout
Fix #1399
2024-03-05 11:11:03 +02:00
Vladimir Enchev
0d18206ae6 DatePicker Close() not working
Fix #1410
2024-03-05 10:03:37 +02:00
Vladimir Enchev
71c82c0f0d version updated 2024-03-04 06:41:45 +02:00
Vladimir Enchev
cc52fdcf5a RadzenDatePicker (Inline) throws error after picking date
Fix #1405
2024-03-04 06:40:21 +02:00
Marek
6d31991fda feat: ClearFilter has optional parameter should reload (#1398)
Co-authored-by: MICKA Marek (Cloud EXT ADM) <adm.cloud.ext.micka@drmaxglobal.onmicrosoft.com>
2024-03-04 07:08:15 +03:00
Vladimir Enchev
7988f8cc1b Update RadzenDatePicker.razor.cs 2024-03-01 17:05:24 +03:00
Vladimir Enchev
59366d6f33 Version updated 2024-02-29 11:20:50 +02:00
Marek
4f7970cb0e fix: filter icon styl (#1397)
Co-authored-by: MICKA Marek (Cloud EXT ADM) <adm.cloud.ext.micka@drmaxglobal.onmicrosoft.com>
2024-02-29 10:53:57 +02:00
Vladimir Enchev
5794b2e977 DataGrid should use In filter operator as default when FilterProperty is different from Property 2024-02-29 10:49:37 +02:00
Vladimir Enchev
291feff903 demo updated 2024-02-28 16:05:05 +02:00
Vladimir Enchev
19ce81e995 OrderDate filter not auto applied
Fix #1396
2024-02-28 15:49:19 +02:00
Vladimir Enchev
4b20d5b954 Tabs focus should excluded non visible tabs 2024-02-28 14:06:38 +02:00
Vladimir Enchev
90221a0e16 Version updated 2024-02-28 09:41:04 +02:00
Vladimir Enchev
085036bc93 DataGrid inserted row not validated when there is already edited item in multiple edit mode 2024-02-28 09:40:42 +02:00
Vladimir Enchev
21186d0858 Tab focused state not removed from previous selected/focused tab in server render mode 2024-02-28 09:23:08 +02:00
Vladimir Enchev
22e8d15f60 DataGrid PageUp/Down/Home/End support added for keyboard navigation when virtualized 2024-02-27 16:17:31 +02:00
Vladimir Enchev
f258e6d17f DatePicker with TimeOnly crashes on 00:00 value
Fix #1394
2024-02-27 15:05:29 +02:00
Vladimir Enchev
a6a4185585 Update RadzenDropDownDataGrid.razor.cs 2024-02-27 14:15:59 +02:00
Vladimir Enchev
9924a574a8 DropDownDataGrid will force inner DataGrid refresh on popup open if virtualized 2024-02-27 11:17:01 +02:00
Vladimir Enchev
7282d02c22 Cannot tab out from DropDownDataGrid after ESC or ENTER 2024-02-26 15:44:24 +02:00
Vladimir Enchev
1ea62c3c60 Version updated 2024-02-26 11:09:06 +02:00
Vladimir Enchev
5929a37d73 scrollIntoViewIfNeeded should not be used when virtual 2024-02-26 11:07:43 +02:00
Vladimir Enchev
f4a0ec30ec DataGrid keyboard navigation with virtualization improved 2024-02-26 11:01:42 +02:00
yordanov
c5c1e3c1ca Fix ProfileMenu bullet points in Safari 2024-02-26 10:47:17 +02:00
Vladimir Enchev
449c74eb66 Fixed various keyboard navigation problems in Firefox 2024-02-26 09:57:54 +02:00
yordanov
016717c8ef Fix day focused state in DatePicker 2024-02-26 09:20:31 +02:00
Marek
75bb80d343 chore: double iteration removed (#1390)
Co-authored-by: MICKA Marek (Cloud EXT ADM) <adm.cloud.ext.micka@drmaxglobal.onmicrosoft.com>
2024-02-26 09:00:34 +02:00
Krystian Szatan
c04c32e876 EventConsole - optional AlertStyle (#1391)
Now can log warnings, errors etc.
2024-02-26 08:59:16 +02:00
Vladimir Enchev
09025e0a8f DatePicker Value property setter comparing old and new value fixed 2024-02-26 08:54:53 +02:00
Vladimir Enchev
13e845a5da Version updated 2024-02-23 15:18:11 +02:00
Vladimir Enchev
2f4284f806 Fixed exception in TreeView expand/collapse
Fix #1389
2024-02-23 15:17:49 +02:00
Vladimir Enchev
d4af5926cb PanelMenu item not expanded on reload if selected 2024-02-23 14:51:05 +02:00
Vladimir Enchev
0ad2f463ab Fixed DatePicker focus lost on selection 2024-02-23 09:29:20 +02:00
Vladimir Enchev
3b49f9947f Fixed select all of unbound DropDown
Close #1388
2024-02-23 09:23:13 +02:00
Vladimir Enchev
514b536f57 Version updated 2024-02-22 16:39:34 +02:00
Vladimir Enchev
040143f557 Open menu on ArrowDown 2024-02-22 15:27:55 +02:00
Vladimir Enchev
c75d0cc989 Menu Toggle() and Close() methods fixed 2024-02-22 15:15:56 +02:00
yordanov
701ac3f85d Fix anchors 2024-02-22 14:41:24 +02:00
yordanov
f283cff6bc Add info for HighContrast color swatches 2024-02-22 14:40:12 +02:00
Vladimir Enchev
d8e62cc541 Tab focused state not removed from previous selected/focused tab properly 2024-02-22 14:36:32 +02:00
Vladimir Enchev
8853c8a124 version updated 2024-02-22 11:26:28 +02:00
Vladimir Enchev
027fa4119b Various components templates should not propagate keydown 2024-02-22 11:25:52 +02:00
Vladimir Enchev
5424375e0d Accordion templates should not propagate keydown 2024-02-22 11:08:14 +02:00
Vladimir Enchev
6007658c72 DataGrid special rows should not propagate keydown 2024-02-22 10:40:48 +02:00
Vladimir Enchev
e0916858a8 DataGrid filter row should not propagate onkeydown 2024-02-22 09:17:54 +02:00
Vladimir Enchev
1f397978d6 code fixed 2024-02-21 15:35:21 +02:00
Vladimir Enchev
518f58885e version updated 2024-02-21 15:30:08 +02:00
Vladimir Enchev
ece24fa24b RadzenAccordion item role fixed 2024-02-21 15:25:01 +02:00
Vladimir Enchev
6524eb2b55 Version updated 2024-02-21 14:55:00 +02:00
rauschp
b16a6b1ab1 Allow the icon in the ProfileMenu to be enabled/disabled (#1380)
* Add toggleable icon to the Profile menu

* Update the summary to better reflect the name

---------

Co-authored-by: Peter Rausch <peter@Peters-Air.attlocal.net>
2024-02-20 18:52:13 +02:00
Vladimir Enchev
cda2ca43dd demo fixed 2024-02-20 18:46:14 +02:00
Vladimir Enchev
3375d30fad tabindex set for various buttons 2024-02-20 18:26:41 +02:00
yordanov
6b61c462a0 Update tooltip templates in demos config 2024-02-20 17:59:43 +02:00
Vladimir Enchev
226fab5904 test fixed 2024-02-20 16:26:07 +02:00
Vladimir Enchev
be2791462e Version updated 2024-02-20 16:20:25 +02:00
Vladimir Enchev
9b38e6cb8f Stop propagation of keydown event in DataGrid cells 2024-02-20 15:35:13 +02:00
Vladimir Enchev
bce7830b86 Version updated 2024-02-20 14:55:23 +02:00
yordanov
4e6a3311a4 Update premium themes 2024-02-20 12:59:18 +02:00
yordanov
f8c1c87b01 Update sidebar toggle focus styles 2024-02-20 12:28:06 +02:00
Vladimir Enchev
94c3ae6533 Upload Choose button focus fixed 2024-02-20 09:44:33 +02:00
Vladimir Enchev
8ca1ed17d4 DataGrid column HeaderTooltip property added 2024-02-20 09:14:40 +02:00
Vladimir Enchev
a645363091 demo reload fixed 2024-02-19 11:34:23 +02:00
Vladimir Enchev
7db3c29e14 MenuItem Close() and Toggle() methods made public
Fix #906
2024-02-19 11:14:53 +02:00
Vladimir Enchev
4c28475c0d Give the UI time to react 2024-02-19 11:07:30 +02:00
Vladimir Enchev
c509f17789 DropDown RemoveChipTitle property added
Fix #1357
2024-02-19 10:57:55 +02:00
Vladimir Enchev
6690ea7c0e Fix #1114 2024-02-19 10:46:29 +02:00
Vladimir Enchev
347942668d Keyboard navigation and accessibility improvements added to all components (#1379)
* Components keyboard navigation improved

* Tree CheckBox TabIndex set to -1

* DataGrid and Pager keyboard navigation section added to first demo

* DataFilter keyboard navigation info added to first page

* Tree keyboard navigation info added to first page

* Scheduler keyboard navigation info added to first page

* DropDownDataGrid keyboard navigation info added to first page

* DatePicker keyboard navigation info added to first page

* FileInput keyboard navigation info added to first page

* demo updated

* SplitButton keyboard navigation info added to first page

* Upload keyboard navigation info added

* Chart keyboard navigation info added to first page

* demo updated

* focusTableRow() fixed

* more focusTableRow() fixes

* even more focusTableRow() fixes

* Update Accessibility page content

* Update anchors in navigation components demos and add keyboard navigation shortcuts

* Update MainLayout

* Update Scheduler focus styles

* Update keyboard navigation wording

* Appointments focus improved

* Update and document HTMLEditor shortcuts

* Appointment focus improvements for week view

* Replace ripple's background transition with background-size

* focus contentView on enter

* focus View on enter

* persist selected theme

* YearPlannerView keyboard navigation improved

* YearTimelineView keyboard navigation improved

* months focus state fixed

* days navigation fixed

* code fixed

* ScrollIntoView added

* Update anchors in components demos

* Update Scheduler focus styles

* Update premium themes

---------

Co-authored-by: yordanov <vasil@yordanov.info>
2024-02-19 10:31:27 +02:00
Atanas Korchev
1a3643d6f8 The id attribute of RadzenMenuItem is rendered twice. 2024-02-15 13:02:40 +02:00
Atanas Korchev
0af64210c5 The style of RadzenMenuItem does not render. 2024-02-15 12:16:31 +02:00
Paul Ruston
7989b8eb0e Add ImageStyle Property to MenuItem / ContextMenu (#1373) 2024-02-14 11:47:58 +02:00
Vladimir Enchev
4d902a03ca version updated 2024-02-13 09:35:59 +02:00
Josh
8af5b826b2 ensure nullable DateOnly and TimeOnly are parsed properly (#1372) 2024-02-13 09:10:35 +02:00
Atanas Korchev
953b8e4fb2 Chart trends throw InvalidOperationException when used with empty series. 2024-02-12 09:50:31 +02:00
David Kohout
95c4af6f84 Support for multiple inserts in DataGrid (#1369)
* Added support for multiple inserts in DataGrid

* Demo page DataGridInLineEdit updates.

Now allows for multiple edits and inserts.
Fixed issue when row is in insert mode and user starts to edit older row
2024-02-12 09:13:52 +02:00
Paul Ruston
f2be35ee94 Scheduler changes to set a start month for year views (#1366)
* Scheduler changes for Year views to set start month when rendering

* Change test for start month from integer to Enum

* Move SchedulteStartMonth from Scheduler to appropriate Views.

* Variable and Enum changes.
2024-02-09 16:03:36 +02:00
Vladimir Enchev
056bc1af22 source code fixed 2024-02-09 15:08:26 +02:00
Vladimir Enchev
46501093ce DataGrid header cell width style applied twice 2024-02-09 09:38:29 +02:00
Vladimir Enchev
0344e3f633 demo code improved 2024-02-07 10:00:31 +02:00
Vladimir Enchev
7882607c6e code improved 2024-02-07 09:53:23 +02:00
Vladimir Enchev
684c02b1c5 Version updated 2024-02-07 09:39:49 +02:00
Eric McGaha
7d8889d045 #1362 - DataFilter operator not being set using AddFilter. (#1363) 2024-02-07 09:32:04 +02:00
Josh
a05b293582 Feature: DatePicker, support for DateOnly/TimeOnly types (#1364)
* support DateOnly binding, by converting when assigning to Value

* support for TimeOnly, by converting when assigning to Value

* sample for DateOnly/TimeOnly binding

---------

Co-authored-by: Josh H <josh@inventivecoders.com>
2024-02-07 09:27:01 +02:00
Vladimir Enchev
c37085a1c7 demo improved 2024-02-06 17:16:52 +02:00
Chris Vanstone
bb8d7e2339 Handle DateTimeOffset and DateTimeOffset? in GetFilterValue (#1355) 2024-02-06 16:19:36 +02:00
Paul Ruston
84c87d2dee DataGrid Column Custom Command Filter (#1354)
* DataGrid Column Custom Command Filter

* Adjustment to Linq command in demo

* Rename CustomFilterCommand to CustomFilterExpression

* Changed name of a couple of variables in demo to match expression / command change.
2024-02-06 15:20:46 +02:00
Vladimir Enchev
710566e817 DropDownDataGrid shows blank data after clearing selections
Fix #1353
2024-02-06 09:31:30 +02:00
Vladimir Enchev
a1ca96017c version updated 2024-02-01 16:59:58 +02:00
Vladimir Enchev
686868519c Fixed virtualized DropDown with LoadData will not load items after clear
Fix #1352
2024-02-01 11:52:38 +02:00
yordanov
f16f0e7e08 Update premium themes 2024-02-01 10:17:48 +02:00
yordanov
f96bf404e6 Remove local source paths for Material fonts 2024-01-31 13:45:10 +02:00
Vladimir Enchev
6d6a80dd4d Collapsible RadzenFieldset IconColor fixed 2024-01-30 18:12:34 +02:00
Vladimir Enchev
94532e8598 version updated 2024-01-30 10:55:11 +02:00
Vladimir Enchev
254449ec1a RadzenNumeric does not respect step parameter properly in German culture
Fix #1350
2024-01-30 10:54:06 +02:00
nielsNocore
3c69021c6c enforce columnSize min width (#1348)
* shcnaged startColmresize to enforce the min widht property of a column in javascript

* fixed typo,
2024-01-30 10:05:53 +02:00
Vladimir Enchev
68955d67bb AutoComplete component is throwing 'Uncaught TypeError: Cannot read properties of undefined (reading 'instance')'
Fix #1349
2024-01-30 10:05:10 +02:00
Vladimir Enchev
bc1eadad26 Return null instead empty string for inputs value 2024-01-29 19:10:44 +02:00
Paul Ruston
ebe6245243 Add base type to filter array (#1347) 2024-01-29 18:32:09 +02:00
egans146
d12c624b23 change RadzenDatagrid OnSort to async (#1346)
fix for RadzenDataGrid displays incorrectly ordered data when using async LoadData #1345

Co-authored-by: Florent MARTIN <florent.martin@capgemini.com>
2024-01-28 09:43:55 +02:00
Vladimir Enchev
11c1668d65 Version updated 2024-01-26 11:11:38 +02:00
Vladimir Enchev
158c27e52b Numeric should not default to min value on nullable types 2024-01-26 11:09:26 +02:00
Marek
36b777da8f Can change added (#1317)
* Can change added

* demo added

* CanChange with EventCallback

* renamed

* Rename to follow existing naming conventions.

* Add description.

---------

Co-authored-by: Marek Mička <xmicka13@vutbr.cz>
Co-authored-by: Atanas Korchev <akorchev@gmail.com>
2024-01-23 16:59:26 +02:00
Vladimir Enchev
012010957d Version updated 2024-01-22 17:36:47 +02:00
Vladimir Enchev
b0f041328d DataGrid sort API demo updated 2024-01-22 11:40:12 +02:00
David Johnston
94a12d9767 #1338 Reset pagination to first page, when column sorting occurs, retaining default behavior. (#1340)
* Reset pagers when sorting changes

* #1338 Rest to first page on column sorting

* Made backward compatible.

* Renamed to make intention clearer

* Moved code to more appropriate location
2024-01-22 11:36:03 +02:00
Vladimir Enchev
06cbb3e7f8 RadzenDataGrid displays incorrectly filtered data when using async LoadData
Fix #1341
2024-01-22 10:05:05 +02:00
Vladimir Enchev
47de40856b NotificationMessage DetailContent and SummaryContent added 2024-01-20 12:20:47 +02:00
Vladimir Enchev
c044fa2932 DialogCardPage added to two demos source editor 2024-01-19 17:06:31 +02:00
Vladimir Enchev
10f2145c15 Update DataGridSortApi.razor
Close #1339 #1338
2024-01-19 16:53:07 +02:00
nielsNocore
de89355b05 implemented: when numpad decimal seperator is used. the numeric input will use the current culture Decimal separator instead of a . (period) (#1337) 2024-01-19 11:14:56 +02:00
yordanov
54f9eed786 Rename odd striped row background css variable. Resolves #1335 2024-01-18 16:57:26 +02:00
David Johnston
d8e73e9cb4 #1335 Separate colour for odd striped row background 2024-01-18 16:43:54 +02:00
yordanov
ba7f07e1c8 Update premium themes 2024-01-18 09:21:16 +02:00
yordanov
9353015ddc Update code snippet background and text color 2024-01-18 09:21:16 +02:00
Vladimir Enchev
780e300815 Version updated 2024-01-18 09:13:22 +02:00
yordanov
4ed6464bbe Fix heading levels in demo pages 2024-01-17 18:24:51 +02:00
yordanov
8a9ed91051 Fix heading levels in EventConsole and MainLayout 2024-01-17 18:00:38 +02:00
yordanov
784fabc288 Update shades of Badges used in demos 2024-01-17 17:49:33 +02:00
yordanov
1a25d1b866 Update Tooltip text color in material theme 2024-01-17 16:14:02 +02:00
Vladimir Enchev
b4bd2c3785 DropDownDataGrid should be focused when selecting items with mouse 2024-01-17 10:12:20 +02:00
Vladimir Enchev
c72a18c7e4 Fixed RadzenDataGrid not loading on first render
Fix #1332
2024-01-17 10:00:55 +02:00
yordanov
51095f4a9f Update Pager button colors 2024-01-16 16:02:21 +02:00
yordanov
f2af835a02 Update ProgressBar severity colors 2024-01-16 15:48:48 +02:00
yordanov
fa8965f7bd Update Button base color 2024-01-16 15:48:11 +02:00
yordanov
e4da8a26b0 Update Checkbox checked color 2024-01-16 15:31:22 +02:00
yordanov
45351a504f Update DatePicker interaction state colors in standard theme 2024-01-16 15:09:47 +02:00
yordanov
48ce3fd4d0 Update DatePicker interaction state colors 2024-01-16 14:58:30 +02:00
yordanov
98825a7d5f Update DropDown interaction state colors 2024-01-16 14:42:10 +02:00
Vladimir Enchev
7011688812 DataFilter will get the filter operator from the property 2024-01-16 11:22:00 +02:00
yordanov
ea8a3049cd Update PanelMenu interaction state colors 2024-01-16 11:13:35 +02:00
yordanov
d2c1e7aca5 Update Editor button text colors 2024-01-16 10:59:02 +02:00
yordanov
2d80e831be Update Header and SidebarToggle colors 2024-01-16 10:52:24 +02:00
yordanov
c83e7b2b14 Fix Validator text color 2024-01-16 10:52:24 +02:00
Vladimir Enchev
c7c71bc785 Accordion HeaderTemplate renamed to Template 2024-01-16 10:40:14 +02:00
yordanov
8c0e27b83b Fix Grid interaction state colors 2024-01-16 10:35:43 +02:00
yordanov
d275837da5 Fix Menu item colors 2024-01-16 10:35:43 +02:00
djatkinsrealis
c1ecb703bf #1320 Cascade RadzenDataGrid class to all descendants (#1328) 2024-01-16 10:05:44 +02:00
djatkinsrealis
f804b56f92 #1329 Optional pagination text labels for PagedDataBoundComponent Prev and Next buttons (#1330) 2024-01-16 09:47:29 +02:00
Vladimir Enchev
d7a04c86f3 Accordion item HeaderTemplate added 2024-01-16 09:37:42 +02:00
yordanov
652b76ba50 Fix Numeric button color 2024-01-15 18:54:57 +02:00
yordanov
359de1a1e5 Fix Splitter bar active color 2024-01-15 18:38:10 +02:00
yordanov
eecec3106b Fix Switch circle color 2024-01-15 18:30:13 +02:00
yordanov
f233b23569 Fix Tooltip text color in themes 2024-01-15 18:22:52 +02:00
yordanov
0862a81322 Fix Tooltip text color 2024-01-15 18:22:52 +02:00
yordanov
6421fc9519 Fix Upload choose button colors 2024-01-15 18:22:52 +02:00
bert-algoet
b1ef59bff9 Missing css styling on RadzenCheckBoxListItem Template (#1331)
* Added a Template to the RadzenCheckBoxListItem

* missing css styling on RadzenCheckboxListItemTemplate
2024-01-15 16:08:07 +02:00
yordanov
cd7670ad11 Fix Tree text colors 2024-01-15 13:07:02 +02:00
yordanov
79fa482f70 Fix Slider handle color 2024-01-15 12:59:03 +02:00
yordanov
11705f7ccd Fix Steps number selected state color 2024-01-15 12:44:38 +02:00
yordanov
11da4794b5 Fix SelectBar selected state colors 2024-01-15 12:17:38 +02:00
yordanov
5cc6ae012a Fix Scheduler text colors 2024-01-15 11:45:40 +02:00
Vladimir Enchev
938c321a54 version updated 2024-01-15 10:47:14 +02:00
bert-algoet
867422a2d9 Added a Template to the RadzenCheckBoxListItem (#1327) 2024-01-15 10:40:42 +02:00
djatkinsrealis
8a547877b5 #1321 change PagerPosition enum to use flags (#1324) 2024-01-15 10:40:07 +02:00
djatkinsrealis
3e301af80c #1322 Add custom FooterTemplate to DataGrid (#1323) 2024-01-15 10:24:12 +02:00
Faenrig Kolkrabe
41ad6dc339 Added MaxLength attribute to RadzenAutoComplete (#1326)
Enhancement request due to forum post 'https://forum.radzen.com/t/radzenautocomplete-maxlength/16153'

Co-authored-by: jpk <j.p.kocherscheidt@protonmail.com>
2024-01-15 10:23:26 +02:00
Josh
2f17f0d4ae Support for IFormattable (#1318)
* Support IFormattable, if TValue implements it

* Include demo for custom numeric types

* improve method name

* In cases where the value is already of the correct type, do not perform conversion.  Refactor SetParametersAsync to honor custom numeric support

* perform the Min/Max check before the equality shortcut

* remove unnecessary type conversion logic

* fixup: if type implements IComparable, be sure to return value immediately, if in range

* PR feedback: this resolves the issue, in that the value is pushed to the dom via JS.  I couldn't understand why this existing statement had the other conditionals.  Why would you want to trigger the ValueChanged/Changed callbacks, if the value indeed hasn't changed, or if there's a Format.  However, admittedly I don't know the background of why it was this way.

https://github.com/radzenhq/radzen-blazor/pull/1318#issuecomment-1886478912

---------

Co-authored-by: Josh H <josh@inventivecoders.com>
2024-01-12 11:13:16 +02:00
Vladimir Enchev
f1f99a1d92 Version updated 2024-01-12 09:03:59 +02:00
Vladimir Enchev
ad6fbe2bf3 Fixed RadzenDatePicker doesn't gain focus with OnDemand PopupRenderMode
Fix #1307
2024-01-10 13:31:39 +02:00
Vladimir Enchev
e0bfad4807 DataGrid column resize improved
Fix #1308
2024-01-10 10:13:36 +02:00
Vladimir Enchev
3572ab9452 Check if dialog is resizable before observing size changes
Fix #1314
2024-01-10 09:36:28 +02:00
Josh
30ed285dcf Support for custom Numeric Types (#1315)
* add a test for the ConvertValue Parameter.  Update InternalValueChanged code with the following enhancements:

a) only perform the overhead associated with Min/Max bounds checking if needed
b) by doing a, custom types that wrap decimal work with the control and avoid attempted ChangeValue conversion

* move dollars to own file, and implement IComparable<decimal>, and a TypeConverter

* Support TypeConverter for conversions to/from decimal, for custom numeric types

* support for IComparable, for when Min/Max are used with custom numeric types

* move Max/Min null check inside CheckBounds

---------

Co-authored-by: Josh H <josh@inventivecoders.com>
2024-01-10 09:14:57 +02:00
Vladimir Enchev
2881491cc2 demo code imporved 2024-01-09 13:08:30 +02:00
Vladimir Enchev
96f4d3e136 Version updated 2024-01-09 12:05:17 +02:00
Vladimir Enchev
9e9ab6ae13 Dialog options TitleContent property added 2024-01-09 11:59:11 +02:00
Vladimir Enchev
029cad9224 Missing summary added 2024-01-09 11:58:50 +02:00
Vladimir Enchev
0029315c2e Update DataFilter IQueryable demo with filtering collection using In operator 2024-01-09 09:46:00 +02:00
Atanas Korchev
247c3b58ec Use AllowFloatingLabel in CurrentPlaceholder. 2024-01-09 09:45:06 +02:00
yordanov
7a165adfb8 Fix FormField label background color 2024-01-09 09:22:23 +02:00
yordanov
5777319bfa Add new AllowFloatingLabel property to RadzenFormField 2024-01-08 18:54:14 +02:00
adrianjcalvert
9219c5a1ad Update Radzen.Blazor.js (#1312)
withCredentials added to ajax object in upload method
2024-01-08 07:14:24 +02:00
Vladimir Enchev
096295d258 Popup component outside click
Fix #1310
2024-01-08 07:14:00 +02:00
yordanov
aa26e0c44d Fix --rz-tabs-tab-color and cursor in RadzenTabs - resolves #1303 2024-01-07 16:12:16 +02:00
yordanov
8fcd0c5e4c FormField label should float on top if DropDown placeholder is present 2024-01-07 15:51:41 +02:00
Vladimir Enchev
1a26487df3 TabsChange demo added 2024-01-06 06:40:30 +02:00
Vladimir Enchev
7afedf59bf DataFilter In/NotIn filter operators support added 2024-01-05 15:18:22 +02:00
Vladimir Enchev
e81267995d version updated 2024-01-04 16:51:12 +02:00
Vladimir Enchev
9c206629b1 DataGrid cell css class not applied correctly 2024-01-04 16:50:59 +02:00
Vladimir Enchev
1e8dcdf4ea DataGrid select all for OData demo updated 2024-01-04 12:08:30 +02:00
Vladimir Enchev
027e120c87 demo update with multiple selection 2024-01-04 11:41:33 +02:00
Vladimir Enchev
09de9e5fda Version updated 2024-01-04 09:04:55 +02:00
Vladimir Enchev
b1c64bbd98 FileInput and Upload will not upload properly when Name is specified 2024-01-04 09:03:06 +02:00
Vladimir Enchev
7ec6f6caad Fixed Draggable errors when ref is null on drag start 2024-01-04 08:54:06 +02:00
stlufred
85babbeb01 Fix null exception when expanding tree node (#1306)
If:
- Checkboxes enabled
- CheckedValues is null
2024-01-04 08:45:54 +02:00
yordanov
0006223494 Revert "End-of-year promotion"
This reverts commit 5f73d1e57a.
2024-01-04 08:36:00 +02:00
Vladimir Enchev
5f1bf408f7 Fixed query could not be translated excepton
Fix #1300
2024-01-03 15:49:54 +02:00
Vladimir Enchev
8e8fd019c3 GoogleMap demo description updated 2024-01-02 15:37:44 +02:00
Vladimir Enchev
c7b98005bb GoogleMap ApiKey added to demo 2024-01-02 15:27:25 +02:00
Vladimir Enchev
508e95b9d8 GoogleMap demo restored 2024-01-02 15:11:33 +02:00
Vladimir Enchev
5245df3ce3 GoogleMap demo removed from navigation 2024-01-02 15:05:51 +02:00
Vladimir Enchev
ec66dd5649 Version updated 2024-01-02 14:15:03 +02:00
Vladimir Enchev
d28c3f9ba3 Fixed SplitButton error on click
Fix #1304
2024-01-02 14:13:51 +02:00
Vladimir Enchev
64705b393a Added ShowCalendarWeek to DatePicker
Close #1293
2024-01-02 14:08:35 +02:00
Vladimir Enchev
42b4557de7 DataGrid grouping API demo updated with ShowGroupExpandColumn 2024-01-02 13:48:23 +02:00
CodePro.Tv
d089a06566 made toggle visibility column optional, added group header with toggle (#1298)
Co-authored-by: CodeProTv <burritostand@gmail.com>
2024-01-02 13:47:37 +02:00
Atanas Korchev
4bbfdf8e85 Update the custom dialog editor example. 2024-01-02 11:15:50 +02:00
yordanov
1e6db0f0a5 Update copyright year 2024-01-01 17:08:10 +02:00
Atanas Korchev
0778c150b6 Cannot show RadzenAlert after the user closes it. 2023-12-25 10:40:11 +02:00
Atanas Korchev
30a7170f50 Cannot set the style of RadzenRating. Fixes #1296. 2023-12-22 16:47:31 +02:00
Paul Ruston
b9ca828522 New property ShowMarkers on Line Series (#1287)
* New property ShowMarkers on Line Series

* Add checkbox to Show Markers on LineSeries demo

* Moved marker visibility to RadzenMarkers and added change to other series types  that render markers. Updated demo
2023-12-20 14:05:20 +02:00
yordanov
5f73d1e57a End-of-year promotion 2023-12-20 09:41:51 +02:00
yordanov
b0f4c4b8e0 Fix typo 2023-12-19 11:02:19 +02:00
Vladimir Enchev
10e343b8bb More DataGrid OnKeyDown improvments 2023-12-19 10:21:28 +02:00
Vladimir Enchev
0ab5630ebf DataGrid OnKeyDown improved 2023-12-19 10:00:30 +02:00
Piotr Stola
86a47ad533 #1288 NotificationService: Missing IEquatable<T> Implementation (#1291)
* #1288 NotificationService: Missing IEquatable<T> Implementation in NotificationMessage

* #1288 NotificationService: Missing IEquatable<T> Implementation in NotificationMessage - fix for GetHashCode
2023-12-19 09:32:31 +02:00
Vladimir Enchev
fecf36a7ff Version updated 2023-12-18 18:21:47 +02:00
Vladimir Enchev
16b392d360 Accordion expand/collapse events logic fixed 2023-12-18 18:21:22 +02:00
yordanov
dd6709c14a Add LinkedIn follow button 2023-12-18 15:21:23 +02:00
yordanov
69622ad25a Add how to video in themes demo page 2023-12-18 15:02:54 +02:00
yordanov
7e6a5642c1 Update quickstart video 2023-12-18 15:01:59 +02:00
yordanov
ed9923dbf9 Add open graph tags 2023-12-15 11:03:21 +02:00
yordanov
bb13d0b6f9 Update demos titles and descriptions 2023-12-15 09:58:50 +02:00
Vladimir Enchev
423e00eccd TabsWrap demo added 2023-12-14 18:46:23 +02:00
Vladimir Enchev
90ffa50718 Popups close logic fixed 2023-12-14 15:47:52 +02:00
Vladimir Enchev
4f0ed25e8e version updated 2023-12-14 13:40:00 +02:00
Vladimir Enchev
3f99cc7a6d Change theme added 2023-12-14 13:38:43 +02:00
Vladimir Enchev
a7e9d43411 WASM debugging fixed 2023-12-14 11:35:25 +02:00
Vladimir Enchev
c79bc6e32f DataGrid will hide column resizers when column reorder in-progress 2023-12-14 11:16:36 +02:00
Vladimir Enchev
a2b18aaec4 Fixed Accordion Expand/Collapse events not raised 2023-12-13 17:45:38 +02:00
Paul Ruston
886e96f5d6 Add new Bar and Column Series property 'ColorMode' (#1272)
* Column Chart - Position data labels above, level or below bar if positive, zero or negative, respectively.
Bar Chart - Position data labels right, level or left of bar if positive, zero or negative, respectively.

* Add new series property 'ColorMode'.

* Revert "Add new series property 'ColorMode'."

This reverts commit 07295350c6.

* ColorMode option 'Series' or 'PositiveNegative'.
Bar and Column Render methods improved.

* Make Render method a bit more concise. Change property name to ChartSeriesColorMode

* Code refactoring and property name change

* Refactoring and renaming

* Change the workings to generic ColorRanges rather than static PositiveNegative

* Remove ColorMode and redo PickColor to check for null Ranges instead. Apply to StackedSeries also.

* Removed colorMode XML Comment

* Tidied up code as per comments

* Rename val to itemValue and remove trailing spaces from files

* The ones I missed :)

* Create FillRange demo
2023-12-13 16:49:08 +02:00
decimvs
88388fc5b1 feature: added support to define a custom function to be called when datagrid enum filter is rendering enum filter menu to display a translated text by calling a custom function. It allows to use alternative I18N stacks. (#1282)
Co-authored-by: guillermoec <guillermoec>
2023-12-13 09:18:10 +02:00
Vladimir Enchev
7cd4dec4df demo fixed 2023-12-11 18:05:50 +02:00
Vladimir Enchev
567c43f2f0 Accordion selection with keyboard added 2023-12-11 16:20:15 +02:00
Vladimir Enchev
566a2509c9 Attribute aria-checked added to various components 2023-12-11 13:59:01 +02:00
Vladimir Enchev
dbaad2e169 Version updated 2023-12-11 09:53:05 +02:00
Vladimir Enchev
2fdf9f9a8c Styling chart demo fixed
Fix #1280
2023-12-11 09:33:47 +02:00
Vladimir Enchev
ebfcef12a7 Fixed DataGrid composite columns width logic
Fix #1273
2023-12-11 09:27:10 +02:00
Vladimir Enchev
a0fc26afd7 Dialog will stop render during drag 2023-12-08 18:09:57 +02:00
Vladimir Enchev
5c8c8b6502 DataGrid item cannot be deselected in case of multiple selection and LoadData binding 2023-12-08 15:12:21 +02:00
Vladimir Enchev
7e38749e40 version updated 2023-12-08 10:05:02 +02:00
Vladimir Enchev
e538336c5e DataGrid keyboard navigation fixed
Fix #1277
2023-12-08 10:04:45 +02:00
Justin Schweigert
f14b519756 Add ability to configure AutoComplete input type (#1274)
* Add ability to configure AutoComplete input type

* Rename property to InputType
2023-12-08 09:26:42 +02:00
Vladimir Enchev
034a1b3991 Version updated 2023-12-07 16:38:25 +02:00
Vladimir Enchev
a2144d21c2 Fixed redundant link WCAG warning
Removed href="javascript:void(0)" and added @onclick:preventDefault="true" instead
2023-12-07 16:04:56 +02:00
Vladimir Enchev
4a50a3161d Validator demos accessibility improved 2023-12-07 15:34:16 +02:00
Vladimir Enchev
d983b1f329 Alert demo accessibility improved 2023-12-07 15:22:36 +02:00
Vladimir Enchev
c1d5429245 Name/Component made unique 2023-12-07 15:14:34 +02:00
Vladimir Enchev
c094016c33 demos accessibility improved 2023-12-07 15:11:53 +02:00
Vladimir Enchev
5caf503784 demo accessibility improved 2023-12-07 15:08:14 +02:00
Vladimir Enchev
93cd9f6880 code fixed 2023-12-07 15:01:22 +02:00
Vladimir Enchev
7c7f5220da For changed to Component 2023-12-07 15:00:57 +02:00
Vladimir Enchev
09e916fe18 Upload accessibility improved 2023-12-07 14:55:05 +02:00
Vladimir Enchev
471d9eed35 demos accessibility improved 2023-12-07 13:53:32 +02:00
Vladimir Enchev
4457385281 Logic for id for TextBox. TextArea and Password fixed 2023-12-07 12:41:44 +02:00
Vladimir Enchev
c37d999ff3 TextBox, TextArea and Password should set Name as id if not set 2023-12-07 12:31:21 +02:00
Vladimir Enchev
6813b01c20 demos accessibility improved 2023-12-07 12:14:03 +02:00
Vladimir Enchev
2e6032f81b demo accessibility improved 2023-12-07 12:00:50 +02:00
Vladimir Enchev
001e9989b8 RadioButtonList accessibility improved 2023-12-07 11:52:38 +02:00
Vladimir Enchev
45dc0a2a72 Password demos accessibility improved 2023-12-07 11:48:41 +02:00
Vladimir Enchev
dbb511b2f9 Numeric demos accessibility improved 2023-12-07 11:46:37 +02:00
Vladimir Enchev
cbd13b49ef Mask demo accessibility improved 2023-12-07 11:42:38 +02:00
Vladimir Enchev
5902a7f113 ListBox accessibility improved 2023-12-07 11:39:39 +02:00
Vladimir Enchev
70e71fc1da HtmlEditor demo accessibility improved 2023-12-07 11:28:55 +02:00
Vladimir Enchev
91d941b663 FileInput accessibility improved 2023-12-07 11:24:54 +02:00
Vladimir Enchev
75ca1ff498 ColorPicker accessibility improved 2023-12-07 11:16:05 +02:00
Vladimir Enchev
b0e5ad3ef5 CheckBoxList accessibility improved 2023-12-07 11:11:58 +02:00
Vladimir Enchev
0c12ff7662 demo fixed 2023-12-07 11:05:55 +02:00
Vladimir Enchev
d44c6c593d ToggleButton demos accessibility improved 2023-12-07 11:04:23 +02:00
Vladimir Enchev
cdce35ec7a AutoComplete demos accessibility improved 2023-12-07 10:49:42 +02:00
Vladimir Enchev
20210d7d54 BreadCrumbItgem should not use orphaned label 2023-12-07 10:23:16 +02:00
Vladimir Enchev
8ade843108 Switch and ToggleButton InputAttributes added 2023-12-07 10:12:22 +02:00
Vladimir Enchev
faab0e841e SplitButton OpenAriaLabel and Tree SelectItemAriaLabel added 2023-12-06 17:09:54 +02:00
Vladimir Enchev
efae6afd5a demos accessibility improved 2023-12-06 16:44:09 +02:00
Vladimir Enchev
bb8f13d57b Demo accessibility improved 2023-12-06 16:26:08 +02:00
Vladimir Enchev
ff1903b1cc DataGrid filter aria labels exposed as properties 2023-12-06 16:20:00 +02:00
Vladimir Enchev
db193bd94a DataGrid filter accessibility improved 2023-12-06 16:04:41 +02:00
Vladimir Enchev
0ad1d57785 CheckBox InputAttributes added 2023-12-06 15:36:29 +02:00
Vladimir Enchev
0c340286ef various accessibility errors fixed 2023-12-06 14:39:07 +02:00
Vladimir Enchev
e60d681992 Added labels to all DatePicker demos 2023-12-06 11:27:40 +02:00
OndrejUzovic
fff48260be ref null reference fix (#1271) 2023-12-06 11:17:14 +02:00
Vladimir Enchev
2e7752559d various form components accessibility fixed 2023-12-06 10:40:19 +02:00
Vladimir Enchev
aa000e46ed FilterTemplate added to demo
Close #1269
2023-12-06 09:33:36 +02:00
Paul Ruston
8ed441d968 Column Chart - Position data labels above, level or below bar if positive, zero or negative, respectively. (#1270)
Bar Chart - Position data labels right, level or left of bar if positive, zero or negative, respectively.
2023-12-06 09:30:27 +02:00
Vladimir Enchev
c711a0c32c aria-label added to RadzenPanelMenuItem 2023-12-06 09:24:51 +02:00
Vladimir Enchev
2bdfe2e12a AlternateText set for various images 2023-12-05 15:45:34 +02:00
Vladimir Enchev
1023fd90f1 Missing form label and orphaned label accessibility errors fixed 2023-12-05 15:27:41 +02:00
Vladimir Enchev
059a59c746 RadzenLabel changed to span
Orphaned label accessibility error
2023-12-05 15:26:00 +02:00
Vladimir Enchev
2363a1fbb6 tests fixed 2023-12-05 15:24:55 +02:00
Vladimir Enchev
26b2cc816e DatePicker width fixed 2023-12-05 10:27:04 +02:00
Vladimir Enchev
93fc4950df Various AriaLabel properties added 2023-12-05 10:17:45 +02:00
Vladimir Enchev
f042076cab various images alt attribute added 2023-12-05 09:21:56 +02:00
Vladimir Enchev
9a6fd69885 ImageAlternateText property added to various components 2023-12-05 09:13:27 +02:00
yordanov
ffbf4b07f1 Update Scheduler demos 2023-12-01 13:16:33 +02:00
yordanov
88ac570031 Style content in Scheduler Tooltip demo 2023-12-01 11:26:57 +02:00
Atanas Korchev
70c5d4eb43 Set Delay to null. 2023-12-01 10:39:31 +02:00
Atanas Korchev
1899f97b1e Add support for tooltips in Scheduler appointments. 2023-12-01 10:24:08 +02:00
Vladimir Enchev
56cbb44f94 Microsoft.AspNetCore.Components versions updated
Fix https://github.com/radzenhq/radzen-blazor/security/dependabot/4
Fix https://github.com/radzenhq/radzen-blazor/security/dependabot/5
2023-12-01 10:04:25 +02:00
Vladimir Enchev
42c6b70f2b demo fixed 2023-12-01 10:00:39 +02:00
Atanas Korchev
f673a36ccd Wrong pie series tooltip displayed when some value is zero. Fixes #1264. 2023-12-01 09:39:53 +02:00
Vladimir Enchev
80f319311e DataGrid keyboard navigation and selection for rows added 2023-12-01 09:29:13 +02:00
Vladimir Enchev
d256d5f7da System.Linq.Dynamic.Core updated to latest
Fix #1263
2023-11-30 10:11:54 +02:00
liam-gray
0b7737a054 Stop all groups collapsing when switching to and from edit mode (#1265) 2023-11-30 08:50:15 +02:00
Vladimir Enchev
89f0c01acc Version updated 2023-11-29 11:47:40 +02:00
Vladimir Enchev
d66cde252d Editable DropDown demo added 2023-11-28 15:27:00 +02:00
Vladimir Enchev
c9103bd521 Dialog height not updated properly when multiple dialogs are chained 2023-11-28 09:19:22 +02:00
yordanov
d2e87b0e13 Update links 2023-11-28 08:41:38 +02:00
yordanov
a7eb042276 Stop "BlackFriday2023"
This reverts commit 9fd5220e8c.
2023-11-28 08:34:04 +02:00
Vladimir Enchev
114796006f version updated 2023-11-27 19:06:33 +02:00
Vladimir Enchev
38932f14cc DatePicker ShowDays property added to allow Year/Month selection only 2023-11-27 18:59:02 +02:00
Vladimir Enchev
3ee1286cf4 obsolete code deleted 2023-11-27 15:14:51 +02:00
Vladimir Enchev
ffef5923c6 Accordion Select item state fixed 2023-11-27 15:12:56 +02:00
Maks
e670c679df Added FilterString generation for the FilterOperator.In and FilterOperator.NotIn (Intersect/Except) operators for LoadData. (#1260)
Added the correct method for comparing objects supported by a collection, to correctly load the filter with the collection
2023-11-27 11:55:19 +02:00
Vladimir Enchev
06ba235947 demo fixed 2023-11-27 11:52:01 +02:00
Atanas Korchev
db72bb33f2 Stacked area (#1258)
* Stacked area rendering.

* Support markers and tooltips.
2023-11-23 12:54:10 +02:00
Vladimir Enchev
0c700cd1f8 version updated 2023-11-23 09:36:30 +02:00
Vladimir Enchev
721b63b197 DataGrid GroupDescriptor FormatString added 2023-11-22 16:55:10 +02:00
AlittaSakraf
41ca477b8a Update QueryableExtension.cs (#1256)
Bug: If you use a sub-property in the Column PropertyName (ex: "Data2.Name") and the filter is isNull / IsNotNull / Empty/ NotEmtpy  -> There will be an excepction: "Error: The 'np' (null-propagation) function requires the first argument to be a MemberExpression, ParameterExpression or MethodCallExpression (at index 0)
because of the dooble np(np()) in the Filter property....
2023-11-22 08:46:45 +02:00
yordanov
9fd5220e8c BlackFriday2023 2023-11-21 11:33:13 +02:00
Vladimir Enchev
65be8cd2ce Enabled arbitrary attributes for RadzenComponents 2023-11-20 16:02:08 +02:00
Vladimir Enchev
4b24ed4a21 .NET 8 Static @@rendermode info added 2023-11-20 15:54:52 +02:00
yordanov
93bdb4236e Fix frozen column background with disabled alternating rows. Resolves #1253 2023-11-17 11:08:54 +02:00
Vladimir Enchev
db82a14837 analytics restored 2023-11-16 17:12:32 +02:00
Vladimir Enchev
b6cb460085 Version updated 2023-11-16 15:16:08 +02:00
Vladimir Enchev
358bb18f8f Fixed DataGrid CellRender not raised for child columns
Fix #1252
2023-11-16 15:15:54 +02:00
Vladimir Enchev
bd2cc60aae Version updated 2023-11-16 10:08:20 +02:00
Vladimir Enchev
f00bd31eaf Fixed adding attributes in DataGrid CellRender event 2023-11-16 10:08:03 +02:00
yordanov
191ca88daa Fix FormField input disabled color 2023-11-15 14:20:12 +02:00
Vladimir Enchev
611571d566 Demos converted to .NET 8 Blazor Web app type (#1250)
* Demos converted to new Blazort Web .NET 8 app

* code edit fixed
2023-11-15 14:19:51 +02:00
Vladimir Enchev
11550edcd0 Version updated 2023-11-14 22:10:45 +02:00
Vladimir Enchev
3c51f44190 Change reverted
Reverted https://github.com/radzenhq/radzen-blazor/pull/1246
2023-11-14 22:09:34 +02:00
Vladimir Enchev
ee3fbcae78 8.0 restored 2023-11-14 22:02:24 +02:00
Vladimir Enchev
63ad119e63 version updated 2023-11-14 22:01:23 +02:00
Vladimir Enchev
bfcae3fc70 code removed 2023-11-14 21:57:48 +02:00
Vladimir Enchev
21b261b2d3 code fixed 2023-11-14 21:56:59 +02:00
Vladimir Enchev
9ac94167d2 attempt to clear 2023-11-14 21:55:43 +02:00
Vladimir Enchev
170c782ba2 code fixed 2023-11-14 21:53:21 +02:00
Vladimir Enchev
7465259340 docker updated 2023-11-14 21:52:41 +02:00
Vladimir Enchev
c871e8b64e docker updated to .NET 8 2023-11-14 18:49:48 +02:00
Vladimir Enchev
1dfaa93568 Version updated 2023-11-14 18:43:57 +02:00
Vladimir Enchev
866c480634 .NET8 added (#1248)
* net8 added

* Update ci.yml
2023-11-14 18:42:47 +02:00
Vladimir Enchev
ae6fbc1acb Panel expand/collapse icon position demo added
Close #1244
2023-11-14 15:22:08 +02:00
Vladimir Enchev
1cbf9c5eb8 Fixed virtualized DropDown will not raise LoadData when empty
Fix #1247
2023-11-14 14:35:37 +02:00
DanRogers99
210da6c94b Numeric Issue with Leading Zeros (#1245)
* Numeric Issue with Leading Zeros

* .
2023-11-14 14:18:09 +02:00
MicrosoftHawk
5be889d169 The EditRow doesn't use the same compare method as the CancelEditRow. (#1246)
Co-authored-by: Siebe Jan de Vries <siebejan.devries@axba.nl>
2023-11-14 14:08:27 +02:00
Vladimir Enchev
03f992bfc5 various warnings fixed 2023-11-14 10:38:25 +02:00
DanRogers99
db6afdbfbb Add Icon (#1243) 2023-11-14 08:43:39 +02:00
Vladimir Enchev
624c562c1f Menu item disabled property added (#1242)
* RadzenMenuItem Disabled property added

* code fixed

* Update premium themes

---------

Co-authored-by: yordanov <vasil@yordanov.info>
2023-11-13 21:13:29 +02:00
Derek Beattie
4809eccb9e Update DataGridColumnResizing.razor (#1241)
This demo demonstraes column resizing but the column lines aren't visible.
2023-11-13 09:07:27 +02:00
Vladimir Enchev
1f9f46175c Optimized DataGrid cell attributes 2023-11-12 12:38:42 +02:00
Vladimir Enchev
71b16e1824 Set DataGrid cell rowspan/colspan only when needed 2023-11-10 16:44:00 +02:00
Vladimir Enchev
3975b2c6e3 virtualization removed from demo 2023-11-10 11:59:14 +02:00
Vladimir Enchev
48bcb02f82 Added virtualization to performance demo 2023-11-10 11:48:05 +02:00
Vladimir Enchev
9fd83e56e2 Version updated 2023-11-10 07:14:27 +02:00
Vladimir Enchev
a40742a45c DataGrid RowDoubleClick not raised 2023-11-10 07:14:14 +02:00
Vladimir Enchev
4d10e7e290 Version updated 2023-11-09 21:49:28 +02:00
Vladimir Enchev
83f1a1ef8e DataGrid row selection fixed 2023-11-09 21:49:19 +02:00
Vladimir Enchev
47581eb453 AutoComplete will select item on TAB 2023-11-09 17:10:43 +02:00
Vladimir Enchev
045ac03837 Version updated 2023-11-09 16:19:32 +02:00
Vladimir Enchev
6439845d32 bootstrap CSS added 2023-11-08 13:59:25 +02:00
Vladimir Enchev
0b0721b9d3 bootstrap CSS added 2023-11-08 11:41:56 +02:00
Vladimir Enchev
f1ba65affa More DataGrid cell render optimizations 2023-11-07 16:33:37 +02:00
GeorgeKarlinzer
e60bdbf80c Make RadzenDataGrid.ItemEquals protected (#1239)
Co-authored-by: Heorhi Kupryianau <h.kupryianau@sente.pl>
2023-11-07 09:51:40 +02:00
Vladimir Enchev
2269b500f3 Fixed RadzenDropDownDataGrid not calling LoadData when virtualized and empty initially 2023-11-06 16:34:40 +02:00
Vladimir Enchev
089f2e964c Version updated 2023-11-06 11:26:42 +02:00
Vladimir Enchev
1e477f71ef Demo service changed to our OData service which support In operator 2023-11-06 11:25:03 +02:00
Vladimir Enchev
430e8efd42 DataGrid In/NotIn filter operators should be available only for IEnumerable
Opt
2023-11-06 11:17:00 +02:00
kSacred
bddd7e5417 Fix columns visibility when DataGrid Reset, columns visibility returns to its default state (#1233) 2023-11-06 10:21:55 +02:00
Paul Ruston
10deb4c51a Add property to SplitterPane to be able to hide Splitter Bar (#1238) 2023-11-06 10:21:02 +02:00
Victor Ureta
530c3a5576 Gets the currently selected RadzenTabsItem based on the selectedIndex (#1235) 2023-11-06 10:20:44 +02:00
Vladimir Enchev
4e5cb34051 cell render improved (#1234) 2023-11-03 18:36:39 +02:00
Vladimir Enchev
e7c5eb6bee DropDown and DropDownDataGrid InputAttributes added
Close #1016 #1232
2023-11-03 09:46:39 +02:00
Vladimir Enchev
f2cb6ed1a6 DropDownDataGrid keyboard row navigation added 2023-11-02 17:29:12 +02:00
yordanov
ce745204f7 Update product descriptions 2023-11-02 15:36:12 +02:00
yordanov
8b3c9f2f72 Update example reference 2023-11-02 10:52:50 +02:00
Vladimir Enchev
2aa1c85972 missing title added 2023-11-02 10:36:36 +02:00
Vladimir Enchev
766e5db363 Version updated 2023-11-02 10:16:12 +02:00
Vladimir Enchev
c1504e104d ToggleButton component added (#1231)
* Added ToggleButton component

* IconColor support added to ToggleButton

* ToggleButtonStyle and ToggleShade added

* toggleStyle fixed

* ToggleIcon added

* code improved

* Update ToggleButton demos

* use ToggleIcon only if specified

* ToggleShade imroved

* ToggleShade set to Shade.Default

* Shade.Darker for ToggleShade

* rz-shade-default removed when toggled

* buttonStyle replaced

* classes reworked

* base classes reworked

* Update ToggleButton demos

---------

Co-authored-by: yordanov <vasil@yordanov.info>
2023-11-02 10:12:56 +02:00
DanRogers99
3705b740c9 Close Nested Modals (#1227) 2023-10-31 09:34:12 +02:00
Vladimir Enchev
85889ee338 Added ContextMenu Support on RadzenMenuItem
Fix #1224
2023-10-30 16:13:10 +02:00
Atanas Korchev
32254fbed8 Display error if the example cannot be loaded. 2023-10-30 10:35:30 +02:00
Vladimir Enchev
62fbac2d19 Version updated 2023-10-30 09:41:19 +02:00
Vladimir Enchev
6b02bb973f DialogOptions.CloseDialogOnEsc behavior fixed
Fix #1221
2023-10-30 09:40:51 +02:00
Vladimir Enchev
1ad15035de Fixed RequiredValidator validation of DropDown with multiple selection. 2023-10-27 13:27:30 +03:00
Vladimir Enchev
dd7a21010a Fixed DataGrid LoadData filter when binding to OData with virtualization
Fix #1220
2023-10-26 16:58:31 +03:00
Atanas Korchev
f69ab641f7 Add mask to the full height overlay. 2023-10-25 13:21:52 +03:00
yordanov
27308b59ea Update tags in Layout demos 2023-10-25 13:03:22 +03:00
yordanov
f1aa9fe906 Style collapse button in sidebar 2023-10-25 12:43:31 +03:00
Atanas Korchev
112b28342a Layout demo improvements. 2023-10-25 12:05:23 +03:00
Vladimir Enchev
2f9fe92b6c multiple CaptureUnmatchedValues removed 2023-10-24 11:39:17 +03:00
Vladimir Enchev
4a45c78512 InputAttributes added to various form components
Fix #1212
2023-10-24 09:17:20 +03:00
Vladimir Enchev
0c78f66c21 Row keeps highlighted state after clearing DropDownDataGrid
Fix #1215
2023-10-24 08:58:24 +03:00
Dave Bagler
be6f934e7b Added expand/collapse title and aria-label attributes to panels. (#1217) 2023-10-24 08:36:19 +03:00
Vladimir Enchev
79fa11f2c9 demo improved 2023-10-23 14:32:11 +03:00
yordanov
349966a7c3 Update premium themes 2023-10-23 10:30:33 +03:00
Vladimir Enchev
4867825367 Version updated 2023-10-23 09:33:00 +03:00
kSacred
36686afe04 New parameter UniqueFilters in DataFilter. (#1199)
* New parameter Unique filters in DataFilter. If set to true, then only unique filters can be used, that is, one property can only be used once in a filter.
The IsSelected parameter has been added to DataFilterProperty. Indicates whether the property has already been selected in the DataFilter.

* merge master
2023-10-23 09:31:21 +03:00
Vladimir Enchev
9547896074 Second DataGrid frozen columns demo removed 2023-10-23 09:21:00 +03:00
Péter Vida
4ecb737ea7 Right side frozen columns for RadzenDataGrid (#1213)
* FrozenPosition added#

* Some improvements.

* Some improvements.

* Column demo improved.

* Styling fixes.

* _grid.scss update

* Cleanup.

* Cleanup.

* Demo exapmle message.

* ident fix.

---------

Co-authored-by: Péter Vida <vida.peter@vigapeta.com>
2023-10-23 09:20:19 +03:00
Guillermo Orue Marighetti
0147f398ec Catch JSRuntime invoke exceptions (#1210) 2023-10-23 08:55:06 +03:00
Guillermo Orue Marighetti
3fd0420b52 Add EmptyTemplate to RadzenDropdown (#1211)
* Add an empty template to RadzenDropdown

* Adapt validation from RadzenDatagrid structure

* Simplified validations
2023-10-23 08:54:07 +03:00
Atanas Korchev
decba39373 Trying to upload files in RadzenHtmlEditor sometimes throws JS exceptions "target.matches is not a function". 2023-10-20 21:50:10 +03:00
Atanas Korchev
15972a9203 Prevent memory leaks related to validation. 2023-10-20 13:41:14 +03:00
Dave Bagler
94c0a52824 Expand/Collapse aria-label and title attributes. (#1204)
* Adding aria-label and title attribute parameters to field sets and accordion items.

* Changing the Label parameters to AriaLabel
2023-10-20 08:56:18 +02:00
Dave Bagler
d583f52d7e Adding aria-label and title attributes to pager buttons. (#1205)
* Adding aria-label and title attributes to pager buttons.

* Changing the Label parameters to AriaLabel.
2023-10-20 08:55:25 +02:00
Dave Bagler
9b243f90ee Adding title and aria-label attributes to step buttons. (#1208) 2023-10-20 08:54:09 +02:00
GAUSS-LVS Dev
18168e4577 More Image properties (#1207)
* Added an Image property to RadzenLink

* Replaced Version with VersionPrefix in order to specify a VersionSuffix with dotnet pack

* Revert "Replaced Version with VersionPrefix in order to specify a VersionSuffix with dotnet pack"

This reverts commit 457a7b24b8.

* More Image properties
- Added in ContextMenuItem
- Used in RadzenContextMenu
- Added and used in RadzenProfileMenuItem

* Removed Parameter attribute

---------

Co-authored-by: pb <p.baumann@gauss-lvs.de>
2023-10-19 16:20:01 +03:00
GAUSS-LVS Dev
a18e5454ce Added an Image property for RadzenLink (#1203)
* Added an Image property to RadzenLink

* Replaced Version with VersionPrefix in order to specify a VersionSuffix with dotnet pack

* Revert "Replaced Version with VersionPrefix in order to specify a VersionSuffix with dotnet pack"

This reverts commit 457a7b24b8.

---------

Co-authored-by: pb <p.baumann@gauss-lvs.de>
2023-10-19 10:59:58 +03:00
kSacred
7bf16f2891 Added property Sorts to the Query, to obtain sorting in different services, for example during export. (#1206) 2023-10-19 10:59:27 +03:00
kSacred
8491387a15 Fixed loading datagrid filter settings with quotes. When loading the filter value from json, get the string value of the element. (#1202) 2023-10-18 16:03:36 +03:00
Vladimir Enchev
123ae18a64 Version updated 2023-10-18 11:19:58 +03:00
kSacred
f3a19597fc Set the filter operator specified in the code when adding a filter in DataFilter (#1198) 2023-10-18 11:16:29 +03:00
Vladimir Enchev
6c6ccbf07c Fixed exception when removing groups from virtualized DataGrid 2023-10-18 11:12:27 +03:00
Guillermo Orue Marighetti
09af9a2576 Add placeholder to dropdown filter (#1196)
* Add placeholder to dropdown filter

* Fix summary
2023-10-16 14:15:09 +03:00
kSacred
cf813d7eb4 Added the missing classes to the DataFilter elements, by analogy with the already existing rz-datafilter-* element classes. (#1197) 2023-10-16 14:14:37 +03:00
Vladimir Enchev
f0ca523dfb Version updated 2023-10-16 09:53:19 +03:00
Atanas Korchev
6a08443853 Override Dispose in the Monaco component. 2023-10-16 09:45:43 +03:00
DanielSugdenPhoenix
030b9b0c82 Added the ability to display smaller segmented pie charts (#1191)
* Added functionality to allow the changing of the starting angle of, and the number of degrees the pie and donut charts span

* Removed nullable on StartAngle and TotalAngle, added default values and removed unneeded checks

* Updated comment about default value of the StartAngle in RadzenPieSeries

* Refactor the implementation of StartAngle and TotalAngle.

* Fix for rendering segments greater than180 degrees

* Restore the demo.

* Revert "Restore the demo."

This reverts commit 3d44fa71b0.

---------

Co-authored-by: Atanas Korchev <akorchev@gmail.com>
2023-10-16 09:43:21 +03:00
yordanov
8a0b511649 Fix PanelMenu expand arrow position in item template 2023-10-16 09:40:01 +03:00
Marek
7853b830ae RadzenStepsItem can have own NextText and PreviousText (#1195)
Co-authored-by: Marek Mička <xmicka13@vutbr.cz>
2023-10-16 09:18:59 +03:00
Vladimir Enchev
77eb7f7821 SelectBarItem not updated on Disabled change 2023-10-13 11:49:06 +03:00
Atanas Korchev
65e71ac56f More styling fixes in the installation article. 2023-10-13 10:07:21 +03:00
Atanas Korchev
a2a1bcb77b Styling fixes in the installation article. 2023-10-13 09:55:55 +03:00
Atanas Korchev
e8fadc638c Upload documentation fixes. 2023-10-13 09:48:20 +03:00
Atanas Korchev
507a8330b7 .NET 8 documentation updates. 2023-10-13 09:48:13 +03:00
Vladimir Enchev
1dc1c99c33 Slider cannot reach the maximum when initial value is equal to Max 2023-10-12 15:53:59 +03:00
Vladimir Enchev
0cd89585e2 PageSizeOptions added to demo 2023-10-12 10:12:17 +03:00
Guillermo Orue Marighetti
c54148c291 Add placeholder to datagrid filter (#1192) 2023-10-12 08:54:34 +03:00
Vladimir Enchev
f7d7fa5031 Version updated 2023-10-10 15:19:04 +03:00
Vladimir Enchev
d959bd6c34 Tabs item Visible=false not working with TabRenderMode.Client
Fixed
2023-10-10 12:06:06 +03:00
Vladimir Enchev
92240d3e8b Check if grid is not null
Fix #1188
2023-10-10 09:28:42 +03:00
kSacred
0c634a4fa6 Added FilterOperator.Custom check to GetColumnFilter. (#1187)
With FilterOperator.Custom there is no need to generate a filterString, otherwise it throws an error.
2023-10-10 08:36:52 +03:00
Vladimir Enchev
c8e2414a70 RadzenComponents used in the demos 2023-10-09 14:50:42 +03:00
Vladimir Enchev
a6956b34db Version updated 2023-10-09 14:41:30 +03:00
Vladimir Enchev
055c2ec202 Ensure Google API is loaded when calling updateMap() 2023-10-09 14:41:20 +03:00
kSacred
1c0e03eadc Added a check for FilterOperator.Custom in ClearFilters so that the FilterOperator does not change and remains FilterOperator.Custom (#1186) 2023-10-09 14:17:16 +03:00
Vladimir Enchev
f8c44cf2d3 IconColor added to all components with Icon. Predefined theme colors added in Colors class. (#1185) 2023-10-06 11:18:29 +03:00
Vladimir Enchev
d99eeb1e1e RadzenComponents added to simplify adding of special components to layout 2023-10-05 11:16:35 +03:00
Vladimir Enchev
c42a4d9d1c Version updated 2023-10-04 10:07:40 +03:00
Nathan Stuller
2b8eb11bc3 Changing method modifiers so they can be overridden (#1178)
* Changing method modifiers so they can be overridden

* Removing the event handler for onkeydown is what really speeds it up

* Revert OnKeyDown change

---------

Co-authored-by: Nathan Stuller <stullern@hotmail.com>
2023-10-04 07:08:13 +03:00
kSacred
f4f62c6edf Fixed exception when set/load a filter with Nullable enum type in DataGrid (#1179) 2023-10-03 14:48:07 +03:00
kSacred
142f75e662 Added Filters to Query to be able to get filter data via grid.Query.Filters (#1177)
* Added Filters to Query to be able to get filter data via grid.Query.Filters

* Return FilterParameters
removed change for RadzenGrid.razor

* removed change for RadzenGrid.razor
2023-10-03 11:54:55 +03:00
Vladimir Enchev
1bc19921ff Merge branch 'master' of https://github.com/radzenhq/radzen-blazor 2023-09-29 09:24:51 +03:00
Vladimir Enchev
d901b795f7 Version updated 2023-09-29 09:24:48 +03:00
johnmiller86
de19e3abec Added a RadzenGoogleMap boolean parameter to zoom the map to fit marker bounds on update - JDM (#1176)
Co-authored-by: John Miller <JMiller@geo-blue.com>
2023-09-29 09:23:42 +03:00
kSacred
ee1ab72d0a Fix DataGrid not loading with settings if equal to default. (#1175) 2023-09-29 09:22:56 +03:00
Vladimir Enchev
c699dd71af Avoid Radzen is not defined error 2023-09-28 09:15:05 +03:00
Vladimir Enchev
3452bafd4b demo updated 2023-09-28 09:04:32 +03:00
kSacred
0aabac338d Added "Custom" to FilterOperator, for manually building a custom filter (#1169) 2023-09-28 08:56:21 +03:00
kSacred
a9a25a9197 Fixed pagination when set a filter via SetFilterValueAsync in FilterTemplate. (#1173) 2023-09-28 08:51:29 +03:00
Stuart Turner
aa295e9688 Add support for EditTemplate (#1171) 2023-09-27 16:41:01 +03:00
Vladimir Enchev
9cf21b1192 DataGrid multiple selection demo updated 2023-09-27 10:54:22 +03:00
Atanas Korchev
7efb6fc125 Update the scheduler demo to pass a copy of the appointment so cancelling works. 2023-09-24 11:50:38 +03:00
Atanas Korchev
a050af7985 Stacked charts sometimes render gaps. 2023-09-22 17:51:16 +03:00
Vladimir Enchev
25e3fd90c5 Version updated 2023-09-22 15:44:43 +03:00
Vladimir Enchev
e79384a3c4 DropDownBase multiple selection fixed
Fix #1163
2023-09-22 15:44:32 +03:00
Vladimir Enchev
c784af67da Version updated 2023-09-21 09:09:14 +03:00
Vladimir Enchev
74d4681f33 DropDown selected items should be cleared when retrieving from Value 2023-09-21 09:07:20 +03:00
yordanov
eaa939eda3 Update premium themes 2023-09-20 14:10:50 +03:00
Vasil Yordanov
a3b21debb0 Switch from LibSass to Dart Sass (#1161)
Replacing LibSass with Dart Sass. Resolves #1077
2023-09-20 13:59:19 +03:00
Vladimir Enchev
db9168e179 DropDownDataGrid inner DataGrid exposed as property 2023-09-20 09:10:47 +03:00
Vladimir Enchev
d68a5106a5 DataGrid RenderAsync event added
Fix #1160
2023-09-19 16:47:57 +03:00
TimChen
5244d7af1e add IsShowArrow (#1158)
* add IsShowArrow

* layout demo add IsShowArrow

* Modify ShowArrow name
2023-09-18 16:01:32 +03:00
Vladimir Enchev
0ee095617e DataGrid and DataList LoadingTemplate added 2023-09-18 15:58:09 +03:00
Vladimir Enchev
8d7d022576 FocusAsync() method added to all form components 2023-09-18 12:15:40 +03:00
Vladimir Enchev
098cf78753 AutoComplete FocusAsync() method added 2023-09-18 11:52:14 +03:00
Vladimir Enchev
4131811e32 Version updated 2023-09-18 11:21:30 +03:00
Vladimir Enchev
260cd62329 DataGrid RefreshDataAsync() method improved 2023-09-18 10:21:03 +03:00
Vladimir Enchev
b6b8ce55c6 Fixed DataFilter OData filter when selecting all elements of IEnumerable
Fix #1156
2023-09-18 09:11:46 +03:00
Vladimir Enchev
1d3e5a60e2 Merge branch 'master' of https://github.com/radzenhq/radzen-blazor 2023-09-18 08:59:01 +03:00
Vladimir Enchev
b2397cfd54 Virtualized DataGrid sorting and cache improved 2023-09-18 08:58:51 +03:00
johanpolak
15ef3bdadb Allow Template in RadioButtonListItem (#1155)
Co-authored-by: Johan Polak | Camas IT bv <JohanPolak@camasit.nl>
2023-09-18 08:47:40 +03:00
Vladimir Enchev
c353e713cc Merge branch 'master' of https://github.com/radzenhq/radzen-blazor 2023-09-18 08:45:54 +03:00
Atanas Korchev
1eaaad320f Allow specific generic definitions. 2023-09-14 18:48:50 +03:00
Atanas Korchev
e0c0071d8b Enable RadzenComponentActivator only for .NET 5 or greater. 2023-09-14 18:35:56 +03:00
Atanas Korchev
0a7c274f33 Add component activator that allows replacing component intsances with custom ones. 2023-09-14 18:32:34 +03:00
yordanov
d4621f8b8a Update premium themes 2023-09-14 11:37:57 +03:00
yordanov
5b0c1fd16e Fix alignment in DataGrid column draggable hint 2023-09-14 11:31:58 +03:00
yordanov
6b5847f149 Update premium themes 2023-09-14 09:33:31 +03:00
yordanov
b227d89a01 Fix DataGrid group header spacing in compact mode 2023-09-14 09:24:48 +03:00
Vladimir Enchev
a4191556ea DataGrid RefreshDataAsync() method added 2023-09-14 05:24:12 +03:00
yordanov
a7d90c0b39 Fix Wrap option in RadzenStack demo 2023-09-13 19:37:22 +03:00
yordanov
6edef4ec97 Update premium themes 2023-09-13 19:00:10 +03:00
yordanov
17f7ae7daa Add today styles to DatePicker 2023-09-13 18:46:24 +03:00
Vladimir Enchev
03d33f2074 Version updated 2023-09-13 16:02:11 +03:00
Vladimir Enchev
8787d8ad43 DataGrid LoadSettings event added 2023-09-13 16:01:52 +03:00
Vladimir Enchev
69f98aa756 demo fixed 2023-09-13 15:20:24 +03:00
Vladimir Enchev
9620faafe1 version updated 2023-09-13 11:48:33 +03:00
Vladimir Enchev
2ba0b164fc DataGrid internal clear of the LoadData args cache imlemented 2023-09-13 11:48:11 +03:00
Vladimir Enchev
77b9b2e8ce DataGrid Reload() overload simplified 2023-09-13 10:50:42 +03:00
Vladimir Enchev
58be436aaa DataGrid LoadData args cache simplified 2023-09-13 10:21:32 +03:00
Vladimir Enchev
5995eb8b8e DataGrid should not call LoadData twice on first render when virtualized 2023-09-13 10:13:36 +03:00
Vladimir Enchev
0e4f942b15 Merge branch 'master' of https://github.com/radzenhq/radzen-blazor 2023-09-12 17:16:56 +03:00
Vladimir Enchev
c14f773ed4 DataGrid Reload() method overload added with ability to clear the cache 2023-09-12 17:16:46 +03:00
TimChen
3ef08a53d1 add icon sidebar demo (#1153) 2023-09-12 17:06:09 +03:00
Vladimir Enchev
67d32c5a96 Version updated 2023-09-12 10:20:48 +03:00
Vladimir Enchev
e351793043 DataGrid LoadData event calls optimized when virtualization is on 2023-09-12 10:14:50 +03:00
Vladimir Enchev
f0a987e7a2 Fixed UTC dates to work with fi-FI and dk-DK cultures 2023-09-12 08:42:47 +03:00
AlittaSakraf
c0354961f7 Update RadzenNumeric.razor.cs (#1149)
There is a bug: Uncaught ReferenceError: False is not defined
at HTMLInputElement.onblur
2023-09-11 19:24:32 +03:00
TimChen
4c8c8dcdab panel menu item add display style (#1147)
* panel menu item add display style

* Remove unnecessary DisplayStyle attributes
2023-09-11 19:23:43 +03:00
Vladimir Enchev
cae80096e1 DatePicker day render refactored 2023-09-08 09:55:12 +03:00
Vladimir Enchev
45d4fcc0bf DataFilter will clear FilterValue and disable input if operator is set to empty/null 2023-09-08 09:30:10 +03:00
Marek
da5380a472 Added columnPickerTitle (#1144)
Co-authored-by: Marek Mička <xmicka13@vutbr.cz>
2023-09-07 17:53:17 +03:00
Vladimir Enchev
b27544663e Version updated 2023-09-07 11:06:19 +03:00
Vladimir Enchev
75c35aa9e5 Popup should not be destroyed on dispose 2023-09-07 11:05:37 +03:00
Vladimir Enchev
ad0fd8d5c8 Fixed DropDown ClearSearchAfterSelection behavior
Fix #1143
2023-09-07 09:07:48 +03:00
Vladimir Enchev
c60cd1fabb DataGrid settings save/load of arrays fixed
Fixed #1139
2023-09-06 16:36:40 +03:00
kSacred
7cfb6258d5 Fix calling DataGrid Reload when loading settings with filter and page greater than 1. (#1141) 2023-09-06 10:18:43 +03:00
Vladimir Enchev
ff1bc2577f Version updated 2023-09-04 16:20:00 +03:00
Vladimir Enchev
07ab3621b3 Popup toggle logic fixed 2023-09-04 16:17:54 +03:00
Vladimir Enchev
0af3f3fcce Fixed DatePicker closed immediately after selecting a month or year from the drop-down lists when using PopupRenderMode.OnDemand
Fix #1138
2023-09-04 13:33:11 +03:00
Vladimir Enchev
cb8a70744d Cannot toggle visibility of Steps item 2023-09-04 11:51:16 +03:00
Vladimir Enchev
c6a8d3e251 ExpandMode removed from DataGrid self-referenced hierarchy demo 2023-09-04 10:11:17 +03:00
TimChen
d871292d39 Add TabsModify Demo (#1133)
* Add TabsModify

* Fix the tabs modify example
2023-09-04 09:32:20 +03:00
Vladimir Enchev
255febcd70 Selected item not retrieved properly when bound using LoadData with custom filtering 2023-09-01 14:46:16 +03:00
Vladimir Enchev
c7d8f77fb4 Version updated 2023-09-01 10:16:21 +03:00
Vladimir Enchev
248de4ef0f AddRadzenComponents() method used across demos 2023-09-01 10:16:13 +03:00
Vladimir Enchev
56ae5d2c33 Tooltip close logic fixed to not show tooltips with delay if Close() is invoked 2023-09-01 10:11:06 +03:00
Vladimir Enchev
2cc575d74b Avoid acessing DataGrid PageSize directly when loading settings 2023-08-29 17:00:28 +03:00
yordanov
b0b68d16a4 Update premium themes 2023-08-29 16:29:48 +03:00
Vladimir Enchev
45fd510e15 AddRadzenComponents() extension method added 2023-08-29 11:16:34 +03:00
Vladimir Enchev
0376a58374 Version updated 2023-08-29 09:45:16 +03:00
Vladimir Enchev
b1d1d2c7f8 DataGrid will not call LoadData in simple filter with virtualization enabled 2023-08-29 09:45:00 +03:00
Vladimir Enchev
6de14c91e4 Clear selected rows button added 2023-08-28 16:23:40 +03:00
Vladimir Enchev
a04cbeba78 Merge branch 'master' of https://github.com/radzenhq/radzen-blazor 2023-08-28 10:54:11 +03:00
Vladimir Enchev
82610e281d ContextMenu doesn't work for RadzenPanelMenuItem
Fix #1130
2023-08-28 10:54:02 +03:00
stlufred
e9b3213d8b Make icon used by data grid filter customizable (#1129) 2023-08-28 10:32:13 +03:00
mvoxland-MoorheadSchools
313ee50bf2 Indication for isNull/isNotNull in simple datagrid filter (#1127)
Added an Indication for when a datagrid (in simple mode)'s filter operator is set to either "is null" or "is not null". Before there was no way to see that any filters were applied until the popup was opened.
2023-08-28 10:26:22 +03:00
Vladimir Enchev
fca72e3fad Version updated 2023-08-24 10:12:54 +03:00
yordanov
97657da95d Update premium themes 2023-08-23 18:06:23 +03:00
Atanas Korchev
f32240ba65 RadzenHtmlEditor fires its Change event before updating the argument specified with @bind-Value. 2023-08-23 16:28:01 +03:00
yordanov
1d8d20a7d7 Keep base, light, and dark styles in a single base-styles-map for consistency across themes 2023-08-22 11:05:51 +03:00
Cosmatevs
5fba2685b1 Timeline: add missing light and dark styles (#1122) 2023-08-22 10:44:26 +03:00
AlittaSakraf
2c39551560 Update RadzenDataGridFilterMenu.razor (#1123)
If you use "FilterMode.SimpleWithMenu" and Grid Settings together, then the "Clear" button in the fitler menu, do not work, because there was a SaveSetting() calling in the ClearFilter function. (Always loaded the "last" settings, after the Clear button has pushed.
2023-08-22 09:31:58 +03:00
Vladimir Enchev
265ca8b433 themes updated 2023-08-21 15:36:25 +03:00
Vladimir Enchev
8c4b33ec17 Version updated 2023-08-21 15:28:40 +03:00
yordanov
937bf6f57a ShowValue should display ProgressBar label in Material and Fluent themes. Resolves #1119 2023-08-21 14:46:51 +03:00
Vladimir Enchev
e2f142ed28 DropDownDataGrid pager will not wrap if not needed 2023-08-21 13:44:08 +03:00
yordanov
9a835690aa Update Material Dark theme 2023-08-21 11:12:38 +03:00
Atanas Korchev
5f4ec1c446 Add the Appointment model in the demo. 2023-08-21 11:05:19 +03:00
Atanas Korchev
7b11516520 Update the MoreSelect documentation. 2023-08-21 11:05:19 +03:00
Atanas Korchev
4a6543b0c6 Add related files to the export demo. 2023-08-21 11:05:19 +03:00
Atanas Korchev
fa197c1b7f Dispose the editor and support csharp language syntax highlighting. 2023-08-21 11:05:19 +03:00
Cosmatevs
ab4ab7e63b Fix wobbly tab selection in Material theme – resolves #1116
To do: update Material Dark theme
2023-08-21 10:39:07 +03:00
Vladimir Enchev
b88a8e605a Test deleted since the DatePicker will treat now default(DateTime) as null 2023-08-21 10:08:53 +03:00
Vladimir Enchev
519d8fc64a DatePicker will treat default(DateTime) as null 2023-08-18 10:44:59 +03:00
Vladimir Enchev
8032fde262 demo updated 2023-08-18 09:06:23 +03:00
Vladimir Enchev
02b4b0b9b6 Version updated 2023-08-18 08:47:06 +03:00
Vladimir Enchev
933c820f20 RadzenNumeric defaults to min value on tab 2023-08-18 08:46:31 +03:00
Thorsten Liborius
8476fdb77f OpenAsync method signature changed to virtual to support unit testing (#1117)
Co-authored-by: Thorsten Liborius <thorsten.liborius@shkb.ch>
2023-08-18 08:05:31 +03:00
Vladimir Enchev
ae1f280062 DropDown, DropDownDataGrid and ListBox SearchText two-way binding support added 2023-08-17 16:38:48 +03:00
Vladimir Enchev
d58dd28051 AdditionalSourceCodePages set 2023-08-17 11:41:40 +03:00
Vladimir Enchev
a212382da6 DataGridFooterTotals demo improved 2023-08-17 11:33:34 +03:00
Vladimir Enchev
b1819ff755 Enabled warnings to be treated as errors
[BREAKING] DropDownDataGrid SearchText renamed to SearchTextPlaceholder
2023-08-16 12:20:55 +03:00
Cosmatevs
2317305f0e Switch: make clicking a label change a value of the corresponding switch (by Name property; as in the case of ordinary checkboxes) (#1115) 2023-08-15 16:28:26 +03:00
Vladimir Enchev
da5f7e27c4 Allow DataGrid settings to be loaded in OnInitialized() 2023-08-15 11:19:19 +03:00
Vladimir Enchev
4c4dd71195 Version updated 2023-08-11 08:48:22 +03:00
Vladimir Enchev
61c3d3c34a Virtualized DropDownDataGrid refresh after filter will not work properly in some cases 2023-08-11 08:45:10 +03:00
Vladimir Enchev
59d4e30469 Version updated 2023-08-11 07:59:19 +03:00
Cosmatevs
e0dd34df2b DataGrid: prevent sorting from being triggerred while resizing a reorderable column (#1109)
* DataGrid: give unique IDs to column resizers and column reorderers to avoid using wrong elements in js functions

* Typo fix
2023-08-11 07:58:47 +03:00
Cosmatevs
41366d9376 DataGrid: make headers and footers of frozen columns frozen just like cells are (fix to commit 2795413) (#1108) 2023-08-11 07:56:41 +03:00
Vladimir Enchev
1779b8d67e Version updated 2023-08-10 16:35:49 +03:00
Vladimir Enchev
b673cbe411 Load settings by Property/UniqueID improved 2023-08-10 16:35:41 +03:00
Vladimir Enchev
1a595c5043 DataGrid will no longer auto-generate column UniqueID and will save settings for columns only if Property or UniqueID is set 2023-08-10 16:30:52 +03:00
Vladimir Enchev
bce5ae88ee Version updated 2023-08-10 14:57:05 +03:00
Vladimir Enchev
b81d15cdef DataGrid will use column index instead GUID for UniqueID 2023-08-10 14:56:27 +03:00
Vladimir Enchev
ec6747ac09 Too early close of filter popup can cause improper filter 2023-08-10 13:51:45 +03:00
Vladimir Enchev
5cd35bbfb5 DatePicker should not allow dates outside of Min/Max on Ok button
Fix #1107
2023-08-10 11:10:27 +03:00
Vladimir Enchev
1b07509e18 Theme page simplified 2023-08-10 10:54:43 +03:00
Vladimir Enchev
35211b94db DataGrid CloseFilter() logic fixed with OnDemand FilterPopupRenderMode 2023-08-10 10:32:10 +03:00
yordanov
0e9338a0e4 Add Themes demo page 2023-08-10 09:07:40 +03:00
Vladimir Enchev
95b099d62c Added DataGrid self-reference hierarchy expanded class for indent
Fix #1104
2023-08-09 08:05:47 +03:00
yordanov
b295963d8d Update demos descriptions 2023-08-08 12:11:50 +03:00
Vladimir Enchev
884ca797d8 Version updated 2023-08-08 10:43:52 +03:00
Vasil Yordanov
3664b4acec Timeline component (#1103)
* Add RadzenTimeline component, styles and demos

---------

Co-authored-by: Atanas Korchev <akorchev@gmail.com>
2023-08-08 10:37:39 +03:00
Vladimir Enchev
95f33310bf Fixed RadzenTabs - selected tab styling incorrect with hidden tabs
Fix #1003
2023-08-07 11:41:17 +03:00
Vladimir Enchev
a1500051b9 Cascading data loaded on-demand 2023-08-07 11:24:51 +03:00
Vladimir Enchev
be1a6cc985 Added Save/Load settings support for DataGrid columns without Property
Fix #1058
2023-08-07 11:17:53 +03:00
Vladimir Enchev
32525a0204 RadzenNumeric inconsistently resets Value when out of Max/Min
Fixed #1098
2023-08-07 10:58:39 +03:00
Vladimir Enchev
8b64c8afd3 Fixed popup close logic
Fix #1086
2023-08-07 10:44:50 +03:00
stlufred
2795413fc1 Fix customizing style of in HeaderCellRender and FooterCellRender (#1102) 2023-08-07 10:11:48 +03:00
Vladimir Enchev
8db9fc3f17 other filtering demos improved to respect auto-filter setting in template filters 2023-08-01 11:08:49 +03:00
Vladimir Enchev
d7c2fb8a02 OrderID will respect auto-filter setting 2023-08-01 11:03:14 +03:00
Vladimir Enchev
6c9d09f6c3 Date only filtering demo added 2023-08-01 09:17:57 +03:00
Vladimir Enchev
1482fe3e1b RadzenNumeric added to DataGrid column filter template demo 2023-08-01 08:51:07 +03:00
Vladimir Enchev
c2f0422a68 Fixed DataGrid inner filter popups not closed properly 2023-07-31 17:17:04 +03:00
Vladimir Enchev
4b3a7af308 Version updated 2023-07-31 08:04:58 +03:00
Vladimir Enchev
7b2cd6e4b0 DataList Reload() fixed
Fix #1095
2023-07-31 08:04:28 +03:00
Vladimir Enchev
60dbe28dca Popup demo improved 2023-07-28 10:14:41 +03:00
Vladimir Enchev
3dde8c5905 Fixed DropDown, DropDownDataGrid and ListBox filtering input logic 2023-07-28 09:48:09 +03:00
Vladimir Enchev
9207ef357f Version updated 2023-07-27 10:58:49 +03:00
Vladimir Enchev
ce7ea27255 DataList Reload() fixed in case of virtualization 2023-07-27 10:54:36 +03:00
Vladimir Enchev
c3eb701c56 Search added to custom popup demo 2023-07-27 10:54:19 +03:00
Vladimir Enchev
180c1fe185 Popup component example added 2023-07-27 09:46:40 +03:00
Rogier Reedijk
9b3138102d Add ParseInput to DatePicker (#1090)
* Add ParseInput to DatePicker

* Add demo for DatePicker.ParseInput

---------

Co-authored-by: Rogier Reedijk <reedijkr@wigo4it.nl>
2023-07-26 18:02:51 +03:00
Thomas Knudsen
e43412c02f Use key directive for notifications (#1092)
Co-authored-by: Thomas H. Knudsen <thk@yco.dk>
2023-07-26 18:01:45 +03:00
Cosmatevs
a223fad28c RadzenDataGridColumn: handle non-px widths of frozen columns (#1076)
* DataGridColumn: handle non-px widths of frozen columns, simplify css style conditions

* DataGridColumn: simplify calculation of frozen column style
2023-07-25 20:32:30 +03:00
Vladimir Enchev
9ade31a813 Version updated 2023-07-25 10:08:37 +03:00
Vladimir Enchev
fd91024b8d DataFilter PropertiesCollection added similar to DataGrid ColumnsCollection 2023-07-25 09:30:36 +03:00
Vladimir Enchev
0d9526ed72 LoadStateAsync called multiple times in the demo
Fix #1083
2023-07-25 09:06:07 +03:00
Vladimir Enchev
d4e51a1b51 OData filtering of DateTime fixes for various cultures 2023-07-25 08:49:42 +03:00
nitrouscookies
ded26df5d0 DataFilter - Added AllowColumnFiltering (#1079)
Co-authored-by: dstillwell <dstillwell@moorheadschools.org>
2023-07-25 08:43:28 +03:00
kSacred
a3ba44771f Added "Show button" parameter to radzendatapicker. (#1075)
Allows to hide the button in the field and open popup datepicker when you click on the field with "input is allowed"

Co-authored-by: Sacred <s>
2023-07-25 08:43:07 +03:00
Cosmatevs
83f4ac980e DataGridColumnHeaderCell: make the resizing element fill the whole cell while resizing to prevent an accidental click on the cell and therefore an unexpected resort (#1082) 2023-07-25 08:40:49 +03:00
Ben Croughs
5da102c058 close event on x (#1085)
Co-authored-by: BC3 <bc3@telenet.be>
2023-07-25 08:39:20 +03:00
kSacred
27608327af Added SetFilterValueAsync method set column filter value and reload grid. Allows you to use the FilterTemplate without initializing an additional property. (#1087)
Co-authored-by: Sacred <s>
2023-07-25 08:38:56 +03:00
Vladimir Enchev
fcbbd53dd8 Version updated 2023-07-19 10:54:53 +03:00
Vladimir Enchev
76aaab319c Revert "switching from libsass to dartsass (#1068)"
This reverts commit f77ebe3af7.
2023-07-19 10:54:10 +03:00
yordanov
6ea6a46c15 Update premium themes 2023-07-19 09:47:34 +03:00
Victor Ureta
c0f3e62a10 Add MarkupString in RadzenFormField (#1071) 2023-07-18 19:56:41 +03:00
Vladimir Enchev
5f71660c7a version updated 2023-07-18 10:14:26 +03:00
Vladimir Enchev
e6b15de5a4 Merge branch 'master' of https://github.com/radzenhq/radzen-blazor 2023-07-18 10:11:09 +03:00
Vladimir Enchev
bf74569906 themes updated 2023-07-18 10:11:06 +03:00
Atanas Korchev
b70f1f84be Change the implementation of NoTools and rename it to ShowToolbar. 2023-07-18 10:08:24 +03:00
Dave Bagler
a2209e73fc Htmledit on input (#1070)
* adding a paramter for allow for no-tool HTMLEditors.

* Adding input event to the HTMLEditor
2023-07-18 09:38:08 +03:00
Dave Bagler
f77ebe3af7 switching from libsass to dartsass (#1068) 2023-07-18 09:37:31 +03:00
Cosmatevs
8c4370780d Progress bar circular component + progress bar extension (#1044)
Add RadzenProgressBarCircular component
2023-07-17 19:29:58 +03:00
Cosmatevs
e4b352f1ce DataGridColumn: Add ShowUpDownForNumericFilter function; rename the class file for hierarchy (#1065)
Demos/GataGridFilterApi: Use override of ShowUpDownForNumericFilter
2023-07-17 19:13:03 +03:00
Jimmy Ho
a679e33d54 fix AddButton not enable (#1066)
click AddButton, then click Edit/Delete button on the other row, how ever save/cancel, the AddButton still disable
2023-07-17 19:11:15 +03:00
Vladimir Enchev
e477ce3d9a Version updated 2023-07-14 12:17:17 +03:00
kSacred
f15d7ac445 Fix: enum dropdown beyond the edge of the column (#1061) 2023-07-14 09:42:47 +03:00
kSacred
d36af364bf Added custom text for null enum value in filter. Default value "No value" instead of "<null>". (#1062)
Co-authored-by: Sacred <s>
2023-07-14 09:41:41 +03:00
Vladimir Enchev
b0ebcf86e6 DropDownBase filtering enum by description support added 2023-07-14 09:40:49 +03:00
Atanas Korchev
247ec75c9e Scheduler does not display certain events in day and week view. 2023-07-13 20:08:11 +03:00
Atanas Korchev
3b43bf3579 Cannot edit demos that use other pages. 2023-07-13 14:10:10 +03:00
atafra92
2be6d5cdef add isLoading property to dropdown datagrid component (#1054)
* add isLoading property to dropdown datagrid component

* Revert "add isLoading property to dropdown datagrid component"

This reverts commit 7299939f7c.

* added isLoading property to dropdown datagrid component
2023-07-13 09:47:35 +03:00
kSacred
fef7526af4 Fix search with quotes in RadzenDataGrid filter (#1051) 2023-07-12 14:57:46 +03:00
yordanov
88ee26ecf8 Fix typo. Resolves #1053 2023-07-12 09:47:57 +03:00
Atanas Korchev
947c602cb0 A visual glitch appears when using StrokeWidth in RadzenPieSeries. 2023-07-07 09:35:51 +03:00
Ben Croughs
fd0cf4e4e3 do not hide 2 notification when clicking close (#1047)
Co-authored-by: BC3 <bc3@telenet.be>
2023-07-06 21:08:14 +03:00
foerdi
0d11bffa82 fixed PropertyAccess.GetProperty for complex property expressions (#1048)
RadzenDataGrid could not be filtered or sorted by colums with advanced
proprty expressions like function calls

Co-authored-by: Ferdinand Lange <lange@iftc.uni-hannover.de>
2023-07-06 08:45:05 +03:00
Vladimir Enchev
c9a9c48de3 Version updated 2023-07-03 19:47:06 +03:00
Vladimir Enchev
fbbcb58e3f DataGrid INotifyCollectionChanged support added 2023-06-30 11:40:06 +03:00
yordanov
ed9dbea34a Add Quickstart image 2023-06-28 11:21:37 +03:00
yordanov
9ccca42011 Add a Quickstart video to Get started page 2023-06-28 11:19:47 +03:00
dependabot[bot]
d7bc92e465 Bump System.Linq.Dynamic.Core from 1.2.22 to 1.3.0 in /Radzen.Blazor (#1041)
Bumps [System.Linq.Dynamic.Core](https://github.com/zzzprojects/System.Linq.Dynamic.Core) from 1.2.22 to 1.3.0.
- [Release notes](https://github.com/zzzprojects/System.Linq.Dynamic.Core/releases)
- [Changelog](https://github.com/zzzprojects/System.Linq.Dynamic.Core/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zzzprojects/System.Linq.Dynamic.Core/compare/v1.2.22...v1.3.0)

---
updated-dependencies:
- dependency-name: System.Linq.Dynamic.Core
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-28 10:48:38 +03:00
yordanov
5d29ebfde2 Update see in action link 2023-06-28 10:16:12 +03:00
Vladimir Enchev
efa14f2dcd DatePicker FormattedValue do not respect specified Culture 2023-06-26 14:47:07 +03:00
Vladimir Enchev
2e07802a05 Version updated 2023-06-26 11:13:05 +03:00
Vladimir Enchev
34a83a46d9 DataGrid column picker not closed properly when FilterPopupRenderMode=OnDemand
Fix #1039
2023-06-26 10:11:48 +03:00
Atanas Korchev
9db5c68a64 Fix wrong tag name in HelpPrerequirements.razor. 2023-06-26 09:18:58 +03:00
Atanas Korchev
5dac84c511 Add FocusAsync method to RadzenHtmlEditor. 2023-06-26 09:18:58 +03:00
yordanov
ce834c9b18 Update DataGrid footer totals and template demos 2023-06-23 18:20:07 +03:00
Atanas Korchev
0af5f626bc Make the anchors in RadzenText scroll the page. 2023-06-22 12:47:13 +03:00
Atanas Korchev
0d68186dfe The remember me text is missing when FormFieldVariant is set of RadzenLogin. 2023-06-22 10:15:29 +03:00
Vladimir Enchev
65e226d02d Version updated 2023-06-20 14:37:16 +03:00
Vladimir Enchev
15d0654cd7 FocusTrap not working on Dialog when last focusable component is RadzenDatePicker
Fix #1024
2023-06-20 14:36:43 +03:00
Vladimir Enchev
f7c36efab8 Not possible to close multiple nested dialogs using the Escape key
Fix #1026
2023-06-20 10:58:28 +03:00
Vladimir Enchev
09e372f37b dialogResizer disposed 2023-06-20 10:37:23 +03:00
Vladimir Enchev
a020e06c3d Dialog height/width should not be changed on drag but only on resize
Close #1032
2023-06-20 10:33:31 +03:00
Atanas Korchev
650f2caf42 Improve RadzenScheduler rendering algorithm to handle more cases. 2023-06-19 17:32:32 +03:00
Vladimir Enchev
bfaa5a9878 Fixed DataGrid doesn't show empty message with empty Data
Fix #1034
2023-06-19 09:55:49 +03:00
Vladimir Enchev
7d22fc727b PagedDataBoundComponent should not raise PageSizeChanged on firs render
Fix #1030
2023-06-19 09:50:27 +03:00
ChristianA1992
e78db0d549 Method to replace only the first occurence of a string (#1028)
There is a bug, if you column is called something like Car.ApiCar.Brand.
When the GetPropertyType method is run, it replaces all occurences of Car. which makes it so the column can't be filtered.
2023-06-16 15:13:45 +03:00
Vladimir Enchev
4a610d9868 Example fixed 2023-06-15 18:03:17 +03:00
yordanov
2c08ab1e52 Update premium themes 2023-06-15 17:24:38 +03:00
Vladimir Enchev
70c26493c4 text fixed 2023-06-15 17:18:45 +03:00
Vladimir Enchev
e5f45550d4 Version updated 2023-06-15 17:07:15 +03:00
Vladimir Enchev
80c196d863 DataFilter LoadData demo added 2023-06-15 17:06:29 +03:00
Vladimir Enchev
516ee4b762 DatePicker doesn't render correctly with PopupRenderMode.OnDemand
Fix #1025
2023-06-15 11:32:02 +03:00
Vladimir Enchev
7371e15ebb Numeric FormattedValue demo fixed
Fix #1022
2023-06-14 16:01:28 +03:00
Vladimir Enchev
b6f6f79c00 DateFilter in DataGrid can not be cleared by using backspace/delete
Fix #1023
2023-06-14 15:50:26 +03:00
Vladimir Enchev
d8dd38dcdd DataGrid column picker filtering made case-insensitive 2023-06-14 11:44:38 +03:00
yordanov
1384c2b477 Update new and updated demo badges 2023-06-14 10:43:35 +03:00
Vladimir Enchev
2006a44fdd DataGrid LoadData executed twice on filter
Fix #1020
2023-06-14 09:53:49 +03:00
yordanov
f7c04c9f7e Card Variant property added 2023-06-14 08:57:45 +03:00
yordanov
1dbb36bd77 Fix accordion border radius. Resolves #1018 2023-06-14 08:45:03 +03:00
yordanov
54cabebbfa Fix FormField label line-height. Resolves #995 2023-06-13 15:26:54 +03:00
Vladimir Enchev
f31c2296dd Version updated 2023-06-13 11:35:11 +03:00
Vladimir Enchev
6f66fd9597 DataGrid column FilterValueTemplate and SecondFilterValueTemplate properties added
Easily customize default DataGrid advanced filter with custom components for FilterValue/SecondFIlterValue. More generic than #1015. Close #1015.
2023-06-13 11:32:54 +03:00
Vladimir Enchev
8c33bd828a example fixed 2023-06-13 10:06:46 +03:00
Vladimir Enchev
068352de91 Numeric should not default to min when value type is nullable 2023-06-13 09:15:49 +03:00
Vladimir Enchev
f5c166906b Fixed DataGrid filtering with In/NotIn in combination with other filter 2023-06-13 08:38:36 +03:00
Atanas Korchev
514772f5c2 Fix typo. 2023-06-12 12:39:53 +03:00
Vladimir Enchev
2e0c2aa8bc DataGrid multiple sorting order saved/restored in proper order from Settings
Fix #1010
2023-06-09 12:05:43 +03:00
Vladimir Enchev
bfd641f1b1 DataGrid ColumnsPickerAllowFiltering property added 2023-06-08 08:00:29 +03:00
Vladimir Enchev
1c45af855d Version updated 2023-06-07 11:27:17 +03:00
Vasil Yordanov
5d7cf75bed New Material 3, Material 3 Dark and Fluent UI Dark premium themes (#1009)
* Update Stack, Row, and Column demos
* Reorder themes in theme picker
* Update premium themes
---------
Co-authored-by: Atanas Korchev <akorchev@gmail.com>
2023-06-07 11:26:29 +03:00
Vladimir Enchev
04ee23b7b5 DataGrid EmptyTemplate not shown with virtualization using LoadData
Fix #1008
2023-06-06 11:14:27 +03:00
yordanov
99c3c71be8 RadzenBody should have padding 2023-06-06 10:24:12 +03:00
yordanov
0c2fb54d14 Fix css selectors 2023-06-06 09:31:33 +03:00
yordanov
eaf875dfd5 Fix RadzenFormField label position with RadzenRadioButtonList or RadzenCheckBoxList inside 2023-06-06 09:14:02 +03:00
Victor Ureta
29e61087ac Add "Create" Button Functionality to RadzenDropDownDataGrid Component (#1007)
* Add

* Add

* Add

---------

Co-authored-by: Bikotoru Ryzen <you@example.com>
2023-06-06 09:02:44 +03:00
Vladimir Enchev
ef989e7909 Version updated 2023-06-05 16:21:59 +03:00
Vladimir Enchev
ab1fd464cf Fixed DataFilter remove filter 2023-06-05 16:21:13 +03:00
Vladimir Enchev
4a042b73b8 In/NotIn operators removed from DataFilter 2023-06-05 16:03:39 +03:00
Vladimir Enchev
b416a7de09 Use CultureInfo.InvariantCulture when parsing DateTime for OData 2023-06-05 15:29:52 +03:00
Vladimir Enchev
ebec631cde DataGrid Sorts collection exposed 2023-06-05 10:35:03 +03:00
Vladimir Enchev
cd6a751a68 DataGrid ColumnsPickerMaxSelectedLabels property added
Close #https://github.com/radzenhq/radzen-blazor/pull/1001
2023-06-02 09:40:37 +03:00
myfayyad
f90692b526 fix nested columns with grouping in datagrid (#998)
* Update RadzenDataGrid.razor to only show the collapse cell for first row not for nested columns rows header

* Update RadzenDataGridGroupRow.razor to have group record with colspan of visible columns and last leaf columns if nested

* Update RadzenDataGrid.razor remove unnecessary testing classes

* Update RadzenDataGridRow.razor fix nested columns grouping with allow composite cell

* Update RadzenDataGridHeaderCell.razor to allow grouping to composite cells

* fix count columns for colspan calcualtion if we have visible coulmns plus template columns

* modification to allow grouping "AllowCompositeDataCells, HideGroupedColumn" with composite columns when hidegroupedcolumn equal true and allowcompositecolumn equal true

* return example as it to not hide columns grouped by
2023-06-02 09:28:40 +03:00
Vladimir Enchev
b4ff72d424 demo fixed
Fix #999
2023-06-01 15:01:23 +03:00
yordanov
61de002e0e Update premium themes 2023-05-31 19:03:33 +03:00
yordanov
6c063c856c Update badge styles on demos homepage 2023-05-31 11:08:57 +03:00
yordanov
a075a0b29b Update text colors in Colors demo page 2023-05-31 11:04:35 +03:00
yordanov
0e85e70470 Fix rz-body padding 2023-05-31 10:45:57 +03:00
Vladimir Enchev
0e84d1dad1 Merge branch 'master' of https://github.com/radzenhq/radzen-blazor 2023-05-30 15:01:04 +03:00
Vladimir Enchev
092b3bf9c2 Version updated 2023-05-30 15:00:49 +03:00
OndrejUzovic
87cf688e27 ColorPicker opens and immediately closes #990 (#992) 2023-05-30 14:58:47 +03:00
yordanov
892cab3adf Add --rz-text-selection CSS variables 2023-05-30 10:13:26 +03:00
stlufred
c547f50dc8 Fixed Chart Click method (#991)
* Fixed chart Click method

- Was not using x and y parameters
- Use the same maximum distance as the tooltip (so that click and tooltip returns the same thing)
- Fixed xDelta and yDelta that were not considering MarginLeft and MarginTop

* Add ClickTolerance and TooltipTolerance.

---------

Co-authored-by: Atanas Korchev <akorchev@gmail.com>
2023-05-30 09:51:49 +03:00
yordanov
952bcecb12 Add text color to AutoComplete input 2023-05-29 17:13:11 +03:00
yordanov
1da97c3cd6 Add variable for text color in RadzenSidebar --rz-sidebar-color 2023-05-29 16:55:29 +03:00
blake-fm
b9abc13364 Loop parameters once during SetParametersAsync (#989)
Down from 6.
2023-05-29 12:18:01 +03:00
Vladimir Enchev
fcd2ffa630 Added support for collection filter in DataGrid column Property/FilterProperty and In/Not operators
Close https://github.com/radzenhq/radzen-blazor/pull/987
2023-05-29 09:44:50 +03:00
Atanas Korchev
1f769bc7b5 RadzenHtmlEditor does not show its value if it is initially hidden. 2023-05-26 17:29:30 +03:00
yordanov
e84a5ad62a RadzenBody should have transparent background if only child in RadzenLayout 2023-05-26 10:57:50 +03:00
yordanov
5a481aeb5e Fix text color in outlined and text RadzenButton variants 2023-05-26 10:54:37 +03:00
yordanov
24cea1d8d2 Update Close button styles in RadzenAlert 2023-05-26 10:31:04 +03:00
Vladimir Enchev
134f368953 Numeric FormattedValue should use specified Culture 2023-05-26 08:53:35 +03:00
yordanov
8a6749e38b Add --rz-panel-menu-padding custom CSS property 2023-05-25 16:05:53 +03:00
yordanov
0722639001 Update CSS classes and variables in layout components 2023-05-25 16:05:53 +03:00
Vladimir Enchev
e372dd8ddf index column removed 2023-05-25 14:30:52 +03:00
Vladimir Enchev
c66022eaa8 code fixed 2023-05-25 14:29:50 +03:00
Vladimir Enchev
3b873fc06c Demos data variables update to IQueryable 2023-05-25 14:28:57 +03:00
Vladimir Enchev
f2ac7cca28 Fixed deleting all text in Numeric leads to no data shown
Fix #974
2023-05-25 10:09:27 +03:00
Vladimir Enchev
d21d909de6 DropDown/DropDownDataGrid trailing separator removed 2023-05-25 08:36:17 +03:00
Dave Bagler
7c476ec104 Dialog wrapper class option. (#985)
* Adding WrapperCSSClass parameter to the dialog service.

* Updating container rendering and adding demo.
2023-05-25 08:11:47 +03:00
Atanas Korchev
3716772a06 Tooltip is always visible in Pie and Donut series. 2023-05-24 19:01:03 +03:00
Vladimir Enchev
c1100a5c62 demo reworked 2023-05-23 16:44:23 +03:00
Vladimir Enchev
0ae1332480 Template fixed 2023-05-23 16:30:20 +03:00
1869 changed files with 116029 additions and 48347 deletions

244
.editorconfig Normal file
View File

@@ -0,0 +1,244 @@
# Remove the line below if you want to inherit .editorconfig settings from higher directories
root = true
# C# files
[*.cs]
#### Core EditorConfig Options ####
# Indentation and spacing
indent_size = 4
indent_style = space
tab_width = 4
# New line preferences
end_of_line = crlf
insert_final_newline = false
#### .NET Code Actions ####
# Type members
dotnet_hide_advanced_members = false
dotnet_member_insertion_location = with_other_members_of_the_same_kind
dotnet_property_generation_behavior = prefer_throwing_properties
# Symbol search
dotnet_search_reference_assemblies = true
#### .NET Coding Conventions ####
# Organize usings
dotnet_separate_import_directive_groups = false
dotnet_sort_system_directives_first = false
file_header_template = unset
# this. and Me. preferences
dotnet_style_qualification_for_event = false
dotnet_style_qualification_for_field = false
dotnet_style_qualification_for_method = false
dotnet_style_qualification_for_property = false
# Language keywords vs BCL types preferences
dotnet_style_predefined_type_for_locals_parameters_members = true
dotnet_style_predefined_type_for_member_access = true
# Parentheses preferences
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity
dotnet_style_parentheses_in_other_operators = never_if_unnecessary
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity
# Modifier preferences
dotnet_style_require_accessibility_modifiers = for_non_interface_members
# Expression-level preferences
dotnet_prefer_system_hash_code = true
dotnet_style_coalesce_expression = true
dotnet_style_collection_initializer = true
dotnet_style_explicit_tuple_names = true
dotnet_style_namespace_match_folder = true
dotnet_style_null_propagation = true
dotnet_style_object_initializer = true
dotnet_style_operator_placement_when_wrapping = beginning_of_line
dotnet_style_prefer_auto_properties = true
dotnet_style_prefer_collection_expression = when_types_loosely_match
dotnet_style_prefer_compound_assignment = true
dotnet_style_prefer_conditional_expression_over_assignment = true
dotnet_style_prefer_conditional_expression_over_return = true
dotnet_style_prefer_foreach_explicit_cast_in_source = when_strongly_typed
dotnet_style_prefer_inferred_anonymous_type_member_names = true
dotnet_style_prefer_inferred_tuple_names = true
dotnet_style_prefer_is_null_check_over_reference_equality_method = true
dotnet_style_prefer_simplified_boolean_expressions = true
dotnet_style_prefer_simplified_interpolation = true
# Field preferences
dotnet_style_readonly_field = true
# Parameter preferences
dotnet_code_quality_unused_parameters = all
# Suppression preferences
dotnet_remove_unnecessary_suppression_exclusions = none
# New line preferences
dotnet_style_allow_multiple_blank_lines_experimental = true
dotnet_style_allow_statement_immediately_after_block_experimental = true
#### C# Coding Conventions ####
# var preferences
csharp_style_var_elsewhere = false
csharp_style_var_for_built_in_types = false
csharp_style_var_when_type_is_apparent = false
# Expression-bodied members
csharp_style_expression_bodied_accessors = true
csharp_style_expression_bodied_constructors = false
csharp_style_expression_bodied_indexers = true
csharp_style_expression_bodied_lambdas = true
csharp_style_expression_bodied_local_functions = false
csharp_style_expression_bodied_methods = false
csharp_style_expression_bodied_operators = false
csharp_style_expression_bodied_properties = true
# Pattern matching preferences
csharp_style_pattern_matching_over_as_with_null_check = true
csharp_style_pattern_matching_over_is_with_cast_check = true
csharp_style_prefer_extended_property_pattern = true
csharp_style_prefer_not_pattern = true
csharp_style_prefer_pattern_matching = true
csharp_style_prefer_switch_expression = true
# Null-checking preferences
csharp_style_conditional_delegate_call = true
# Modifier preferences
csharp_prefer_static_anonymous_function = true
csharp_prefer_static_local_function = true
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async
csharp_style_prefer_readonly_struct = true
csharp_style_prefer_readonly_struct_member = true
# Code-block preferences
csharp_prefer_braces = true
csharp_prefer_simple_using_statement = true
csharp_prefer_system_threading_lock = true
csharp_style_namespace_declarations = block_scoped
csharp_style_prefer_method_group_conversion = true
csharp_style_prefer_primary_constructors = true
csharp_style_prefer_top_level_statements = true
# Expression-level preferences
csharp_prefer_simple_default_expression = true
csharp_style_deconstructed_variable_declaration = true
csharp_style_implicit_object_creation_when_type_is_apparent = true
csharp_style_inlined_variable_declaration = true
csharp_style_prefer_index_operator = true
csharp_style_prefer_local_over_anonymous_function = true
csharp_style_prefer_null_check_over_type_check = true
csharp_style_prefer_range_operator = true
csharp_style_prefer_tuple_swap = true
csharp_style_prefer_utf8_string_literals = true
csharp_style_throw_expression = true
csharp_style_unused_value_assignment_preference = discard_variable
csharp_style_unused_value_expression_statement_preference = discard_variable
# 'using' directive preferences
csharp_using_directive_placement = outside_namespace
# New line preferences
csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true
csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true
csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true
csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true
csharp_style_allow_embedded_statements_on_same_line_experimental = true
#### C# Formatting Rules ####
# New line preferences
csharp_new_line_before_catch = true
csharp_new_line_before_else = true
csharp_new_line_before_finally = true
csharp_new_line_before_members_in_anonymous_types = true
csharp_new_line_before_members_in_object_initializers = true
csharp_new_line_before_open_brace = all
csharp_new_line_between_query_expression_clauses = true
# Indentation preferences
csharp_indent_block_contents = true
csharp_indent_braces = false
csharp_indent_case_contents = true
csharp_indent_case_contents_when_block = true
csharp_indent_labels = no_change
csharp_indent_switch_labels = true
# Space preferences
csharp_space_after_cast = false
csharp_space_after_colon_in_inheritance_clause = true
csharp_space_after_comma = true
csharp_space_after_dot = false
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_after_semicolon_in_for_statement = true
csharp_space_around_binary_operators = before_and_after
csharp_space_around_declaration_statements = false
csharp_space_before_colon_in_inheritance_clause = true
csharp_space_before_comma = false
csharp_space_before_dot = false
csharp_space_before_open_square_brackets = false
csharp_space_before_semicolon_in_for_statement = false
csharp_space_between_empty_square_brackets = false
csharp_space_between_method_call_empty_parameter_list_parentheses = false
csharp_space_between_method_call_name_and_opening_parenthesis = false
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
csharp_space_between_method_declaration_name_and_open_parenthesis = false
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = false
csharp_space_between_square_brackets = false
# Wrapping preferences
csharp_preserve_single_line_blocks = true
csharp_preserve_single_line_statements = true
#### Naming styles ####
# Naming rules
dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.types_should_be_pascal_case.symbols = types
dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
# Symbol specifications
dotnet_naming_symbols.interface.applicable_kinds = interface
dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.interface.required_modifiers =
dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.types.required_modifiers =
dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.non_field_members.required_modifiers =
# Naming styles
dotnet_naming_style.pascal_case.required_prefix =
dotnet_naming_style.pascal_case.required_suffix =
dotnet_naming_style.pascal_case.word_separator =
dotnet_naming_style.pascal_case.capitalization = pascal_case
dotnet_naming_style.begins_with_i.required_prefix = I
dotnet_naming_style.begins_with_i.required_suffix =
dotnet_naming_style.begins_with_i.word_separator =
dotnet_naming_style.begins_with_i.capitalization = pascal_case

View File

@@ -11,7 +11,7 @@ assignees: ''
IMPORTANT: Read this first!!!
1. If you own a Radzen Professional or Еnterprise subscription you can report your issue or ask us a question via email at info@radzen.com. Radzen staff will reply within 24 hours (Professional) or 16 hours (Enterprise)
1. If you own a Radzen Blazor subscription you can report your issue or ask us a question via email at info@radzen.com. Radzen staff will reply within 24 hours (Pro) or 16 hours (Team)
2. The Radzen staff guarantees a response to issues in this repo only to paid subscribers.
3. If you have a HOW TO question start a new forum thread in the Radzen Community forum: https://forum.radzen.com. Radzen staff will close issues that are HOWTO questions.
4. Please adhere to the issue template. Specify all the steps required to reproduce the issue or link a project which reproduces it easily (without requiring extra steps such as restoring a database).

View File

@@ -5,4 +5,4 @@ contact_links:
about: Please ask and answer questions here.
- name: Radzen Commercial Support
url: info@radzen.com
about: Radzen Professional or Enterprise subscribers can get dedicated support over email.
about: Radzen Blazor subscribers can get dedicated support over email.

View File

@@ -11,7 +11,7 @@ assignees: ''
IMPORTANT: Read this first!!!
1. If you own a Radzen Professional or Еnterprise subscription you can request your feature via email at info@radzen.com. Radzen staff will reply within 24 hours (Professional) or 16 hours (Enterprise)
1. If you own a Radzen Blazor subscription you can request your feature via email at info@radzen.com. Radzen staff will reply within 24 hours (Pro) or 16 hours (Team)
2. The Radzen staff guarantees a response to issues in this repo only to paid subscribers.
3. If you have a HOW TO question start a new forum thread in the Radzen Community forum: https://forum.radzen.com. Radzen staff will close issues that are HOWTO questions.
4. Please adhere to the issue template.

View File

@@ -15,11 +15,13 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v3
uses: actions/setup-dotnet@v4
with:
dotnet-version: 7.0.x
dotnet-version: 10.0.x
- name: Build
run: dotnet build Radzen.Blazor/Radzen.Blazor.csproj
- name: Test

7
.gitignore vendored
View File

@@ -341,3 +341,10 @@ Radzen.DocFX/_exported_templates
Radzen.DocFX/api/*.yml
!Radzen.DocFX/api/index.md
Radzen.DocFX/api/.manifest
Radzen.Blazor.min.js
/.claude
/SANKEY_PATTERN_COMPARISON.md
*.md
/.gitignore
/.gitignore
RadzenBlazorDemos/wwwroot/demos

View File

@@ -19,7 +19,7 @@ You can ask your question here. Please use the [Radzen.Blazor Components](https:
### Dedicated technical support
Radzen staff provides technical support with guaranteed response time to Radzen Professional and Enterprise subscribers. The pricing options are available [here](https://www.radzen.com/blazor-studio/pricing/).
Radzen staff provides technical support with guaranteed response time to Radzen Professional and Enterprise subscribers. The pricing options are available [here](https://www.radzen.com/pricing).
## How Can I Contribute?

View File

@@ -1,31 +1,23 @@
# syntax=docker/dockerfile:1
FROM mono:latest
ENV DOCFX_VER 2.58.4
RUN apt-get update && apt-get install unzip wget git -y && wget -q -P /tmp https://github.com/dotnet/docfx/releases/download/v${DOCFX_VER}/docfx.zip && \
mkdir -p /opt/docfx && \
unzip /tmp/docfx.zip -d /opt/docfx && \
echo '#!/bin/bash\nmono /opt/docfx/docfx.exe $@' > /usr/bin/docfx && \
chmod +x /usr/bin/docfx && \
rm -rf /tmp/*
FROM mcr.microsoft.com/dotnet/sdk:10.0
COPY Radzen.Blazor /app/Radzen.Blazor
COPY Radzen.DocFX /app/DocFX
COPY Radzen.DocFX /app/Radzen.DocFX
COPY RadzenBlazorDemos /app/RadzenBlazorDemos
COPY RadzenBlazorDemos.Host /app/RadzenBlazorDemos.Host
WORKDIR /app
RUN docfx DocFX/docfx.json
FROM mcr.microsoft.com/dotnet/sdk:7.0
COPY --from=0 /app/RadzenBlazorDemos.Host /app/RadzenBlazorDemos.Host
COPY --from=0 /app/RadzenBlazorDemos /app/RadzenBlazorDemos
RUN dotnet tool install -g docfx
ENV PATH="$PATH:/root/.dotnet/tools"
RUN wget https://dot.net/v1/dotnet-install.sh \
&& bash dotnet-install.sh --channel 8.0 --runtime dotnet --install-dir /usr/share/dotnet
RUN dotnet build -c Release Radzen.Blazor/Radzen.Blazor.csproj -f net8.0
RUN docfx Radzen.DocFX/docfx.json
WORKDIR /app/RadzenBlazorDemos.Host
RUN dotnet publish -c Release -o out
ENV ASPNETCORE_URLS http://*:5000
ENV ASPNETCORE_URLS=http://*:5000
WORKDIR /app/RadzenBlazorDemos.Host/out
ENTRYPOINT ["dotnet", "RadzenBlazorDemos.Host.dll"]

View File

@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2018-2023 Radzen Ltd
Copyright (c) 2018-2025 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

105
README.md
View File

@@ -1,39 +1,13 @@
![Radzen Blazor Components](RadzenBlazorDemos/wwwroot/images/radzen-blazor-components.png)
![Radzen Blazor Components](https://raw.githubusercontent.com/radzenhq/radzen-blazor/master/RadzenBlazorDemos/wwwroot/images/radzen-blazor-components.png)
<h1 align="center">
Radzen Blazor Components
</h1>
Radzen Blazor Components
========================
<p align="center">
A set of <strong>70+ free and open source</strong> native Blazor UI controls.
</p>
The most sophisticated free UI component library for Blazor, featuring **100+ native components**.
<div align="center">
See Online Demos or Read the Docs
[See Online Demos](https://blazor.radzen.com) or [Read the Docs](https://blazor.radzen.com/docs/)
</div>
---
<p align="center">
<a href="https://github.com/radzenhq/radzen-blazor/blob/master/LICENSE">
<img alt="License - MIT" src="https://img.shields.io/github/license/radzenhq/radzen-blazor?logo=github&style=for-the-badge" />
</a>
<a href="https://www.nuget.org/packages/Radzen.Blazor">
<img alt="NuGet Downloads" src="https://img.shields.io/nuget/dt/Radzen.Blazor?color=%232694F9&label=nuget%20downloads&logo=nuget&style=for-the-badge" />
</a>
<img alt="Last Commit" src="https://img.shields.io/github/last-commit/radzenhq/radzen-blazor?logo=github&style=for-the-badge" />
<a href="https://github.com/radzenhq/radzen-blazor/graphs/contributors">
<img alt="Github Contributors" src="https://img.shields.io/github/contributors/radzenhq/radzen-blazor?logo=github&style=for-the-badge" />
</a>
<a href="https://blazor.radzen.com">
<img alt="Radzen Blazor Components - Online Demos" src="https://img.shields.io/badge/demos-online-brightgreen?color=%232694F9&logo=blazor&style=for-the-badge" />
</a>
<a href="https://blazor.radzen.com/docs">
<img alt="Radzen Blazor Components - Documentation" src="https://img.shields.io/badge/docs-online-brightgreen?color=%232694F9&logo=blazor&style=for-the-badge" />
</a>
</p>
[![License - MIT](https://img.shields.io/github/license/radzenhq/radzen-blazor?logo=github&style=for-the-badge)](https://github.com/radzenhq/radzen-blazor/blob/master/LICENSE)[![NuGet Downloads](https://img.shields.io/nuget/dt/Radzen.Blazor?color=%232694F9&label=nuget%20downloads&logo=nuget&style=for-the-badge) ](https://www.nuget.org/packages/Radzen.Blazor)![Last Commit](https://img.shields.io/github/last-commit/radzenhq/radzen-blazor?logo=github&style=for-the-badge) [![Github Contributors](https://img.shields.io/github/contributors/radzenhq/radzen-blazor?logo=github&style=for-the-badge) ](https://github.com/radzenhq/radzen-blazor/graphs/contributors)[![Radzen Blazor Components - Online Demos](https://img.shields.io/badge/demos-online-brightgreen?color=%232694F9&logo=blazor&style=for-the-badge) ](https://blazor.radzen.com)[![Radzen Blazor Components - Documentation](https://img.shields.io/badge/docs-online-brightgreen?color=%232694F9&logo=blazor&style=for-the-badge)](https://blazor.radzen.com/docs)
## Why choose Radzen Blazor Components?
@@ -41,7 +15,7 @@
Radzen Blazor Components are open source and free for commercial use. You can install them from [NuGet](https://www.nuget.org/packages/Radzen.Blazor) or build your own copy from source.
Paid support is available as part of the [Radzen Professional subscription](https://www.radzen.com/blazor-studio/pricing/).
Paid support is available as part of the [Radzen Blazor subscription](https://www.radzen.com/pricing).
### :computer: Native
@@ -64,9 +38,9 @@ Everybody is welcome to visit the [Radzen Community forum](https://forum.radzen.
The Radzen team monitors the forum threads, but does not guarantee a response to every question. For guaranteed responses you may consider the dedicated support option.
Dedicated support for the Radzen Blazor Components is available as part of the [Radzen Professional subscription](https://www.radzen.com/blazor-studio/pricing/).
Dedicated support for the Radzen Blazor Components is available as part of the [Radzen Blazor subscription](https://www.radzen.com/pricing).
Our flagship product [Radzen Blazor Studio](https://www.radzen.com/blazor-studio/) provides tons of productivity features for Blazor developers:
Our flagship product [Radzen Blazor Studio](https://www.radzen.com/blazor-studio) provides tons of productivity features for Blazor developers:
- An industry-leading WYSIWYG Blazor design time canvas
- Scaffolding a complete CRUD applications from a database
- Built-in security - authentication and authorization
@@ -76,67 +50,8 @@ Our flagship product [Radzen Blazor Studio](https://www.radzen.com/blazor-studio
## Get started with Radzen Blazor Components
### 1. Install
Check the [getting started](https://blazor.radzen.com/get-started) instructions to start making awesome Blazor applications.
Radzen Blazor Components are distributed as a [Radzen.Blazor NuGet package](https://www.nuget.org/packages/Radzen.Blazor). You can add them to your project in one of the following ways
- Install the package from command line by running `dotnet add package Radzen.Blazor`
- Add the project from the Visual NuGet Package Manager
- Manually edit the .csproj file and add a project reference
### 2. Import the namespace
Open the `_Imports.razor` file of your Blazor application and add this line `@using Radzen.Blazor`.
### 3. Include a theme
Radzen Blazor components come with five free themes: Material, Standard, Default, Dark, Software and Humanistic.
To use a theme
1. Pick a theme. The [online demos](https://blazor.radzen.com/colors) allow you to preview the available options via the theme dropdown located in the header. The Material theme is currently selected by default.
1. Include the theme CSS file in your Blazor application. Open `Pages\_Layout.cshtml` (Blazor Server .NET 6), `Pages\_Host.cshtml` (Blazor Server .NET 7) or `wwwroot/index.html` (Blazor WebAssembly) and include a theme CSS file by adding this snippet
```html
<link rel="stylesheet" href="_content/Radzen.Blazor/css/material-base.css">
```
To include a different theme (i.e. Standard) just change the name of the CSS file:
```
<link rel="stylesheet" href="_content/Radzen.Blazor/css/standard-base.css">
```
### 4. Include Radzen.Blazor.js
Open `Pages\_Layout.cshtml` (Blazor Server .NET 6), `Pages\_Host.cshtml` (Blazor Server .NET 7) or `wwwroot/index.html` (Blazor WebAssembly) and include this snippet:
```html
<script src="_content/Radzen.Blazor/Radzen.Blazor.js"></script>
```
### 5. Use a component
Use any Radzen Blazor component by typing its tag name in a Blazor page e.g.
```html
<RadzenButton Text="Hi"></RadzenButton>
```
#### Data-binding a property
```razor
<RadzenButton Text=@text />
<RadzenTextBox @bind-Value=@text />
@code {
string text = "Hi";
}
```
#### Handing events
```razor
<RadzenButton Click="@ButtonClicked" Text="Hi"></RadzenButton>
@code {
void ButtonClicked()
{
}
}
```
## Run demos locally
Use Radzen.Server.sln to open and run demos as Blazor server application or Radzen.WebAssembly.sln to open and run demos as Blazor WebAssembly application. Radzen.sln has reference to all projects including tests.

View File

@@ -0,0 +1,171 @@
using Bunit;
using Microsoft.Extensions.DependencyInjection;
using Radzen;
using System;
using System.Net.Http;
using Microsoft.Extensions.Options;
using Xunit;
namespace Radzen.Blazor.Tests
{
public class AIChatTests
{
private void RegisterChatService(TestContext ctx)
{
// Register a dummy HttpClient and default options for AIChatService
ctx.Services.AddSingleton(new HttpClient());
ctx.Services.AddScoped<IAIChatService, AIChatService>();
}
[Fact]
public void RadzenAIChat_ShouldRenderWithDefaultProperties()
{
using var ctx = new TestContext();
RegisterChatService(ctx);
var component = ctx.RenderComponent<RadzenAIChat>();
Assert.Contains("Type your message...", component.Markup);
}
[Fact]
public void RadzenAIChat_ShouldRenderWithCustomTitle()
{
using var ctx = new TestContext();
RegisterChatService(ctx);
var component = ctx.RenderComponent<RadzenAIChat>(parameters => parameters
.Add(p => p.Title, "Custom Chat"));
Assert.Contains("Custom Chat", component.Markup);
}
[Fact]
public void RadzenAIChat_ShouldRenderWithCustomPlaceholder()
{
using var ctx = new TestContext();
RegisterChatService(ctx);
var component = ctx.RenderComponent<RadzenAIChat>(parameters => parameters
.Add(p => p.Placeholder, "Enter your message here..."));
Assert.Contains("Enter your message here...", component.Markup);
}
[Fact]
public void RadzenAIChat_ShouldRenderWithCustomEmptyMessage()
{
using var ctx = new TestContext();
RegisterChatService(ctx);
var component = ctx.RenderComponent<RadzenAIChat>(parameters => parameters
.Add(p => p.EmptyMessage, "No messages yet"));
Assert.Contains("No messages yet", component.Markup);
}
[Fact]
public void RadzenAIChat_ShouldShowClearButtonByDefault()
{
using var ctx = new TestContext();
RegisterChatService(ctx);
var component = ctx.RenderComponent<RadzenAIChat>();
Assert.Contains("rz-chat-header-clear", component.Markup);
}
[Fact]
public void RadzenAIChat_ShouldHideClearButtonWhenShowClearButtonIsFalse()
{
using var ctx = new TestContext();
RegisterChatService(ctx);
var component = ctx.RenderComponent<RadzenAIChat>(parameters => parameters
.Add(p => p.ShowClearButton, false));
Assert.DoesNotContain("clear_all", component.Markup);
}
[Fact]
public void RadzenAIChat_ShouldBeDisabledWhenDisabledIsTrue()
{
using var ctx = new TestContext();
RegisterChatService(ctx);
var component = ctx.RenderComponent<RadzenAIChat>(parameters => parameters
.Add(p => p.Disabled, true));
Assert.Contains("disabled", component.Markup);
}
[Fact]
public void RadzenAIChat_ShouldBeReadOnlyWhenReadOnlyIsTrue()
{
using var ctx = new TestContext();
RegisterChatService(ctx);
var component = ctx.RenderComponent<RadzenAIChat>(parameters => parameters
.Add(p => p.ReadOnly, true));
Assert.Contains("readonly", component.Markup);
}
[Fact]
public void RadzenAIChat_ShouldHaveCorrectCssClass()
{
using var ctx = new TestContext();
RegisterChatService(ctx);
var component = ctx.RenderComponent<RadzenAIChat>();
Assert.Contains("rz-chat", component.Markup);
}
[Fact]
public void ChatMessage_ShouldHaveCorrectProperties()
{
// Arrange
var message = new ChatMessage
{
Content = "Test message",
IsUser = true,
Timestamp = DateTime.Now
};
// Assert
Assert.NotEmpty(message.Id);
Assert.Equal("Test message", message.Content);
Assert.True(message.IsUser);
Assert.False(message.IsStreaming);
}
[Fact]
public void RadzenAIChat_AddMessage_ShouldAddMessageToList()
{
using var ctx = new TestContext();
RegisterChatService(ctx);
var component = ctx.RenderComponent<RadzenAIChat>();
// Act
component.Instance.AddMessage("Test message", true);
// Assert
var messages = component.Instance.GetMessages();
Assert.Single(messages);
Assert.Equal("Test message", messages[0].Content);
Assert.True(messages[0].IsUser);
}
[Fact]
public void RadzenAIChat_ClearChat_ShouldRemoveAllMessages()
{
using var ctx = new TestContext();
RegisterChatService(ctx);
var component = ctx.RenderComponent<RadzenAIChat>();
component.Instance.AddMessage("Test message 1", true);
component.Instance.AddMessage("Test message 2", false);
// Act
component.InvokeAsync(async () => await component.Instance.ClearChat()).Wait();
// Assert
Assert.Empty(component.Instance.GetMessages());
}
[Fact]
public void RadzenAIChat_ShouldLimitMessagesToMaxMessages()
{
using var ctx = new TestContext();
RegisterChatService(ctx);
var component = ctx.RenderComponent<RadzenAIChat>(parameters => parameters.Add(p => p.MaxMessages, 3));
component.Instance.AddMessage("Message 1", true);
component.Instance.AddMessage("Message 2", false);
component.Instance.AddMessage("Message 3", true);
component.Instance.AddMessage("Message 4", false);
// Assert
var messages = component.Instance.GetMessages();
Assert.Equal(3, messages.Count);
Assert.Equal("Message 2", messages[0].Content);
Assert.Equal("Message 3", messages[1].Content);
Assert.Equal("Message 4", messages[2].Content);
}
}
}

View File

@@ -0,0 +1,195 @@
using Bunit;
using Microsoft.AspNetCore.Components;
using Xunit;
namespace Radzen.Blazor.Tests
{
public class AccordionTests
{
[Fact]
public void Accordion_Renders_CssClasses()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenAccordion>();
Assert.Contains(@"rz-accordion", component.Markup);
}
[Fact]
public void Accordion_Renders_AccordionItems()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenAccordion>(parameters =>
{
parameters.Add(p => p.Items, builder =>
{
builder.OpenComponent<RadzenAccordionItem>(0);
builder.AddAttribute(1, "Text", "Test Item");
builder.AddAttribute(2, "ChildContent", (RenderFragment)(contentBuilder =>
{
contentBuilder.AddContent(0, "Item Content");
}));
builder.CloseComponent();
});
});
Assert.Contains("Test Item", component.Markup);
Assert.Contains("Item Content", component.Markup);
}
[Fact]
public void Accordion_Renders_ItemWithIcon()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenAccordion>(parameters =>
{
parameters.Add(p => p.Items, builder =>
{
builder.OpenComponent<RadzenAccordionItem>(0);
builder.AddAttribute(1, "Text", "Orders");
builder.AddAttribute(2, "Icon", "account_balance_wallet");
builder.AddAttribute(3, "ChildContent", (RenderFragment)(contentBuilder =>
{
contentBuilder.AddContent(0, "Order Details");
}));
builder.CloseComponent();
});
});
Assert.Contains("account_balance_wallet", component.Markup);
Assert.Contains("Orders", component.Markup);
}
[Fact]
public void Accordion_SingleExpand_OnlyOneItemExpanded()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenAccordion>(parameters =>
{
parameters.Add(p => p.Multiple, false); // Single expand mode
parameters.Add(p => p.Items, builder =>
{
// Add first item
builder.OpenComponent<RadzenAccordionItem>(0);
builder.AddAttribute(1, "Text", "Item 1");
builder.AddAttribute(2, "ChildContent", (RenderFragment)(b => b.AddContent(0, "Content 1")));
builder.CloseComponent();
// Add second item
builder.OpenComponent<RadzenAccordionItem>(1);
builder.AddAttribute(1, "Text", "Item 2");
builder.AddAttribute(2, "ChildContent", (RenderFragment)(b => b.AddContent(0, "Content 2")));
builder.CloseComponent();
});
});
Assert.False(component.Instance.Multiple);
}
[Fact]
public void Accordion_MultipleExpand_AllowsMultipleItemsExpanded()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenAccordion>(parameters =>
{
parameters.Add(p => p.Multiple, true);
});
Assert.True(component.Instance.Multiple);
}
[Fact]
public void Accordion_Raises_ExpandEvent()
{
using var ctx = new TestContext();
var expandRaised = false;
int expandedIndex = -1;
var component = ctx.RenderComponent<RadzenAccordion>(parameters =>
{
parameters.Add(p => p.Expand, EventCallback.Factory.Create<int>(this, (index) =>
{
expandRaised = true;
expandedIndex = index;
}));
parameters.Add(p => p.Items, builder =>
{
builder.OpenComponent<RadzenAccordionItem>(0);
builder.AddAttribute(1, "Text", "Test Item");
builder.AddAttribute(2, "ChildContent", (RenderFragment)(b => b.AddContent(0, "Content")));
builder.CloseComponent();
});
});
// Find and click the accordion header link to expand
var header = component.Find(".rz-accordion-header a");
header.Click();
Assert.True(expandRaised);
Assert.Equal(0, expandedIndex);
}
[Fact]
public void Accordion_Raises_CollapseEvent()
{
using var ctx = new TestContext();
var collapseRaised = false;
int collapsedIndex = -1;
var component = ctx.RenderComponent<RadzenAccordion>(parameters =>
{
parameters.Add(p => p.Collapse, EventCallback.Factory.Create<int>(this, (index) =>
{
collapseRaised = true;
collapsedIndex = index;
}));
parameters.Add(p => p.Items, builder =>
{
builder.OpenComponent<RadzenAccordionItem>(0);
builder.AddAttribute(1, "Text", "Test Item");
builder.AddAttribute(2, "Selected", true); // Start expanded
builder.AddAttribute(3, "ChildContent", (RenderFragment)(b => b.AddContent(0, "Content")));
builder.CloseComponent();
});
});
// Find and click the accordion header link to collapse
var header = component.Find(".rz-accordion-header a");
header.Click();
Assert.True(collapseRaised);
Assert.Equal(0, collapsedIndex);
}
[Fact]
public void Accordion_DisabledItem_CannotExpand()
{
using var ctx = new TestContext();
var expandRaised = false;
var component = ctx.RenderComponent<RadzenAccordion>(parameters =>
{
parameters.Add(p => p.Expand, EventCallback.Factory.Create<int>(this, (_) => expandRaised = true));
parameters.Add(p => p.Items, builder =>
{
builder.OpenComponent<RadzenAccordionItem>(0);
builder.AddAttribute(1, "Text", "Disabled Item");
builder.AddAttribute(2, "Disabled", true);
builder.AddAttribute(3, "ChildContent", (RenderFragment)(b => b.AddContent(0, "Content")));
builder.CloseComponent();
});
});
// Try to click the disabled item
var header = component.Find(".rz-accordion-header a");
header.Click();
// Event should not be raised for disabled item
Assert.False(expandRaised);
}
}
}

View File

@@ -0,0 +1,195 @@
using Bunit;
using Xunit;
namespace Radzen.Blazor.Tests
{
public class AlertTests
{
[Fact]
public void Alert_Renders_CssClasses()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenAlert>();
Assert.Contains(@"rz-alert", component.Markup);
}
[Fact]
public void Alert_Renders_AlertStyle()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenAlert>();
component.SetParametersAndRender(parameters => parameters.Add(p => p.AlertStyle, AlertStyle.Danger));
Assert.Contains("rz-danger", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add(p => p.AlertStyle, AlertStyle.Success));
Assert.Contains("rz-success", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add(p => p.AlertStyle, AlertStyle.Warning));
Assert.Contains("rz-warning", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add(p => p.AlertStyle, AlertStyle.Info));
Assert.Contains("rz-info", component.Markup);
}
[Fact]
public void Alert_Renders_Shade()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenAlert>();
component.SetParametersAndRender(parameters => parameters
.Add(p => p.AlertStyle, AlertStyle.Primary)
.Add(p => p.Shade, Shade.Lighter));
Assert.Contains("rz-shade-lighter", component.Markup);
component.SetParametersAndRender(parameters => parameters
.Add(p => p.AlertStyle, AlertStyle.Primary)
.Add(p => p.Shade, Shade.Darker));
Assert.Contains("rz-shade-darker", component.Markup);
}
[Fact]
public void Alert_Renders_Variant()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenAlert>();
component.SetParametersAndRender(parameters => parameters.Add(p => p.Variant, Variant.Outlined));
Assert.Contains("rz-variant-outlined", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add(p => p.Variant, Variant.Flat));
Assert.Contains("rz-variant-flat", component.Markup);
}
[Fact]
public void Alert_Renders_Title()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenAlert>();
var title = "Alert Title";
component.SetParametersAndRender(parameters => parameters.Add(p => p.Title, title));
Assert.Contains(title, component.Markup);
Assert.Contains("rz-alert-title", component.Markup);
}
[Fact]
public void Alert_Renders_Text()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenAlert>();
var text = "This is an alert message";
component.SetParametersAndRender(parameters => parameters.Add(p => p.Text, text));
Assert.Contains(text, component.Markup);
}
[Fact]
public void Alert_Renders_ChildContent()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenAlert>(parameters =>
{
parameters.AddChildContent("Custom alert content");
});
Assert.Contains("Custom alert content", component.Markup);
}
[Fact]
public void Alert_ShowIcon_DisplaysIcon()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenAlert>();
// Default should show icon
Assert.Contains("rz-alert-icon", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add(p => p.ShowIcon, false));
Assert.DoesNotContain("rz-alert-icon", component.Markup);
}
[Fact]
public void Alert_AllowClose_DisplaysCloseButton()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenAlert>();
// Default AllowClose is true - should contain a button with close icon
component.SetParametersAndRender(parameters => parameters.Add(p => p.AllowClose, true));
Assert.Contains("close", component.Markup);
Assert.Contains("rz-button", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add(p => p.AllowClose, false));
// When AllowClose is false, should not have close button
var buttonCount = System.Text.RegularExpressions.Regex.Matches(component.Markup, "rz-button").Count;
Assert.Equal(0, buttonCount);
}
[Fact]
public void Alert_CloseButton_RaisesCloseEvent()
{
using var ctx = new TestContext();
var closeRaised = false;
var component = ctx.RenderComponent<RadzenAlert>(parameters =>
{
parameters.Add(p => p.AllowClose, true);
parameters.Add(p => p.Close, () => closeRaised = true);
});
var closeButton = component.Find("button.rz-button");
closeButton.Click();
Assert.True(closeRaised);
}
[Fact]
public void Alert_Visible_ControlsDisplay()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenAlert>(parameters =>
{
parameters.Add(p => p.Visible, true);
parameters.Add(p => p.Text, "Visible Alert");
});
Assert.Contains("Visible Alert", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add(p => p.Visible, false));
// When not visible, component should not render
Assert.DoesNotContain("Visible Alert", component.Markup);
}
[Fact]
public void Alert_CloseButton_SetsVisibleToFalse()
{
using var ctx = new TestContext();
var visibleValue = true;
var component = ctx.RenderComponent<RadzenAlert>(parameters =>
{
parameters.Add(p => p.Visible, visibleValue);
parameters.Add(p => p.AllowClose, true);
parameters.Add(p => p.VisibleChanged, (bool value) => visibleValue = value);
});
var closeButton = component.Find("button.rz-button");
closeButton.Click();
Assert.False(visibleValue);
}
}
}

View File

@@ -1,9 +1,74 @@
using Xunit;
using Bunit;
using Xunit;
using System.Collections.Generic;
namespace Radzen.Blazor.Tests
{
public class AutoCompleteTests
{
[Fact]
public void AutoComplete_Renders_WithClassName()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenAutoComplete>();
Assert.Contains(@"rz-autocomplete", component.Markup);
}
[Fact]
public void AutoComplete_Renders_InputElement()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenAutoComplete>();
Assert.Contains("type=\"text\"", component.Markup);
Assert.Contains("rz-inputtext", component.Markup);
}
[Fact]
public void AutoComplete_Renders_Disabled()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenAutoComplete>(parameters =>
{
parameters.Add(p => p.Disabled, true);
});
Assert.Contains("disabled", component.Markup);
Assert.Contains("rz-state-disabled", component.Markup);
}
[Fact]
public void AutoComplete_Renders_Placeholder()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenAutoComplete>(parameters =>
{
parameters.Add(p => p.Placeholder, "Type to search...");
});
Assert.Contains("placeholder=\"Type to search...\"", component.Markup);
}
[Fact]
public void AutoComplete_Renders_WithData()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var data = new List<string> { "Apple", "Banana", "Cherry" };
var component = ctx.RenderComponent<RadzenAutoComplete>(parameters =>
{
parameters.Add(p => p.Data, data);
});
Assert.Contains("rz-autocomplete-panel", component.Markup);
}
[Fact]
public void AutoComplete_Enum_Converts_To_Attr_Value()
{

View File

@@ -30,7 +30,7 @@ namespace Radzen.Blazor.Tests
component.SetParametersAndRender(parameters => parameters.Add(p => p.Icon, icon));
Assert.Contains(@$"<i class=""rz-button-icon-left rzi"">{icon}</i>", component.Markup);
Assert.Contains(@$"<i class=""notranslate rz-button-icon-left rzi"">{icon}</i>", component.Markup);
}
[Fact]
@@ -48,7 +48,7 @@ namespace Radzen.Blazor.Tests
);
// does not render the actual icon when busy
Assert.DoesNotContain(@$"<i class=""rz-button-icon-left rzi"">{icon}</i>", component.Markup);
Assert.DoesNotContain(@$"<i class=""notranslate rz-button-icon-left rzi"">{icon}</i>", component.Markup);
// renders the icon with busy spin animation
Assert.Contains(@"<i style=""animation: rotation", component.Markup);
@@ -71,7 +71,7 @@ namespace Radzen.Blazor.Tests
parameters.Add(p => p.Icon, icon);
});
Assert.Contains(@$"<i class=""rz-button-icon-left rzi"">{icon}</i>", component.Markup);
Assert.Contains(@$"<i class=""notranslate rz-button-icon-left rzi"">{icon}</i>", component.Markup);
Assert.Contains(@$"<span class=""rz-button-text"">{text}</span>", component.Markup);
}
@@ -86,7 +86,7 @@ namespace Radzen.Blazor.Tests
component.SetParametersAndRender(parameters => parameters.Add(p => p.Image, image));
Assert.Contains(@$"<img class=""rz-button-icon-left rzi"" src=""{image}"" />", component.Markup);
Assert.Contains(@$"<img class=""notranslate rz-button-icon-left rzi"" src=""{image}"" alt=""button"" />", component.Markup);
}
[Fact]
@@ -103,9 +103,10 @@ namespace Radzen.Blazor.Tests
{
parameters.Add(p => p.Text, text);
parameters.Add(p => p.Image, image);
parameters.Add(p => p.ImageAlternateText, text);
});
Assert.Contains(@$"<img class=""rz-button-icon-left rzi"" src=""{image}"" />", component.Markup);
Assert.Contains(@$"<img class=""notranslate rz-button-icon-left rzi"" src=""{image}"" alt=""{text}"" />", component.Markup);
Assert.Contains(@$"<span class=""rz-button-text"">{text}</span>", component.Markup);
}

View File

@@ -0,0 +1,46 @@
using Bunit;
using Xunit;
namespace Radzen.Blazor.Tests
{
public class CardTests
{
[Fact]
public void Card_Renders_WithClassName()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenCard>();
Assert.Contains(@"rz-card", component.Markup);
}
[Fact]
public void Card_Renders_ChildContent()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenCard>(parameters =>
{
parameters.AddChildContent("<div>Card Content</div>");
});
Assert.Contains("Card Content", component.Markup);
}
[Fact]
public void Card_Renders_Variant()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenCard>();
component.SetParametersAndRender(parameters => parameters.Add(p => p.Variant, Variant.Outlined));
Assert.Contains("rz-variant-outlined", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add(p => p.Variant, Variant.Filled));
Assert.Contains("rz-variant-filled", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add(p => p.Variant, Variant.Flat));
Assert.Contains("rz-variant-flat", component.Markup);
}
}
}

View File

@@ -0,0 +1,173 @@
using Bunit;
using Microsoft.AspNetCore.Components;
using Xunit;
namespace Radzen.Blazor.Tests
{
public class CarouselTests
{
[Fact]
public void Carousel_Renders_WithClassName()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenCarousel>();
Assert.Contains(@"rz-carousel", component.Markup);
}
[Fact]
public void Carousel_Renders_AllowPaging_True()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenCarousel>(parameters =>
{
parameters.Add(p => p.AllowPaging, true);
parameters.Add(p => p.Items, builder =>
{
builder.OpenComponent<RadzenCarouselItem>(0);
builder.AddAttribute(1, "ChildContent", (RenderFragment)(b => b.AddContent(0, "Slide 1")));
builder.CloseComponent();
builder.OpenComponent<RadzenCarouselItem>(2);
builder.AddAttribute(3, "ChildContent", (RenderFragment)(b => b.AddContent(0, "Slide 2")));
builder.CloseComponent();
});
});
Assert.Contains("rz-carousel-pager-button", component.Markup);
}
[Fact]
public void Carousel_Renders_AllowPaging_False()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenCarousel>(parameters =>
{
parameters.Add(p => p.AllowPaging, false);
parameters.Add(p => p.Items, builder =>
{
builder.OpenComponent<RadzenCarouselItem>(0);
builder.AddAttribute(1, "ChildContent", (RenderFragment)(b => b.AddContent(0, "Slide 1")));
builder.CloseComponent();
});
});
Assert.DoesNotContain("rz-carousel-pager-button", component.Markup);
}
[Fact]
public void Carousel_Renders_AllowNavigation_True()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenCarousel>(parameters =>
{
parameters.Add(p => p.AllowNavigation, true);
});
Assert.Contains("rz-carousel-prev", component.Markup);
Assert.Contains("rz-carousel-next", component.Markup);
}
[Fact]
public void Carousel_Renders_AllowNavigation_False()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenCarousel>(parameters =>
{
parameters.Add(p => p.AllowNavigation, false);
});
Assert.DoesNotContain("rz-carousel-prev", component.Markup);
Assert.DoesNotContain("rz-carousel-next", component.Markup);
Assert.Contains("rz-carousel-no-navigation", component.Markup);
}
[Fact]
public void Carousel_Renders_PagerPosition_Top()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenCarousel>(parameters =>
{
parameters.Add(p => p.PagerPosition, PagerPosition.Top);
parameters.Add(p => p.AllowPaging, true);
parameters.Add(p => p.Items, builder =>
{
builder.OpenComponent<RadzenCarouselItem>(0);
builder.AddAttribute(1, "ChildContent", (RenderFragment)(b => b.AddContent(0, "Slide")));
builder.CloseComponent();
});
});
Assert.Contains("rz-carousel-pager-top", component.Markup);
}
[Fact]
public void Carousel_Renders_PagerPosition_Bottom()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenCarousel>(parameters =>
{
parameters.Add(p => p.PagerPosition, PagerPosition.Bottom);
parameters.Add(p => p.AllowPaging, true);
parameters.Add(p => p.Items, builder =>
{
builder.OpenComponent<RadzenCarouselItem>(0);
builder.AddAttribute(1, "ChildContent", (RenderFragment)(b => b.AddContent(0, "Slide")));
builder.CloseComponent();
});
});
Assert.Contains("rz-carousel-pager-bottom", component.Markup);
}
[Fact]
public void Carousel_Renders_PagerPosition_TopAndBottom()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenCarousel>(parameters =>
{
parameters.Add(p => p.PagerPosition, PagerPosition.TopAndBottom);
parameters.Add(p => p.AllowPaging, true);
parameters.Add(p => p.Items, builder =>
{
builder.OpenComponent<RadzenCarouselItem>(0);
builder.AddAttribute(1, "ChildContent", (RenderFragment)(b => b.AddContent(0, "Slide")));
builder.CloseComponent();
});
});
Assert.Contains("rz-carousel-pager-top", component.Markup);
Assert.Contains("rz-carousel-pager-bottom", component.Markup);
}
[Fact]
public void Carousel_Renders_PagerOverlay_True()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenCarousel>(parameters =>
{
parameters.Add(p => p.PagerOverlay, true);
});
Assert.Contains("rz-carousel-pager-overlay", component.Markup);
}
[Fact]
public void Carousel_Renders_PagerOverlay_False()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenCarousel>(parameters =>
{
parameters.Add(p => p.PagerOverlay, false);
});
Assert.DoesNotContain("rz-carousel-pager-overlay", component.Markup);
}
}
}

View File

@@ -3,6 +3,7 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Bunit;
using Microsoft.Extensions.DependencyInjection;
using Radzen.Blazor.Rendering;
using Xunit;
using Xunit.Abstractions;
@@ -23,6 +24,9 @@ public class ChartTests
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.Setup<Rect>("Radzen.createChart", _ => true).SetResult(new Rect {Left = 0, Top = 0, Width = 200, Height = 200});
ctx.Services.AddScoped<TooltipService>();
ctx.JSInterop.SetupVoid("Radzen.openChartTooltip", _ => true);
ctx.RenderComponent<RadzenChartTooltip>();
var seriesData = Enumerable.Range(0, 5000).Select(i => new Point { X = i, Y = i });
var chart = ctx.RenderComponent<RadzenChart>(chartParameters =>
@@ -42,12 +46,12 @@ public class ChartTests
})));
var stopwatch = Stopwatch.StartNew();
foreach (var _ in Enumerable.Range(0, 10))
foreach (var invocation in Enumerable.Range(0, 10))
{
await chart.InvokeAsync(() => chart.Instance.MouseMove(100, 80));
Assert.Contains("<div class=\"rz-chart-tooltip", chart.Markup);
Assert.Equal((invocation + 1) * 2, ctx.JSInterop.Invocations.Count(x => x.Identifier == "Radzen.openChartTooltip"));
await chart.InvokeAsync(() => chart.Instance.MouseMove(0, 0));
Assert.DoesNotContain("<div class=\"rz-chart-tooltip", chart.Markup);
Assert.Equal(invocation + 1, ctx.JSInterop.Invocations.Count(x => x.Identifier == "Radzen.closeTooltip"));
}
output.WriteLine($"Time took: {stopwatch.Elapsed}");
}

View File

@@ -0,0 +1,369 @@
using Bunit;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.DependencyInjection;
using Radzen.Blazor;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Xunit;
namespace Radzen.Blazor.Tests
{
public class ChatTests
{
[Fact]
public void RadzenChat_ShouldRenderWithTitle()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenChat>(parameters => parameters
.Add(p => p.Title, "Test Chat")
.Add(p => p.CurrentUserId, "user1")
.Add(p => p.Users, new List<ChatUser>())
.Add(p => p.Messages, new List<ChatMessage>())
);
Assert.Contains("Test Chat", component.Markup);
}
[Fact]
public void RadzenChat_ShouldShowEmptyMessageWhenNoMessages()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenChat>(parameters => parameters
.Add(p => p.Title, "Test Chat")
.Add(p => p.CurrentUserId, "user1")
.Add(p => p.Users, new List<ChatUser>())
.Add(p => p.Messages, new List<ChatMessage>())
.Add(p => p.EmptyMessage, "No messages yet!")
);
Assert.Contains("No messages yet!", component.Markup);
}
[Fact]
public void RadzenChat_ShouldDisplayMessages()
{
var messages = new List<ChatMessage>
{
new ChatMessage { Content = "Hello", UserId = "user1", Timestamp = DateTime.Now },
new ChatMessage { Content = "Hi there!", UserId = "user2", Timestamp = DateTime.Now }
};
var users = new List<ChatUser>
{
new ChatUser { Id = "user1", Name = "John" },
new ChatUser { Id = "user2", Name = "Jane" }
};
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenChat>(parameters => parameters
.Add(p => p.Title, "Test Chat")
.Add(p => p.CurrentUserId, "user1")
.Add(p => p.Users, users)
.Add(p => p.Messages, messages)
);
Assert.Contains("Hello", component.Markup);
Assert.Contains("Hi there!", component.Markup);
}
[Fact]
public void RadzenChat_ShouldShowUsersInHeader()
{
var users = new List<ChatUser>
{
new ChatUser { Id = "user1", Name = "John" },
new ChatUser { Id = "user2", Name = "Jane" }
};
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenChat>(parameters => parameters
.Add(p => p.Title, "Test Chat")
.Add(p => p.CurrentUserId, "user1")
.Add(p => p.Users, users)
.Add(p => p.Messages, new List<ChatMessage>())
.Add(p => p.ShowUsers, true)
);
Assert.Contains("John", component.Markup);
Assert.Contains("Jane", component.Markup);
}
[Fact]
public void RadzenChat_ShouldShowUserNamesAboveMessages()
{
var messages = new List<ChatMessage>
{
new ChatMessage { Content = "Hello", UserId = "user2", Timestamp = DateTime.Now }
};
var users = new List<ChatUser>
{
new ChatUser { Id = "user1", Name = "John" },
new ChatUser { Id = "user2", Name = "Jane" }
};
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenChat>(parameters => parameters
.Add(p => p.Title, "Test Chat")
.Add(p => p.CurrentUserId, "user1")
.Add(p => p.Users, users)
.Add(p => p.Messages, messages)
.Add(p => p.ShowUserNames, true)
);
Assert.Contains("Jane", component.Markup);
}
[Fact]
public void RadzenChat_ShouldShowClearButtonWhenEnabled()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenChat>(parameters => parameters
.Add(p => p.Title, "Test Chat")
.Add(p => p.CurrentUserId, "user1")
.Add(p => p.Users, new List<ChatUser>())
.Add(p => p.Messages, new List<ChatMessage>())
.Add(p => p.ShowClearButton, true)
);
var clearButton = component.Find(".rz-chat-header-clear");
Assert.NotNull(clearButton);
}
[Fact]
public void RadzenChat_ShouldNotShowClearButtonWhenDisabled()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenChat>(parameters => parameters
.Add(p => p.Title, "Test Chat")
.Add(p => p.CurrentUserId, "user1")
.Add(p => p.Users, new List<ChatUser>())
.Add(p => p.Messages, new List<ChatMessage>())
.Add(p => p.ShowClearButton, false)
);
var clearButton = component.FindAll(".rz-chat-header-clear");
Assert.Empty(clearButton);
}
[Fact]
public void RadzenChat_ShouldLimitVisibleUsers()
{
var users = new List<ChatUser>
{
new ChatUser { Id = "user1", Name = "John" },
new ChatUser { Id = "user2", Name = "Jane" },
new ChatUser { Id = "user3", Name = "Bob" },
new ChatUser { Id = "user4", Name = "Alice" },
new ChatUser { Id = "user5", Name = "Charlie" },
new ChatUser { Id = "user6", Name = "David" }
};
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenChat>(parameters => parameters
.Add(p => p.Title, "Test Chat")
.Add(p => p.CurrentUserId, "user1")
.Add(p => p.Users, users)
.Add(p => p.Messages, new List<ChatMessage>())
.Add(p => p.ShowUsers, true)
.Add(p => p.MaxVisibleUsers, 3)
);
// Should show "+3" for the remaining users
Assert.Contains("+3", component.Markup);
}
[Fact]
public void RadzenChat_ShouldShowUserMessagesOnRight()
{
var messages = new List<ChatMessage>
{
new ChatMessage { Content = "My message", UserId = "user1", Timestamp = DateTime.Now }
};
var users = new List<ChatUser>
{
new ChatUser { Id = "user1", Name = "John" }
};
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenChat>(parameters => parameters
.Add(p => p.Title, "Test Chat")
.Add(p => p.CurrentUserId, "user1")
.Add(p => p.Users, users)
.Add(p => p.Messages, messages)
);
var userMessage = component.Find(".rz-chat-message-user");
Assert.NotNull(userMessage);
}
[Fact]
public void RadzenChat_ShouldShowUserMessagesOnLeft()
{
var messages = new List<ChatMessage>
{
new ChatMessage { Content = "Other message", UserId = "user2", Timestamp = DateTime.Now }
};
var users = new List<ChatUser>
{
new ChatUser { Id = "user1", Name = "John" },
new ChatUser { Id = "user2", Name = "Jane" }
};
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenChat>(parameters => parameters
.Add(p => p.Title, "Test Chat")
.Add(p => p.CurrentUserId, "user1")
.Add(p => p.Users, users)
.Add(p => p.Messages, messages)
);
var participantMessage = component.Find(".rz-chat-message-participant");
Assert.NotNull(participantMessage);
}
[Fact]
public void RadzenChat_ShouldShowAvatarInitials()
{
var users = new List<ChatUser>
{
new ChatUser { Id = "user1", Name = "John Doe" }
};
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenChat>(parameters => parameters
.Add(p => p.Title, "Test Chat")
.Add(p => p.CurrentUserId, "user1")
.Add(p => p.Users, users)
.Add(p => p.Messages, new List<ChatMessage>())
.Add(p => p.ShowUsers, true)
);
Assert.Contains("JD", component.Markup);
}
[Fact]
public void RadzenChat_ShouldShowAvatarImageWhenProvided()
{
var users = new List<ChatUser>
{
new ChatUser { Id = "user1", Name = "John", AvatarUrl = "https://example.com/avatar.jpg" }
};
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenChat>(parameters => parameters
.Add(p => p.Title, "Test Chat")
.Add(p => p.CurrentUserId, "user1")
.Add(p => p.Users, users)
.Add(p => p.Messages, new List<ChatMessage>())
.Add(p => p.ShowUsers, true)
);
var avatarImage = component.Find(".rz-chat-participant-image");
Assert.NotNull(avatarImage);
Assert.Equal("https://example.com/avatar.jpg", avatarImage.GetAttribute("src"));
}
[Fact]
public void RadzenChat_ShouldBeDisabledWhenDisabled()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenChat>(parameters => parameters
.Add(p => p.Title, "Test Chat")
.Add(p => p.CurrentUserId, "user1")
.Add(p => p.Users, new List<ChatUser>())
.Add(p => p.Messages, new List<ChatMessage>())
.Add(p => p.Disabled, true)
);
var textarea = component.Find(".rz-chat-textarea");
Assert.True(textarea.HasAttribute("disabled"));
}
[Fact]
public void RadzenChat_ShouldBeReadOnlyWhenReadOnly()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenChat>(parameters => parameters
.Add(p => p.Title, "Test Chat")
.Add(p => p.CurrentUserId, "user1")
.Add(p => p.Users, new List<ChatUser>())
.Add(p => p.Messages, new List<ChatMessage>())
.Add(p => p.ReadOnly, true)
);
var textarea = component.Find(".rz-chat-textarea");
Assert.True(textarea.HasAttribute("readonly"));
}
[Fact]
public void RadzenChat_ShouldShowCustomPlaceholder()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenChat>(parameters => parameters
.Add(p => p.Title, "Test Chat")
.Add(p => p.CurrentUserId, "user1")
.Add(p => p.Users, new List<ChatUser>())
.Add(p => p.Messages, new List<ChatMessage>())
.Add(p => p.Placeholder, "Custom placeholder")
);
var textarea = component.Find(".rz-chat-textarea");
Assert.Equal("Custom placeholder", textarea.GetAttribute("placeholder"));
}
[Fact]
public void RadzenChat_ShouldShowStreamingIndicator()
{
var messages = new List<ChatMessage>
{
new ChatMessage { Content = "Streaming message", UserId = "user1", IsStreaming = true, Timestamp = DateTime.Now }
};
var users = new List<ChatUser>
{
new ChatUser { Id = "user1", Name = "John" }
};
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenChat>(parameters => parameters
.Add(p => p.Title, "Test Chat")
.Add(p => p.CurrentUserId, "user1")
.Add(p => p.Users, users)
.Add(p => p.Messages, messages)
);
var streamingIcon = component.Find(".rz-chat-message-streaming-icon");
Assert.NotNull(streamingIcon);
}
[Fact]
public void RadzenChat_ShouldShowMessageTimestamps()
{
var timestamp = DateTime.Now.AddHours(-1);
var messages = new List<ChatMessage>
{
new ChatMessage { Content = "Test message", UserId = "user1", Timestamp = timestamp }
};
var users = new List<ChatUser>
{
new ChatUser { Id = "user1", Name = "John" }
};
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenChat>(parameters => parameters
.Add(p => p.Title, "Test Chat")
.Add(p => p.CurrentUserId, "user1")
.Add(p => p.Users, users)
.Add(p => p.Messages, messages)
);
Assert.Contains(timestamp.ToString("HH:mm"), component.Markup);
}
}
}

View File

@@ -0,0 +1,168 @@
using Bunit;
using Xunit;
using System.Collections.Generic;
namespace Radzen.Blazor.Tests
{
public class CheckBoxListTests
{
class Item
{
public int Id { get; set; }
public string Name { get; set; }
public bool Disabled { get; set; }
}
[Fact]
public void CheckBoxList_Renders_WithClassName()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenCheckBoxList<int>>();
Assert.Contains(@"rz-checkbox-list", component.Markup);
}
[Fact]
public void CheckBoxList_Renders_WithData()
{
using var ctx = new TestContext();
var data = new List<string> { "Option 1", "Option 2", "Option 3" };
var component = ctx.RenderComponent<RadzenCheckBoxList<string>>(parameters =>
{
parameters.Add(p => p.Data, data);
});
Assert.Contains("Option 1", component.Markup);
Assert.Contains("Option 2", component.Markup);
Assert.Contains("Option 3", component.Markup);
}
[Fact]
public void CheckBoxList_Renders_WithCustomTextValueProperties()
{
using var ctx = new TestContext();
var data = new List<Item>
{
new Item { Id = 1, Name = "First" },
new Item { Id = 2, Name = "Second" }
};
var component = ctx.RenderComponent<RadzenCheckBoxList<int>>(parameters =>
{
parameters.Add(p => p.Data, data);
parameters.Add(p => p.TextProperty, "Name");
parameters.Add(p => p.ValueProperty, "Id");
});
Assert.Contains("First", component.Markup);
Assert.Contains("Second", component.Markup);
}
[Fact]
public void CheckBoxList_Renders_Orientation_Horizontal()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenCheckBoxList<int>>(parameters =>
{
parameters.Add(p => p.Orientation, Orientation.Horizontal);
});
Assert.Contains("rz-flex-row", component.Markup);
}
[Fact]
public void CheckBoxList_Renders_Orientation_Vertical()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenCheckBoxList<int>>(parameters =>
{
parameters.Add(p => p.Orientation, Orientation.Vertical);
});
Assert.Contains("rz-flex-column", component.Markup);
}
[Fact]
public void CheckBoxList_Renders_Disabled()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenCheckBoxList<int>>(parameters =>
{
parameters.Add(p => p.Disabled, true);
});
Assert.Contains("disabled", component.Markup);
Assert.Contains("rz-state-disabled", component.Markup);
}
[Fact]
public void CheckBoxList_Renders_AllowSelectAll()
{
using var ctx = new TestContext();
var data = new List<string> { "Option 1", "Option 2" };
var component = ctx.RenderComponent<RadzenCheckBoxList<string>>(parameters =>
{
parameters.Add(p => p.AllowSelectAll, true);
parameters.Add(p => p.Data, data);
});
Assert.Contains("rz-multiselect-header", component.Markup);
}
[Fact]
public void CheckBoxList_Renders_SelectAllText()
{
using var ctx = new TestContext();
var data = new List<string> { "Option 1", "Option 2" };
var component = ctx.RenderComponent<RadzenCheckBoxList<string>>(parameters =>
{
parameters.Add(p => p.AllowSelectAll, true);
parameters.Add(p => p.SelectAllText, "Select All Options");
parameters.Add(p => p.Data, data);
});
Assert.Contains("Select All Options", component.Markup);
}
[Fact]
public void CheckBoxList_Renders_CheckboxInputs()
{
using var ctx = new TestContext();
var data = new List<string> { "Option 1", "Option 2" };
var component = ctx.RenderComponent<RadzenCheckBoxList<string>>(parameters =>
{
parameters.Add(p => p.Data, data);
});
Assert.Contains("type=\"checkbox\"", component.Markup);
Assert.Contains("rz-chkbox", component.Markup);
}
[Fact]
public void CheckBoxList_Renders_DisabledItems()
{
using var ctx = new TestContext();
var data = new List<Item>
{
new Item { Id = 1, Name = "Enabled", Disabled = false },
new Item { Id = 2, Name = "Disabled", Disabled = true }
};
var component = ctx.RenderComponent<RadzenCheckBoxList<int>>(parameters =>
{
parameters.Add(p => p.Data, data);
parameters.Add(p => p.TextProperty, "Name");
parameters.Add(p => p.ValueProperty, "Id");
parameters.Add(p => p.DisabledProperty, "Disabled");
});
Assert.Contains("Enabled", component.Markup);
Assert.Contains("Disabled", component.Markup);
}
}
}

View File

@@ -0,0 +1,74 @@
using Bunit;
using Xunit;
namespace Radzen.Blazor.Tests
{
public class ColumnTests
{
[Fact]
public void Column_Renders_WithClassName()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenColumn>();
Assert.Contains(@"rz-col", component.Markup);
}
[Fact]
public void Column_Renders_ChildContent()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenColumn>(parameters =>
{
parameters.AddChildContent("<div>Column Content</div>");
});
Assert.Contains("Column Content", component.Markup);
}
[Fact]
public void Column_Renders_SizeParameter()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenColumn>();
component.SetParametersAndRender(parameters => parameters.Add(p => p.Size, 6));
Assert.Contains("rz-col-6", component.Markup);
}
[Fact]
public void Column_Renders_SizeMD()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenColumn>();
component.SetParametersAndRender(parameters => parameters.Add(p => p.SizeMD, 4));
Assert.Contains("rz-col-md-4", component.Markup);
}
[Fact]
public void Column_Renders_SizeSM()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenColumn>();
component.SetParametersAndRender(parameters => parameters.Add(p => p.SizeSM, 12));
Assert.Contains("rz-col-sm-12", component.Markup);
}
[Fact]
public void Column_Renders_Offset()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenColumn>();
component.SetParametersAndRender(parameters => parameters.Add(p => p.Offset, 2));
Assert.Contains("rz-offset-2", component.Markup);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -29,7 +29,7 @@ namespace Radzen.Blazor.Tests
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AllowPaging, true));
Assert.Contains(@$"rz-paginator-bottom", component.Markup);
Assert.Contains(@$"rz-pager-bottom", component.Markup);
}
[Fact]
@@ -44,8 +44,8 @@ namespace Radzen.Blazor.Tests
parameters.Add<PagerPosition>(p => p.PagerPosition, PagerPosition.Top);
});
Assert.Contains(@$"rz-paginator", component.Markup);
Assert.DoesNotContain(@$"rz-paginator-bottom", component.Markup);
Assert.Contains(@$"rz-pager", component.Markup);
Assert.DoesNotContain(@$"rz-pager-bottom", component.Markup);
}
[Fact]
@@ -60,8 +60,8 @@ namespace Radzen.Blazor.Tests
parameters.Add<PagerPosition>(p => p.PagerPosition, PagerPosition.TopAndBottom);
});
Assert.Contains(@$"rz-paginator", component.Markup);
Assert.Contains(@$"rz-paginator-bottom", component.Markup);
Assert.Contains(@$"rz-pager", component.Markup);
Assert.Contains(@$"rz-pager-bottom", component.Markup);
}
[Fact]
@@ -127,7 +127,7 @@ namespace Radzen.Blazor.Tests
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; newArgs = args; });
});
component.Find(".rz-paginator-next").Click();
component.Find(".rz-pager-next").Click();
Assert.True(raised);
Assert.True(newArgs.Skip == 10);
@@ -149,7 +149,7 @@ namespace Radzen.Blazor.Tests
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; newArgs = args; });
});
component.Find(".rz-paginator-last").Click();
component.Find(".rz-pager-last").Click();
Assert.True(raised);
Assert.True(newArgs.Skip == 90);
@@ -171,8 +171,8 @@ namespace Radzen.Blazor.Tests
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; newArgs = args; });
});
component.Find(".rz-paginator-next").Click();
component.Find(".rz-paginator-prev").Click();
component.Find(".rz-pager-next").Click();
component.Find(".rz-pager-prev").Click();
Assert.True(raised);
Assert.True(newArgs.Skip == 0);
@@ -194,8 +194,8 @@ namespace Radzen.Blazor.Tests
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; newArgs = args; });
});
component.Find(".rz-paginator-next").Click();
component.Find(".rz-paginator-first").Click();
component.Find(".rz-pager-next").Click();
component.Find(".rz-pager-first").Click();
Assert.True(raised);
Assert.True(newArgs.Skip == 0);
@@ -216,7 +216,7 @@ namespace Radzen.Blazor.Tests
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; });
});
component.Find(".rz-paginator-first").Click();
component.Find(".rz-pager-first").Click();
Assert.False(raised);
}
@@ -235,7 +235,7 @@ namespace Radzen.Blazor.Tests
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; });
});
component.Find(".rz-paginator-prev").Click();
component.Find(".rz-pager-prev").Click();
Assert.False(raised);
}
@@ -253,13 +253,13 @@ namespace Radzen.Blazor.Tests
parameters.Add<bool>(p => p.AllowPaging, true);
});
component.Find(".rz-paginator-last").Click();
component.Find(".rz-pager-last").Click();
component.SetParametersAndRender(parameters => {
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; });
});
component.Find(".rz-paginator-last").Click();
component.Find(".rz-pager-last").Click();
Assert.False(raised);
}
@@ -277,13 +277,13 @@ namespace Radzen.Blazor.Tests
parameters.Add<bool>(p => p.AllowPaging, true);
});
component.Find(".rz-paginator-last").Click();
component.Find(".rz-pager-last").Click();
component.SetParametersAndRender(parameters => {
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; });
});
component.Find(".rz-paginator-next").Click();
component.Find(".rz-pager-next").Click();
Assert.False(raised);
}
@@ -304,7 +304,7 @@ namespace Radzen.Blazor.Tests
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; newArgs = args; });
});
component.Find(".rz-paginator-next").Click();
component.Find(".rz-pager-next").Click();
Assert.True(raised);
Assert.True(newArgs.Skip == 20);

View File

@@ -18,10 +18,10 @@ namespace Radzen.Blazor.Tests
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
Assert.Contains(@$"rz-datepicker", component.Markup);
Assert.Contains(@$"rz-calendar", component.Markup);
Assert.Contains(@$"rz-datepicker-group", component.Markup);
Assert.Contains(@$"rz-datepicker-header", component.Markup);
Assert.Contains(@$"rz-datepicker-calendar", component.Markup);
Assert.Contains(@$"rz-calendar-header", component.Markup);
Assert.Contains(@$"rz-calendar-view", component.Markup);
}
[Fact]
@@ -49,7 +49,8 @@ namespace Radzen.Blazor.Tests
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
component.SetParametersAndRender(parameters => {
component.SetParametersAndRender(parameters =>
{
parameters.Add<bool>(p => p.ShowTime, true);
parameters.Add<bool>(p => p.ShowSeconds, true);
});
@@ -69,7 +70,8 @@ namespace Radzen.Blazor.Tests
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
component.SetParametersAndRender(parameters => {
component.SetParametersAndRender(parameters =>
{
parameters.Add<bool>(p => p.ShowTime, true);
parameters.Add<bool>(p => p.ShowTimeOkButton, true);
});
@@ -91,7 +93,8 @@ namespace Radzen.Blazor.Tests
var format = "d";
component.SetParametersAndRender(parameters => {
component.SetParametersAndRender(parameters =>
{
parameters.Add(p => p.DateFormat, format);
parameters.Add<object>(p => p.Value, DateTime.Now);
});
@@ -108,7 +111,8 @@ namespace Radzen.Blazor.Tests
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
component.SetParametersAndRender(parameters => {
component.SetParametersAndRender(parameters =>
{
parameters.Add<bool>(p => p.ShowTime, true);
parameters.Add(p => p.HourFormat, "12");
});
@@ -127,12 +131,13 @@ namespace Radzen.Blazor.Tests
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
component.SetParametersAndRender(parameters => {
component.SetParametersAndRender(parameters =>
{
parameters.Add<bool>(p => p.ShowTime, true);
parameters.Add<bool>(p => p.TimeOnly, true);
});
Assert.DoesNotContain(@$"rz-datepicker-header", component.Markup);
Assert.DoesNotContain(@$"rz-calendar-header", component.Markup);
}
[Fact]
@@ -144,12 +149,13 @@ namespace Radzen.Blazor.Tests
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
component.SetParametersAndRender(parameters => {
component.SetParametersAndRender(parameters =>
{
parameters.Add<object>(p => p.Value, DateTime.Now);
parameters.Add<bool>(p => p.AllowClear, true);
});
Assert.Contains(@$"<i class=""rz-dropdown-clear-icon rzi rzi-times""", component.Markup);
Assert.Contains(@$"<i class=""notranslate rz-dropdown-clear-icon rzi rzi-times""", component.Markup);
}
[Fact]
@@ -168,6 +174,34 @@ namespace Radzen.Blazor.Tests
Assert.Contains(@$"tabindex=""{value}""", component.Markup);
}
[Fact]
public void DatePicker_Renders_EmptyCssClass_WhenValueIsEmpty()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
component.SetParametersAndRender(parameters => parameters.Add(p => p.Value, null));
Assert.Contains(@$"rz-state-empty", component.Markup);
}
[Fact]
public void DatePicker_DoesNotRender_EmptyCssClass_WhenValueIsNotEmpty()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
component.SetParametersAndRender(parameters => parameters.Add(p => p.Value, DateTime.Now));
Assert.DoesNotContain(@$"rz-state-empty", component.Markup);
}
[Fact]
public void DatePicker_Renders_DisabledParameter()
{
@@ -212,7 +246,7 @@ namespace Radzen.Blazor.Tests
component.SetParametersAndRender(parameters => parameters.Add(p => p.Style, value));
Assert.Contains(@$"style=""display: inline-block;{value}""", component.Markup);
Assert.Contains(@$"style=""{value}""", component.Markup);
}
[Fact]
@@ -241,11 +275,12 @@ namespace Radzen.Blazor.Tests
var raised = false;
object newValue = null;
component.SetParametersAndRender(parameters => {
component.SetParametersAndRender(parameters =>
{
parameters.Add(p => p.Change, args => { raised = true; newValue = args; });
});
component.Find(".rz-datepicker-next-icon").Click();
component.Find(".rz-calendar-next-icon").Click();
Assert.False(raised);
}
@@ -262,11 +297,12 @@ namespace Radzen.Blazor.Tests
var raised = false;
object newValue = null;
component.SetParametersAndRender(parameters => {
component.SetParametersAndRender(parameters =>
{
parameters.Add(p => p.ValueChanged, args => { raised = true; newValue = args; });
});
component.Find(".rz-datepicker-next-icon").Click();
component.Find(".rz-calendar-next-icon").Click();
Assert.False(raised);
}
@@ -283,11 +319,12 @@ namespace Radzen.Blazor.Tests
var raised = false;
object newValue = null;
component.SetParametersAndRender(parameters => {
component.SetParametersAndRender(parameters =>
{
parameters.Add(p => p.Change, args => { raised = true; newValue = args; });
});
component.Find(".rz-datepicker-prev-icon").Click();
component.Find(".rz-calendar-prev-icon").Click();
Assert.False(raised);
}
@@ -304,11 +341,12 @@ namespace Radzen.Blazor.Tests
var raised = false;
object newValue = null;
component.SetParametersAndRender(parameters => {
component.SetParametersAndRender(parameters =>
{
parameters.Add(p => p.ValueChanged, args => { raised = true; newValue = args; });
});
component.Find(".rz-datepicker-prev-icon").Click();
component.Find(".rz-calendar-prev-icon").Click();
Assert.False(raised);
}
@@ -327,7 +365,8 @@ namespace Radzen.Blazor.Tests
var raised = false;
object newValue = null;
component.SetParametersAndRender(parameters => {
component.SetParametersAndRender(parameters =>
{
parameters.Add(p => p.ValueChanged, args => { raised = true; newValue = args; })
.Add(p => p.DateRender, args => { args.Disabled = dates.Contains(args.Date); });
});
@@ -360,7 +399,8 @@ namespace Radzen.Blazor.Tests
var raised = false;
object newValue = null;
component.SetParametersAndRender(parameters => {
component.SetParametersAndRender(parameters =>
{
parameters.Add(p => p.ValueChanged, args => { raised = true; newValue = args; })
.Add(p => p.DateRender, args => { args.Disabled = dates.Contains(args.Date); });
});
@@ -379,6 +419,72 @@ namespace Radzen.Blazor.Tests
Assert.Null(newValue);
}
[Fact]
public void DatePicker_Parses_Input_Using_DateFormat()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenDatePicker<DateTime?>>();
var raised = false;
object newValue = null;
component.SetParametersAndRender(parameters =>
{
parameters.Add(p => p.DateFormat, "ddMM");
parameters.Add(p => p.ValueChanged, args => { raised = true; newValue = args; });
});
var inputElement = component.Find(".rz-inputtext");
string input = "3012";
ctx.JSInterop.Setup<string>("Radzen.getInputValue", invocation => true).SetResult(input);
inputElement.Change(input);
Assert.True(raised);
Assert.Equal(new DateTime(DateTime.Now.Year, 12, 30), newValue);
}
[Fact]
public void DatePicker_Parses_Input_Using_ParseInput()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenDatePicker<DateTime?>>();
Func<string, DateTime?> customParseInput = (input) =>
{
if (DateTime.TryParseExact(input, "ddMM", null, DateTimeStyles.None, out var result))
{
return result;
}
return null;
};
var raised = false;
object newValue = null;
component.SetParametersAndRender(parameters =>
{
parameters.Add(p => p.ParseInput, customParseInput);
parameters.Add(p => p.ValueChanged, args => { raised = true; newValue = args; });
});
var inputElement = component.Find(".rz-inputtext");
string input = "3012";
ctx.JSInterop.Setup<string>("Radzen.getInputValue", invocation => true).SetResult(input);
inputElement.Change(input);
Assert.True(raised);
Assert.Equal(new DateTime(DateTime.Now.Year, 12, 30), newValue);
}
[Fact]
public void DatePicker_Respects_DateTimeMaxValue()
{
@@ -393,26 +499,7 @@ namespace Radzen.Blazor.Tests
Assert.Contains(DateTime.MaxValue.ToString(component.Instance.DateFormat), component.Markup);
var exception = Record.Exception(() => component.Find(".rz-datepicker-next-icon")
.Click());
Assert.Null(exception);
}
[Fact]
public void DatePicker_Respects_DateTimeMinValue()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameters =>
{
parameters.Add(p => p.Value, DateTime.MinValue);
});
Assert.Contains(DateTime.MinValue.ToString(component.Instance.DateFormat), component.Markup);
var exception = Record.Exception(() => component.Find(".rz-datepicker-prev-icon")
var exception = Record.Exception(() => component.Find(".rz-calendar-next-icon")
.Click());
Assert.Null(exception);
}
@@ -441,7 +528,7 @@ namespace Radzen.Blazor.Tests
parameters.Add(p => p.Change, args => { raised = true; newValue = args; });
});
component.Find(".rz-datepicker-next-icon").Click();
component.Find(".rz-calendar-next-icon").Click();
component.FindAll(".rz-button-text").First(x => x.TextContent == "Ok").Click();
Assert.True(raised);
@@ -532,5 +619,243 @@ namespace Radzen.Blazor.Tests
Assert.Contains(@$"rzi-time", component.Markup);
}
[Fact]
public void DatePicker_Supports_DateOnly()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
DateOnly? dateOnly = new DateOnly(2024, 1, 31);
DateOnly? valueChangedValue = null!;
var component = ctx.RenderComponent<RadzenDatePicker<DateOnly?>>(parameters =>
{
parameters.Add(p => p.Value, dateOnly);
parameters.Add(p => p.ValueChanged, args => { valueChangedValue = args; });
});
Assert.False(component.Instance.ShowTime);
var input = component.Find("input");
input.GetAttribute("value").MarkupMatches(dateOnly.ToString());
// update to new value
var inputElement = component.Find(".rz-inputtext");
DateOnly? enteredValue = new DateOnly(2024, 2, 28);
ctx.JSInterop.Setup<string>("Radzen.getInputValue", invocation => true).SetResult(enteredValue.Value.ToShortDateString());
inputElement.Change(enteredValue);
input.GetAttribute("value").MarkupMatches(enteredValue.ToString());
Assert.Equal(enteredValue, component.Instance.Value);
Assert.Equal(enteredValue, valueChangedValue);
}
[Fact]
public void DatePicker_Supports_TimeOnly()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
TimeOnly? timeOnly = new TimeOnly(23, 59, 59);
TimeOnly? valueChangedValue = null!;
var component = ctx.RenderComponent<RadzenDatePicker<TimeOnly>>(parameters =>
{
parameters.Add(p => p.Value, timeOnly);
parameters.Add(p => p.ValueChanged, args => { valueChangedValue = args; });
});
Assert.True(component.Instance.TimeOnly);
Assert.True(component.Instance.ShowTime);
var input = component.Find("input");
input.GetAttribute("value").MarkupMatches(timeOnly.ToString());
// update to new value
var inputElement = component.Find(".rz-inputtext");
TimeOnly? enteredValue = new TimeOnly(1, 4, 5);
ctx.JSInterop.Setup<string>("Radzen.getInputValue", invocation => true).SetResult(enteredValue.Value.ToLongTimeString());
inputElement.Change(enteredValue);
input.GetAttribute("value").MarkupMatches(enteredValue.ToString());
Assert.Equal(enteredValue, component.Instance.Value);
Assert.Equal(enteredValue, valueChangedValue);
}
[Fact]
public void DatePicker_ShowCalendarWeek_WeekNumberAddedInAdditionalColumn()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameter =>
{
parameter.Add(p => p.ShowCalendarWeek, true);
});
Assert.Contains(@$"rz-calendar-week-number", component.Markup);
Assert.Equal(8, component.FindAll(".rz-calendar-view th").Count());
// check header and week number column
Assert.Single(component.FindAll("th.rz-datepicker-week-number"));
Assert.Equal(6, component.FindAll("td.rz-calendar-week-number").Count());
}
[Fact]
public void DatePicker_ShowCalendarWeekFalse_NoAdditionalColumn()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameter =>
{
parameter.Add(p => p.ShowCalendarWeek, false);
});
Assert.DoesNotContain(@$"rz-calendar-week-number", component.Markup);
Assert.Equal(7, component.FindAll(".rz-calendar-view th").Count());
}
[Fact]
public void DatePicker_ShowCalendarWeekWithCustomTitle_TitleCorrectlyRendered()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameter =>
{
parameter.Add(p => p.ShowCalendarWeek, true);
parameter.Add(p => p.CalendarWeekTitle, "Wk");
});
var weekNumberHeader = component.Find(".rz-calendar-view th.rz-datepicker-week-number");
Assert.Contains("Wk", weekNumberHeader.InnerHtml);
}
[Fact]
public void DatePicker_Multiple_Selects_IEnumerableDateTime()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
IEnumerable<DateTime> emitted = null;
var initial = new DateTime(2024, 1, 1);
var component = ctx.RenderComponent<RadzenDatePicker<IEnumerable<DateTime>>>(parameters =>
{
parameters.Add(p => p.Multiple, true);
parameters.Add(p => p.InitialViewDate, initial);
parameters.Add(p => p.ValueChanged, args => { emitted = args; });
});
component.InvokeAsync(() => component.FindAll("td:not(.rz-calendar-other-month) span").First(e => e.TextContent == "10").ParentElement.Click());
component.InvokeAsync(() => component.FindAll("td:not(.rz-calendar-other-month) span").First(e => e.TextContent == "12").ParentElement.Click());
Assert.NotNull(emitted);
var list = emitted.ToList();
Assert.Equal(2, list.Count);
Assert.Contains(new DateTime(2024, 1, 10), list.Select(d => d.Date));
Assert.Contains(new DateTime(2024, 1, 12), list.Select(d => d.Date));
}
[Fact]
public void DatePicker_Multiple_Selects_IEnumerableNullableDateTime()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
IEnumerable<DateTime?> emitted = null;
var initial = new DateTime(2024, 2, 1);
var component = ctx.RenderComponent<RadzenDatePicker<IEnumerable<DateTime?>>>(parameters =>
{
parameters.Add(p => p.Multiple, true);
parameters.Add(p => p.InitialViewDate, initial);
parameters.Add(p => p.ValueChanged, args => { emitted = args; });
});
component.InvokeAsync(() => component.FindAll("td:not(.rz-calendar-other-month) span").First(e => e.TextContent == "3").ParentElement.Click());
component.InvokeAsync(() => component.FindAll("td:not(.rz-calendar-other-month) span").First(e => e.TextContent == "14").ParentElement.Click());
Assert.NotNull(emitted);
var list = emitted.ToList();
Assert.Equal(2, list.Count);
Assert.Contains(new DateTime(2024, 2, 3), list.Select(d => d.Value.Date));
Assert.Contains(new DateTime(2024, 2, 14), list.Select(d => d.Value.Date));
}
[Fact]
public void DatePicker_Multiple_Emits_IEnumerableDateTimeOffsetNullable_WithUtcKind()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
IEnumerable<DateTimeOffset?> emitted = null;
var initial = new DateTime(2024, 3, 1);
var component = ctx.RenderComponent<RadzenDatePicker<IEnumerable<DateTimeOffset?>>>(parameters =>
{
parameters.Add(p => p.Multiple, true);
parameters.Add(p => p.InitialViewDate, initial);
parameters.Add(p => p.Kind, DateTimeKind.Utc);
parameters.Add(p => p.ValueChanged, args => { emitted = args; });
});
component.InvokeAsync(() => component.FindAll("td:not(.rz-calendar-other-month) span").First(e => e.TextContent == "5").ParentElement.Click());
component.InvokeAsync(() => component.FindAll("td:not(.rz-calendar-other-month) span").First(e => e.TextContent == "20").ParentElement.Click());
Assert.NotNull(emitted);
var list = emitted.ToList();
Assert.Equal(2, list.Count);
Assert.All(list, dto => Assert.Equal(TimeSpan.Zero, dto.Value.Offset));
}
[Fact]
public void DatePicker_Multiple_Emits_IEnumerableDateOnlyAndTimeOnlyNullable()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
IEnumerable<DateOnly?> emittedDates = null;
IEnumerable<TimeOnly?> emittedTimes = null;
var initial = new DateTime(2024, 4, 1);
var compDates = ctx.RenderComponent<RadzenDatePicker<IEnumerable<DateOnly?>>>(parameters =>
{
parameters.Add(p => p.Multiple, true);
parameters.Add(p => p.InitialViewDate, initial);
parameters.Add(p => p.ValueChanged, args => { emittedDates = args; });
});
compDates.InvokeAsync(() => compDates.FindAll("td:not(.rz-calendar-other-month) span").First(e => e.TextContent == "7").ParentElement.Click());
compDates.InvokeAsync(() => compDates.FindAll("td:not(.rz-calendar-other-month) span").First(e => e.TextContent == "9").ParentElement.Click());
Assert.NotNull(emittedDates);
var dateList = emittedDates.ToList();
Assert.Equal(2, dateList.Count);
Assert.Contains(new DateOnly(2024, 4, 7), dateList.Select(d => d.Value));
Assert.Contains(new DateOnly(2024, 4, 9), dateList.Select(d => d.Value));
// TimeOnly? emission should produce midnight times for selected dates
var compTimes = ctx.RenderComponent<RadzenDatePicker<IEnumerable<TimeOnly?>>>(parameters =>
{
parameters.Add(p => p.Multiple, true);
parameters.Add(p => p.InitialViewDate, initial);
parameters.Add(p => p.ValueChanged, args => { emittedTimes = args; });
});
compTimes.InvokeAsync(() => compTimes.FindAll("td:not(.rz-calendar-other-month) span").First(e => e.TextContent == "1").ParentElement.Click());
compTimes.InvokeAsync(() => compTimes.FindAll("td:not(.rz-calendar-other-month) span").First(e => e.TextContent == "2").ParentElement.Click());
Assert.NotNull(emittedTimes);
var timeList = emittedTimes.ToList();
Assert.Equal(2, timeList.Count);
Assert.All(timeList, t => Assert.Equal(new TimeOnly(0, 0, 0), t.Value));
}
}
}

View File

@@ -0,0 +1,413 @@
using Bunit;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Xunit;
namespace Radzen.Blazor.Tests
{
public class DialogServiceTests : ComponentBase
{
public class OpenDialogTests
{
[Fact(DisplayName = "DialogOptions default values are set correctly")]
public void DialogOptions_DefaultValues_AreSetCorrectly()
{
// Arrange
var options = new DialogOptions();
var dialogService = new DialogService(null, null);
// Act
dialogService.OpenDialog<DialogServiceTests>("Test", [], options);
// Assert
Assert.Equal("600px", options.Width);
Assert.Equal("", options.Left);
Assert.Equal("", options.Top);
Assert.Equal("", options.Bottom);
Assert.Equal("", options.Height);
Assert.Equal("", options.Style);
Assert.Equal("", options.CssClass);
Assert.Equal("", options.WrapperCssClass);
Assert.Equal("", options.ContentCssClass);
}
[Fact(DisplayName = "DialogOptions values are retained after OpenDialog call")]
public void DialogOptions_Values_AreRetained_AfterOpenDialogCall()
{
// Arrange
var options = new DialogOptions
{
Width = "800px",
Left = "10px",
Top = "20px",
Bottom = "30px",
Height = "400px",
Style = "background-color: red;",
CssClass = "custom-class",
WrapperCssClass = "wrapper-class",
ContentCssClass = "content-class"
};
var dialogService = new DialogService(null, null);
// Act
dialogService.OpenDialog<DialogServiceTests>("Test", [], options);
// Assert
Assert.Equal("800px", options.Width);
Assert.Equal("10px", options.Left);
Assert.Equal("20px", options.Top);
Assert.Equal("30px", options.Bottom);
Assert.Equal("400px", options.Height);
Assert.Equal("background-color: red;", options.Style);
Assert.Equal("custom-class", options.CssClass);
Assert.Equal("wrapper-class", options.WrapperCssClass);
Assert.Equal("content-class", options.ContentCssClass);
}
[Fact(DisplayName = "DialogOptions is null and default values are set correctly")]
public void DialogOptions_IsNull_DefaultValues_AreSetCorrectly()
{
// Arrange
DialogOptions resultingOptions = null;
var dialogService = new DialogService(null, null);
dialogService.OnOpen += (title, type, parameters, options) => resultingOptions = options;
// Act
dialogService.OpenDialog<DialogServiceTests>("Test", [], null);
// Assert
Assert.NotNull(resultingOptions);
Assert.Equal("600px", resultingOptions.Width);
Assert.Equal("", resultingOptions.Left);
Assert.Equal("", resultingOptions.Top);
Assert.Equal("", resultingOptions.Bottom);
Assert.Equal("", resultingOptions.Height);
Assert.Equal("", resultingOptions.Style);
Assert.Equal("", resultingOptions.CssClass);
Assert.Equal("", resultingOptions.WrapperCssClass);
Assert.Equal("", resultingOptions.ContentCssClass);
}
[Fact(DisplayName = "Open with dynamic component type reflective calls are resolved without exception")]
public void Open_DynamicComponentType_Reflective_Calls_Resolve()
{
// Arrange
string resultingTitle = null;
Type resultingType = null;
var dialogService = new DialogService(null, null);
dialogService.OnOpen += (title, type, _, _) =>
{
resultingTitle = title;
resultingType = type;
};
dialogService.Open("Dynamic Open", typeof(RadzenButton), []);
// Assert
Assert.Equal("Dynamic Open", resultingTitle);
Assert.Equal(typeof(RadzenButton), resultingType);
}
[Fact(DisplayName = "OpenAsync with dynamic component type reflective calls are resolved without exception")]
public async Task OpenAsync_DynamicComponentType_Reflective_Calls_Resolve()
{
// Arrange
string resultingTitle = null;
Type resultingType = null;
var dialogService = new DialogService(null, null);
dialogService.OnOpen += (title, type, _, _) =>
{
resultingTitle = title;
resultingType = type;
};
var openTask = dialogService.OpenAsync("Dynamic Open", typeof(RadzenButton), []);
dialogService.Close();
await openTask;
// Assert
Assert.Equal("Dynamic Open", resultingTitle);
Assert.Equal(typeof(RadzenButton), resultingType);
}
}
public class OpenSideDialogTests
{
[Fact(DisplayName = "SideDialogOptions resizable option is retained after OpenSideDialog call")]
public void SideDialogOptions_Resizable_AreRetained_AfterOpenSideDialogCall()
{
// Arrange
var options = new SideDialogOptions { Resizable = true };
SideDialogOptions resultingOptions = null;
var dialogService = new DialogService(null, null);
dialogService.OnSideOpen += (_, _, sideOptions) => resultingOptions = sideOptions;
// Act
dialogService.OpenSide<DialogServiceTests>("Test", [], options);
// Assert
Assert.NotNull(resultingOptions);
Assert.Same(options, resultingOptions);
Assert.True(resultingOptions.Resizable);
}
[Fact(DisplayName = "Side dialog shows resize bar when Resizable is true")]
public void SideDialog_Resizable_ShowsResizeBar()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.Services.AddScoped<DialogService>();
// Render the dialog host
var cut = ctx.RenderComponent<RadzenDialog>();
// Open a side dialog with Resizable=true
var dialogService = ctx.Services.GetRequiredService<DialogService>();
cut.InvokeAsync(() => dialogService.OpenSide("Test", typeof(RadzenButton),
new Dictionary<string, object>(), new SideDialogOptions { Resizable = true }));
// Assert: the resize bar element is present
cut.WaitForAssertion(() =>
{
var markup = cut.Markup;
Assert.Contains("rz-dialog-resize-bar", markup);
// Optionally ensure the inner handle exists too
Assert.Contains("rz-resize", markup);
});
}
[Fact(DisplayName = "Side dialog hides resize bar when Resizable is false")]
public void SideDialog_NonResizable_HidesResizeBar()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.Services.AddScoped<DialogService>();
// Render the dialog host
var cut = ctx.RenderComponent<RadzenDialog>();
// Open a side dialog with Resizable=false
var dialogService = ctx.Services.GetRequiredService<DialogService>();
cut.InvokeAsync(() => dialogService.OpenSide("Test", typeof(RadzenButton),
new Dictionary<string, object>(), new SideDialogOptions()));
// Assert: the resize bar element is not present
cut.WaitForAssertion(() =>
{
var markup = cut.Markup;
Assert.DoesNotContain("rz-dialog-resize-bar", markup);
});
}
}
public class ConfirmTests
{
[Fact(DisplayName = "ConfirmOptions is null and default values are set correctly")]
public async Task ConfirmOptions_IsNull_AreSetCorrectly()
{
// Arrange
var dialogService = new DialogService(null, null);
ConfirmOptions resultingOptions = null;
dialogService.OnOpen += (title, type, parameters, options) => resultingOptions = options as ConfirmOptions;
using var cancellationTokenSource = new CancellationTokenSource();
cancellationTokenSource.Cancel();
// Act
try
{
await dialogService.Confirm(cancellationToken: cancellationTokenSource.Token);
}
catch (TaskCanceledException)
{
// this is expected
}
// Assert
Assert.NotNull(resultingOptions);
Assert.Equal("Ok", resultingOptions.OkButtonText);
Assert.Equal("Cancel", resultingOptions.CancelButtonText);
Assert.Equal("600px", resultingOptions.Width);
Assert.Equal("", resultingOptions.Style);
Assert.Equal("rz-dialog-confirm", resultingOptions.CssClass);
Assert.Equal("rz-dialog-wrapper", resultingOptions.WrapperCssClass);
}
[Fact(DisplayName = "ConfirmOptions default values are set correctly")]
public async Task ConfirmOptions_DefaultValues_AreSetCorrectly()
{
// Arrange
var dialogService = new DialogService(null, null);
ConfirmOptions resultingOptions = null;
dialogService.OnOpen += (title, type, parameters, options) => resultingOptions = options as ConfirmOptions;
using var cancellationTokenSource = new CancellationTokenSource();
cancellationTokenSource.Cancel();
// Act
try
{
await dialogService.Confirm(options: new(), cancellationToken: cancellationTokenSource.Token);
}
catch (TaskCanceledException)
{
// this is expected
}
// Assert
Assert.NotNull(resultingOptions);
Assert.Equal("Ok", resultingOptions.OkButtonText);
Assert.Equal("Cancel", resultingOptions.CancelButtonText);
Assert.Equal("600px", resultingOptions.Width);
Assert.Equal("", resultingOptions.Style);
Assert.Equal("rz-dialog-confirm", resultingOptions.CssClass);
Assert.Equal("rz-dialog-wrapper", resultingOptions.WrapperCssClass);
}
[Fact(DisplayName = "ConfirmOptions values are retained after Confirm call")]
public async Task Confirm_ProvidedValues_AreRetained()
{
// Arrange
var dialogService = new DialogService(null, null);
var options = new ConfirmOptions
{
OkButtonText = "XXX",
CancelButtonText = "YYY",
Width = "800px",
Style = "background-color: red;",
CssClass = "custom-class",
WrapperCssClass = "wrapper-class"
};
ConfirmOptions resultingOptions = null;
dialogService.OnOpen += (title, type, parameters, options) => resultingOptions = options as ConfirmOptions;
// We break out of the dialog immediately, but the options should still be set
using var cancellationTokenSource = new CancellationTokenSource();
cancellationTokenSource.Cancel();
// Act
try
{
await dialogService.Confirm("Confirm?", "Confirm", options, cancellationToken: cancellationTokenSource.Token);
}
catch (TaskCanceledException)
{
// this is expected
}
// Assert
Assert.NotNull(resultingOptions);
Assert.Equal("XXX", resultingOptions.OkButtonText);
Assert.Equal("YYY", resultingOptions.CancelButtonText);
Assert.Equal("800px", resultingOptions.Width);
Assert.Equal("background-color: red;", resultingOptions.Style);
Assert.Equal("rz-dialog-confirm custom-class", resultingOptions.CssClass);
Assert.Equal("rz-dialog-wrapper wrapper-class", resultingOptions.WrapperCssClass);
}
}
public class AlertTests
{
[Fact(DisplayName = "AlertOptions is null and default values are set correctly")]
public async Task AlertOptions_IsNull_AreSetCorrectly()
{
// Arrange
var dialogService = new DialogService(null, null);
AlertOptions resultingOptions = null;
dialogService.OnOpen += (title, type, parameters, options) => resultingOptions = options as AlertOptions;
using var cancellationTokenSource = new CancellationTokenSource();
cancellationTokenSource.Cancel();
// Act
try
{
await dialogService.Alert(cancellationToken: cancellationTokenSource.Token);
}
catch (TaskCanceledException)
{
// this is expected
}
// Assert
Assert.NotNull(resultingOptions);
Assert.Equal("Ok", resultingOptions.OkButtonText);
Assert.Equal("600px", resultingOptions.Width);
Assert.Equal("", resultingOptions.Style);
Assert.Equal("rz-dialog-alert", resultingOptions.CssClass);
Assert.Equal("rz-dialog-wrapper", resultingOptions.WrapperCssClass);
}
[Fact(DisplayName = "AlertOptions default values are set correctly")]
public async Task AlertOptions_DefaultValues_AreSetCorrectly()
{
// Arrange
var dialogService = new DialogService(null, null);
AlertOptions resultingOptions = null;
dialogService.OnOpen += (title, type, parameters, options) => resultingOptions = options as AlertOptions;
using var cancellationTokenSource = new CancellationTokenSource();
cancellationTokenSource.Cancel();
// Act
try
{
await dialogService.Alert(options: new(), cancellationToken: cancellationTokenSource.Token);
}
catch (TaskCanceledException)
{
// this is expected
}
// Assert
Assert.NotNull(resultingOptions);
Assert.Equal("Ok", resultingOptions.OkButtonText);
Assert.Equal("600px", resultingOptions.Width);
Assert.Equal("", resultingOptions.Style);
Assert.Equal("rz-dialog-alert", resultingOptions.CssClass);
Assert.Equal("rz-dialog-wrapper", resultingOptions.WrapperCssClass);
}
[Fact(DisplayName = "AlertOptions values are retained after Alert call")]
public async Task Alert_ProvidedValues_AreRetained()
{
// Arrange
var dialogService = new DialogService(null, null);
var options = new AlertOptions
{
OkButtonText = "XXX",
Width = "800px",
Style = "background-color: red;",
CssClass = "custom-class",
WrapperCssClass = "wrapper-class"
};
AlertOptions resultingOptions = null;
dialogService.OnOpen += (title, type, parameters, options) => resultingOptions = options as AlertOptions;
// We break out of the dialog immediately, but the options should still be set
using var cancellationTokenSource = new CancellationTokenSource();
cancellationTokenSource.Cancel();
// Act
try
{
await dialogService.Alert("Alert?", "Alert", options, cancellationToken: cancellationTokenSource.Token);
}
catch (TaskCanceledException)
{
// this is expected
}
// Assert
Assert.NotNull(resultingOptions);
Assert.Equal("XXX", resultingOptions.OkButtonText);
Assert.Equal("800px", resultingOptions.Width);
Assert.Equal("background-color: red;", resultingOptions.Style);
Assert.Equal("rz-dialog-alert custom-class", resultingOptions.CssClass);
Assert.Equal("rz-dialog-wrapper wrapper-class", resultingOptions.WrapperCssClass);
}
}
}
}

View File

@@ -0,0 +1,58 @@
using System;
using System.ComponentModel;
using System.Globalization;
namespace Radzen.Blazor.Tests;
[TypeConverter(typeof(DollarsTypeConverter))]
public readonly record struct Dollars(decimal Amount) : IComparable<decimal>
{
public int CompareTo(decimal other)
{
return Amount.CompareTo(other);
}
public string ToString(string format, CultureInfo culture = null) => Amount.ToString(format, culture ?? CultureInfo.CreateSpecificCulture("en-US"));
public override string ToString() => Amount.ToString("F2", CultureInfo.CreateSpecificCulture("en-US"));
}
public class DollarsTypeConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(decimal) ||
sourceType == typeof(string))
{
return true;
}
return base.CanConvertFrom(context, sourceType);
}
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof(decimal))
return true;
return base.CanConvertTo(context, destinationType);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
if (value is decimal d)
return new Dollars(d);
if (value is string s)
return decimal.TryParse(s, culture, out var val) ? new Dollars(val) : null;
return base.ConvertFrom(context, culture, value);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(decimal) && value is Dollars d)
return d.Amount;
return base.ConvertTo(context, culture, value, destinationType);
}
}

View File

@@ -0,0 +1,289 @@
using Bunit;
using Xunit;
using System.Collections.Generic;
using System.Linq;
namespace Radzen.Blazor.Tests
{
public class DropDownDataGridTests
{
class Customer
{
public int Id { get; set; }
public string CompanyName { get; set; }
public string ContactName { get; set; }
}
[Fact]
public void DropDownDataGrid_Renders_WithClassName()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenDropDownDataGrid<int>>();
Assert.Contains(@"rz-dropdown", component.Markup);
}
[Fact]
public void DropDownDataGrid_Renders_DropdownTrigger()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenDropDownDataGrid<int>>();
Assert.Contains("rz-dropdown-trigger", component.Markup);
Assert.Contains("rzi-chevron-down", component.Markup);
}
[Fact]
public void DropDownDataGrid_Renders_WithData()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var data = new List<string> { "Item1", "Item2", "Item3" };
var component = ctx.RenderComponent<RadzenDropDownDataGrid<string>>(parameters =>
{
parameters.Add(p => p.Data, data);
});
Assert.Contains("rz-lookup-panel", component.Markup);
}
[Fact]
public void DropDownDataGrid_Renders_WithCustomTextValueProperties()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var data = new List<Customer>
{
new Customer { Id = 1, CompanyName = "Acme Corp", ContactName = "John Doe" },
new Customer { Id = 2, CompanyName = "Tech Inc", ContactName = "Jane Smith" }
};
var component = ctx.RenderComponent<RadzenDropDownDataGrid<int>>(parameters =>
{
parameters.Add(p => p.Data, data);
parameters.Add(p => p.TextProperty, "CompanyName");
parameters.Add(p => p.ValueProperty, "Id");
});
Assert.Contains("rz-lookup-panel", component.Markup);
Assert.Contains("rz-data-grid", component.Markup);
}
[Fact]
public void DropDownDataGrid_Renders_DataGrid()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var data = new List<string> { "Item1" };
var component = ctx.RenderComponent<RadzenDropDownDataGrid<string>>(parameters =>
{
parameters.Add(p => p.Data, data);
});
// DropDownDataGrid embeds a DataGrid
Assert.Contains("rz-data-grid", component.Markup);
}
[Fact]
public void DropDownDataGrid_Renders_AllowFiltering()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var data = new List<string> { "Item1", "Item2" };
var component = ctx.RenderComponent<RadzenDropDownDataGrid<string>>(parameters =>
{
parameters.Add(p => p.AllowFiltering, true);
parameters.Add(p => p.Data, data);
});
Assert.Contains("rz-lookup-search", component.Markup);
Assert.Contains("rz-lookup-search-input", component.Markup);
}
[Fact]
public void DropDownDataGrid_Renders_Placeholder()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenDropDownDataGrid<int>>(parameters =>
{
parameters.Add(p => p.Placeholder, "Select an item");
});
Assert.Contains("Select an item", component.Markup);
Assert.Contains("rz-placeholder", component.Markup);
}
[Fact]
public void DropDownDataGrid_Renders_AllowClear_WithValue()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var data = new List<string> { "Item1" };
var component = ctx.RenderComponent<RadzenDropDownDataGrid<string>>(parameters =>
{
parameters.Add(p => p.AllowClear, true);
parameters.Add(p => p.Data, data);
parameters.Add(p => p.Value, "Item1");
});
Assert.Contains("rz-dropdown-clear-icon", component.Markup);
}
[Fact]
public void DropDownDataGrid_DoesNotRender_AllowClear_WhenNotAllowed()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var data = new List<string> { "Item1" };
var component = ctx.RenderComponent<RadzenDropDownDataGrid<string>>(parameters =>
{
parameters.Add(p => p.AllowClear, false);
parameters.Add(p => p.Data, data);
parameters.Add(p => p.Value, "Item1");
});
Assert.DoesNotContain("rz-dropdown-clear-icon", component.Markup);
}
[Fact]
public void DropDownDataGrid_Renders_Disabled()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenDropDownDataGrid<int>>(parameters =>
{
parameters.Add(p => p.Disabled, true);
});
Assert.Contains("disabled", component.Markup);
Assert.Contains("rz-state-disabled", component.Markup);
}
[Fact]
public void DropDownDataGrid_Renders_Multiple_Panel()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenDropDownDataGrid<IEnumerable<int>>>(parameters =>
{
parameters.Add(p => p.Multiple, true);
});
Assert.Contains("rz-multiselect-panel", component.Markup);
}
[Fact]
public void DropDownDataGrid_Renders_Multiple_WithChips()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var data = new List<string> { "Item1", "Item2" };
var selectedItems = new List<string> { "Item1" };
var component = ctx.RenderComponent<RadzenDropDownDataGrid<IEnumerable<string>>>(parameters =>
{
parameters.Add(p => p.Multiple, true);
parameters.Add(p => p.Chips, true);
parameters.Add(p => p.Data, data);
parameters.Add(p => p.Value, selectedItems);
});
Assert.Contains("rz-dropdown-chips-wrapper", component.Markup);
Assert.Contains("rz-chip", component.Markup);
}
[Fact]
public void DropDownDataGrid_Renders_AllowSorting()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var data = new List<Customer>
{
new Customer { Id = 1, CompanyName = "Acme" }
};
var component = ctx.RenderComponent<RadzenDropDownDataGrid<int>>(parameters =>
{
parameters.Add(p => p.AllowSorting, true);
parameters.Add(p => p.Data, data);
parameters.Add(p => p.TextProperty, "CompanyName");
});
Assert.Contains("rz-data-grid", component.Markup);
}
[Fact]
public void DropDownDataGrid_Renders_SearchTextPlaceholder()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var data = new List<string> { "Item1" };
var component = ctx.RenderComponent<RadzenDropDownDataGrid<string>>(parameters =>
{
parameters.Add(p => p.AllowFiltering, true);
parameters.Add(p => p.SearchTextPlaceholder, "Type to filter...");
parameters.Add(p => p.Data, data);
});
Assert.Contains("placeholder=\"Type to filter...\"", component.Markup);
}
[Fact]
public void DropDownDataGrid_Renders_EmptyText()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenDropDownDataGrid<string>>(parameters =>
{
parameters.Add(p => p.Data, new List<string>());
parameters.Add(p => p.EmptyText, "No items found");
});
Assert.Contains("No items found", component.Markup);
}
[Fact]
public void DropDownDataGrid_Renders_PageSize()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var data = Enumerable.Range(1, 20).Select(i => $"Item {i}").ToList();
var component = ctx.RenderComponent<RadzenDropDownDataGrid<string>>(parameters =>
{
parameters.Add(p => p.Data, data);
parameters.Add(p => p.PageSize, 10);
});
// DataGrid with paging should be present
Assert.Contains("rz-data-grid", component.Markup);
}
[Fact]
public void DropDownDataGrid_Renders_AllowRowSelectOnRowClick()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var data = new List<string> { "Item1", "Item2" };
var component = ctx.RenderComponent<RadzenDropDownDataGrid<string>>(parameters =>
{
parameters.Add(p => p.AllowRowSelectOnRowClick, true);
parameters.Add(p => p.Data, data);
});
Assert.Contains("rz-data-grid", component.Markup);
}
}
}

View File

@@ -1,6 +1,11 @@
using System;
using System.Threading.Tasks;
using AngleSharp.Dom;
using Bunit;
using Microsoft.AspNetCore.Components;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Xunit;
namespace Radzen.Blazor.Tests
@@ -11,18 +16,20 @@ namespace Radzen.Blazor.Tests
{
public string Text { get; set; }
public int Id { get; set; }
public bool Disabled { get; set; }
}
private static IRenderedComponent<RadzenDropDown<T>> DropDown<T>(TestContext ctx, Action<ComponentParameterCollectionBuilder<RadzenDropDown<T>>> configure = null)
{
var data = new [] {
var data = new[] {
new DataItem { Text = "Item 1", Id = 1 },
new DataItem { Text = "Item 2", Id = 2 },
};
var component = ctx.RenderComponent<RadzenDropDown<T>>();
component.SetParametersAndRender(parameters => {
component.SetParametersAndRender(parameters =>
{
parameters.Add(p => p.Data, data);
parameters.Add(p => p.TextProperty, nameof(DataItem.Text));
@@ -39,6 +46,7 @@ namespace Radzen.Blazor.Tests
return component;
}
[Fact]
public async Task Dropdown_SelectItem_Method_Should_Not_Throw()
{
@@ -97,7 +105,8 @@ namespace Radzen.Blazor.Tests
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = DropDown<string>(ctx, parameters => {
var component = DropDown<string>(ctx, parameters =>
{
parameters.Add(p => p.ValueProperty, nameof(DataItem.Text));
});
@@ -112,6 +121,35 @@ namespace Radzen.Blazor.Tests
Assert.Contains("rz-state-highlight", items[0].ClassList);
}
[Fact]
public void DropDown_Respects_ItemEqualityComparer()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
List<DataItem> boundCollection = [new() { Text = "Item 2" }];
var component = DropDown<List<DataItem>>(ctx, parameters =>
{
parameters.Add(p => p.ItemComparer, new DataItemComparer());
parameters.Add(p => p.Multiple, true);
parameters.Add(p => p.Value, boundCollection);
});
var selectedItems = component.FindAll(".rz-state-highlight");
Assert.Equal(1, selectedItems.Count);
Assert.Equal("Item 2", selectedItems[0].TextContent.Trim());
// select Item 1 in list
var items = component.FindAll(".rz-multiselect-item");
items[0].Click();
component.Render();
selectedItems = component.FindAll(".rz-state-highlight");
Assert.Equal(2, selectedItems.Count);
Assert.Equal("Item 1", selectedItems[0].TextContent.Trim());
}
[Fact]
public void DropDown_AppliesSelectionStyleWhenMultipleSelectionIsEnabled()
{
@@ -119,7 +157,8 @@ namespace Radzen.Blazor.Tests
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = DropDown<string>(ctx, parameters => {
var component = DropDown<string>(ctx, parameters =>
{
parameters.Add(p => p.ValueProperty, nameof(DataItem.Text));
parameters.Add(p => p.Multiple, true);
});
@@ -140,5 +179,565 @@ namespace Radzen.Blazor.Tests
Assert.Equal(2, selectedItems.Count);
}
[Fact]
public void DropDown_AppliesValueTemplateOnMultipleSelection()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var valueTemplateFragment = (RenderFragment<dynamic>)(_context =>
builder =>
{
builder.AddContent(0, $"value: {_context.Text}");
});
var component = DropDown<string>(ctx, parameters =>
{
parameters.Add(p => p.Multiple, true)
.Add(p => p.ValueTemplate, valueTemplateFragment);
});
var items = component.FindAll(".rz-multiselect-item");
items[0].Click();
items[1].Click();
component.Render();
var selectedItems = component.Find(".rz-inputtext");
Assert.Contains("value: Item 1,value: Item 2", selectedItems.Text());
}
[Fact]
public void DropDown_AppliesValueTemplateWhenTepmlateDefined()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var valueTemplateFragment = (RenderFragment<dynamic>)(_context =>
builder =>
{
builder.AddContent(0, $"value: {_context.Text}");
});
var templateFragment = (RenderFragment<dynamic>)(_context =>
builder =>
{
builder.AddContent(0, $"template: {_context.Text}");
});
var component = DropDown<string>(ctx, parameters =>
{
parameters.Add(p => p.Multiple, true)
.Add(p => p.ValueTemplate, valueTemplateFragment)
.Add(p => p.Template, templateFragment);
});
var items = component.FindAll(".rz-multiselect-item");
items[0].Click();
items[1].Click();
component.Render();
var selectedItems = component.Find(".rz-inputtext");
var itemsText = component.FindAll(".rz-multiselect-item-content");
Assert.Collection(itemsText, item => Assert.Contains("template: Item 1", item.Text()), item => Assert.Contains("template: Item 2", item.Text()));
Assert.Contains("value: Item 1,value: Item 2", selectedItems.Text());
}
[Fact]
public void DropDown_AppliesValueTemplateOnMultipleSelectionChips()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var valueTemplateFragment = (RenderFragment<dynamic>)(_context =>
builder =>
{
builder.AddContent(0, $"value: {_context.Text}");
});
var component = DropDown<string>(ctx, parameters =>
{
parameters.Add(p => p.Multiple, true)
.Add(p => p.ValueTemplate, valueTemplateFragment)
.Add(p => p.Chips, true);
});
var items = component.FindAll(".rz-multiselect-item");
items[0].Click();
items[1].Click();
component.Render();
var selectedItems = component.FindAll(".rz-chip-text");
Assert.Collection(selectedItems, item => Assert.Contains("value: Item 1", item.Text()), item => Assert.Contains("value: Item 2", item.Text()));
}
[Theory]
[InlineData(false, true, false, true, "false")]
[InlineData(true, false, true, false, "true")]
[InlineData(true, false, false, false, "false")]
[InlineData(true, false, false, true, "true")]
[InlineData(false, false, false, true, "false")]
public void DropDown_AllSelectedFalseIfListIsAllDisabled(bool item1Selected, bool item1Disabled, bool item2Selected, bool item2Disabled, string expectedAriaCheckedValue)
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var data = new[] {
new DataItem { Text = "Item 1", Id = 1, Disabled = item1Disabled },
new DataItem { Text = "Item 2", Id = 2, Disabled = item2Disabled },
};
List<int> selectedValues = [];
if (item1Selected)
{
selectedValues.Add(data[0].Id);
}
if (item2Selected)
{
selectedValues.Add(data[1].Id);
}
var component = ctx.RenderComponent<RadzenDropDown<List<int>>>(parameters => parameters
.Add(p => p.Data, data)
.Add(p => p.Value, selectedValues)
.Add(p => p.Multiple, true)
.Add(p => p.AllowSelectAll, true)
.Add(p => p.TextProperty, nameof(DataItem.Text))
.Add(p => p.DisabledProperty, nameof(DataItem.Disabled))
.Add(p => p.ValueProperty, nameof(DataItem.Id)));
Assert.NotNull(component);
var highlightedItems = component.FindAll(".rz-state-highlight");
Assert.Equal(selectedValues.Count, highlightedItems.Count);
var selectAllCheckBox = component.Find(".rz-multiselect-header input[type='checkbox']");
Assert.Equal(expectedAriaCheckedValue, selectAllCheckBox.GetAttribute("aria-checked"));
}
[Fact]
public void DropDown_ReferenceGenericCollectionAssignment_HashSet_ReferencesInstance()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var originalHashSet = new HashSet<int>();
var capturedValue = (HashSet<int>)null;
var component = DropDownWithReferenceCollection<HashSet<int>>(ctx, parameters =>
{
parameters.Add(p => p.Multiple, true);
parameters.Add(p => p.Value, originalHashSet);
parameters.Add(p => p.ValueChanged, EventCallback.Factory.Create<HashSet<int>>(this, value => capturedValue = value));
parameters.Add(p => p.ValueProperty, nameof(DataItem.Id));
});
var items = component.FindAll(".rz-multiselect-item");
// Select first item
items[0].Click();
component.Render();
// Verify the same HashSet instance is Referenced
Assert.Same(originalHashSet, capturedValue);
// Verify the item was added correctly
Assert.Single(originalHashSet);
Assert.Contains(1, originalHashSet);
}
[Fact]
public void DropDown_ReferenceGenericCollectionAssignment_HashSet_MultipleSelections()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var originalHashSet = new HashSet<int> { 2 }; // Pre-populate with Item 2
var capturedValues = new List<HashSet<int>>();
var component = DropDownWithReferenceCollection<HashSet<int>>(ctx, parameters =>
{
parameters.Add(p => p.Multiple, true);
parameters.Add(p => p.Value, originalHashSet);
parameters.Add(p => p.ValueChanged, EventCallback.Factory.Create<HashSet<int>>(this, value => capturedValues.Add(value)));
parameters.Add(p => p.ValueProperty, nameof(DataItem.Id));
});
var items = component.FindAll(".rz-multiselect-item");
// Select first item (should add to existing collection)
items[0].Click();
component.Render();
// Verify the same HashSet instance is Referenced
Assert.Single(capturedValues);
Assert.Same(originalHashSet, capturedValues[0]);
// Verify both items are now in the collection
Assert.Equal(2, originalHashSet.Count);
Assert.Contains(1, originalHashSet);
Assert.Contains(2, originalHashSet);
// Deselect second item (should remove from collection)
items = component.FindAll(".rz-multiselect-item"); // Re-find items after render
items[1].Click();
component.Render();
// Verify the same HashSet instance is still Referenced
Assert.Equal(2, capturedValues.Count);
Assert.Same(originalHashSet, capturedValues[1]);
// Verify only first item remains
Assert.Single(originalHashSet);
Assert.Contains(1, originalHashSet);
Assert.DoesNotContain(2, originalHashSet);
}
[Fact]
public void DropDown_ReferenceGenericCollectionAssignment_SortedSet_ReferencesInstance()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var originalSortedSet = new SortedSet<int>();
var capturedValue = (SortedSet<int>)null;
var component = DropDownWithReferenceCollection<SortedSet<int>>(ctx, parameters =>
{
parameters.Add(p => p.Multiple, true);
parameters.Add(p => p.Value, originalSortedSet);
parameters.Add(p => p.ValueChanged, EventCallback.Factory.Create<SortedSet<int>>(this, value => capturedValue = value));
parameters.Add(p => p.ValueProperty, nameof(DataItem.Id));
});
var items = component.FindAll(".rz-multiselect-item");
// Select both items
items[0].Click();
component.Render();
items = component.FindAll(".rz-multiselect-item"); // Re-find items after first click
items[1].Click();
component.Render();
// Verify the same SortedSet instance is Referenced
Assert.Same(originalSortedSet, capturedValue);
// Verify items are sorted correctly
Assert.Equal(2, originalSortedSet.Count);
var sortedItems = originalSortedSet.ToList();
Assert.Equal(1, sortedItems[0]);
Assert.Equal(2, sortedItems[1]);
}
[Fact]
public void DropDown_ReferenceGenericCollectionAssignment_CustomCollection_ReferencesInstance()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var originalCollection = new CustomCollection<int>();
var capturedValue = (CustomCollection<int>)null;
var component = DropDownWithReferenceCollection<CustomCollection<int>>(ctx, parameters =>
{
parameters.Add(p => p.Multiple, true);
parameters.Add(p => p.Value, originalCollection);
parameters.Add(p => p.ValueChanged, EventCallback.Factory.Create<CustomCollection<int>>(this, value => capturedValue = value));
parameters.Add(p => p.ValueProperty, nameof(DataItem.Id));
});
var items = component.FindAll(".rz-multiselect-item");
// Select first item
items[0].Click();
component.Render();
// Verify the same custom collection instance is Referenced
Assert.Same(originalCollection, capturedValue);
// Verify the item was added correctly
Assert.Single(originalCollection);
Assert.Contains(1, originalCollection);
}
[Fact]
public void DropDown_ReferenceGenericCollectionAssignment_List_ReferencesInstance()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var originalList = new List<int>();
var capturedValue = (List<int>)null;
var component = DropDownWithReferenceCollection<List<int>>(ctx, parameters =>
{
parameters.Add(p => p.Multiple, true);
parameters.Add(p => p.Value, originalList);
parameters.Add(p => p.ValueChanged, EventCallback.Factory.Create<List<int>>(this, value => capturedValue = value));
parameters.Add(p => p.ValueProperty, nameof(DataItem.Id));
});
var items = component.FindAll(".rz-multiselect-item");
// Select first item
items[0].Click();
component.Render();
// For List<T>, it should now Reference the instance since we removed the IList exclusion
// Arrays are now excluded instead
Assert.Same(originalList, capturedValue);
// And the content should be correct
Assert.Single(capturedValue);
Assert.Contains(1, capturedValue);
}
[Fact]
public void DropDown_ReferenceGenericCollectionAssignment_DisabledByDefault()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var originalList = new List<int>();
var capturedValue = (List<int>)null;
var component = DropDown<List<int>>(ctx, parameters =>
{
parameters.Add(p => p.Multiple, true);
parameters.Add(p => p.Value, originalList);
parameters.Add(p => p.ValueChanged, EventCallback.Factory.Create<List<int>>(this, value => capturedValue = value));
parameters.Add(p => p.ValueProperty, nameof(DataItem.Id));
});
var items = component.FindAll(".rz-multiselect-item");
// Select first item
items[0].Click();
component.Render();
// When ReferenceCollectionOnSelection is false (default), a new instance should be created
Assert.NotSame(originalList, capturedValue);
// But the content should still be correct
Assert.Single(capturedValue);
Assert.Contains(1, capturedValue);
}
[Fact]
public void DropDown_Reset_PreservesCollectionInstanceButClears()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var originalHashSet = new HashSet<int> { 1, 2 }; // Pre-populate
var capturedValues = new List<HashSet<int>>();
var component = DropDownWithReferenceCollection<HashSet<int>>(ctx, parameters =>
{
parameters.Add(p => p.Multiple, true);
parameters.Add(p => p.Value, originalHashSet);
parameters.Add(p => p.ValueChanged, EventCallback.Factory.Create<HashSet<int>>(this, value => capturedValues.Add(value)));
parameters.Add(p => p.ValueProperty, nameof(DataItem.Id));
});
// Verify initial state - collection should have 2 items
Assert.Equal(2, originalHashSet.Count);
Assert.Contains(1, originalHashSet);
Assert.Contains(2, originalHashSet);
// Call Reset (public method that calls ClearAll internally)
component.InvokeAsync(() => component.Instance.Reset());
component.Render();
// Verify the same HashSet instance is preserved
Assert.Single(capturedValues);
Assert.Same(originalHashSet, capturedValues[0]);
// Verify the collection is now cleared
Assert.Empty(originalHashSet);
}
[Fact]
public void DropDown_SelectAll_PreservesCollectionInstanceAndPopulates()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var originalHashSet = new HashSet<int>(); // Start empty
var capturedValues = new List<HashSet<int>>();
var component = DropDownWithReferenceCollection<HashSet<int>>(ctx, parameters =>
{
parameters.Add(p => p.Multiple, true);
parameters.Add(p => p.AllowSelectAll, true);
parameters.Add(p => p.Value, originalHashSet);
parameters.Add(p => p.ValueChanged, EventCallback.Factory.Create<HashSet<int>>(this, value => capturedValues.Add(value)));
parameters.Add(p => p.ValueProperty, nameof(DataItem.Id));
});
// Verify initial state - collection should be empty
Assert.Empty(originalHashSet);
// Find and click the "Select All" checkbox
var selectAllCheckBox = component.Find(".rz-multiselect-header input[type='checkbox']");
selectAllCheckBox.Click();
component.Render();
// Verify the same HashSet instance is preserved
Assert.Single(capturedValues);
Assert.Same(originalHashSet, capturedValues[0]);
// Verify the collection now contains both items
Assert.Equal(2, originalHashSet.Count);
Assert.Contains(1, originalHashSet);
Assert.Contains(2, originalHashSet);
}
class ReferenceCollectionDropDown<T> : Radzen.Blazor.RadzenDropDown<T>
{
protected override void OnInitialized()
{
PreserveCollectionOnSelection = true;
base.OnInitialized();
}
}
private static IRenderedComponent<ReferenceCollectionDropDown<T>> DropDownWithReferenceCollection<T>(TestContext ctx, Action<ComponentParameterCollectionBuilder<ReferenceCollectionDropDown<T>>> configure = null)
{
var data = new[] {
new DataItem { Text = "Item 1", Id = 1 },
new DataItem { Text = "Item 2", Id = 2 },
};
var component = ctx.RenderComponent<ReferenceCollectionDropDown<T>>();
component.SetParametersAndRender(parameters =>
{
parameters.Add(p => p.Data, data);
parameters.Add(p => p.TextProperty, nameof(DataItem.Text));
if (configure != null)
{
configure.Invoke(parameters);
}
else
{
parameters.Add(p => p.ValueProperty, nameof(DataItem.Id));
}
});
return component;
}
class DataItemComparer : IEqualityComparer<DataItem>, IEqualityComparer<object>
{
public bool Equals(DataItem x, DataItem y)
{
if (ReferenceEquals(x, y)) return true;
if (x is null) return false;
if (y is null) return false;
if (x.GetType() != y.GetType()) return false;
return x.Text == y.Text;
}
public int GetHashCode(DataItem obj)
{
return obj.Text.GetHashCode();
}
public new bool Equals(object x, object y)
{
return Equals((DataItem)x, (DataItem)y);
}
public int GetHashCode(object obj)
{
return GetHashCode((DataItem)obj);
}
}
class CustomCollection<T> : ICollection<T>
{
private readonly List<T> _items = new();
public int Count => _items.Count;
public bool IsReadOnly => false;
public void Add(T item) => _items.Add(item);
public void Clear() => _items.Clear();
public bool Contains(T item) => _items.Contains(item);
public void CopyTo(T[] array, int arrayIndex) => _items.CopyTo(array, arrayIndex);
public bool Remove(T item) => _items.Remove(item);
public IEnumerator<T> GetEnumerator() => _items.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
[Fact]
public void DropDown_Renders_Placeholder()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenDropDown<int>>(parameters =>
{
parameters.Add(p => p.Placeholder, "Select an option");
});
Assert.Contains("Select an option", component.Markup);
Assert.Contains("rz-placeholder", component.Markup);
}
[Fact]
public void DropDown_Renders_AllowClear_WithValue()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var data = new[] { new DataItem { Text = "Item 1", Id = 1 } };
var component = ctx.RenderComponent<RadzenDropDown<int>>(parameters =>
{
parameters.Add(p => p.AllowClear, true);
parameters.Add(p => p.Data, data);
parameters.Add(p => p.TextProperty, nameof(DataItem.Text));
parameters.Add(p => p.ValueProperty, nameof(DataItem.Id));
parameters.Add(p => p.Value, 1);
});
Assert.Contains("rz-dropdown-clear-icon", component.Markup);
}
[Fact]
public void DropDown_DoesNotRender_AllowClear_WhenNotAllowed()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var data = new[] { new DataItem { Text = "Item 1", Id = 1 } };
var component = ctx.RenderComponent<RadzenDropDown<int>>(parameters =>
{
parameters.Add(p => p.AllowClear, false);
parameters.Add(p => p.Data, data);
parameters.Add(p => p.TextProperty, nameof(DataItem.Text));
parameters.Add(p => p.ValueProperty, nameof(DataItem.Id));
parameters.Add(p => p.Value, 1);
});
Assert.DoesNotContain("rz-dropdown-clear-icon", component.Markup);
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,323 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using Xunit;
namespace Radzen.Blazor.Tests
{
class TestEntity
{
public string Name { get; set; }
public int Age { get; set; }
public double Salary { get; set; }
public float Score { get; set; }
public decimal Balance { get; set; }
public short Level { get; set; }
public long Population { get; set; }
public Status AccountStatus { get; set; }
public DateTime CreatedAt { get; set; }
public DateTimeOffset LastUpdated { get; set; }
public Guid Id { get; set; }
public TimeOnly StartTime { get; set; }
public DateOnly BirthDate { get; set; }
public List<int> Scores { get; set; }
public List<string> Tags { get; set; }
public List<TestEntity> Children { get; set; }
public Address Address { get; set; }
public double[] Salaries { get; set; }
public float[] Heights { get; set; }
public decimal[] Balances { get; set; }
public short[] Levels { get; set; }
public long[] Populations { get; set; }
public string[] Names { get; set; }
public Guid[] Ids { get; set; }
public DateTime[] CreatedDates { get; set; }
public DateTimeOffset[] UpdatedDates { get; set; }
public TimeOnly[] StartTimes { get; set; }
public DateOnly[] BirthDates { get; set; }
public Status[] Statuses { get; set; }
}
enum Status
{
Active,
Inactive,
Suspended
}
class Address
{
public string City { get; set; }
public string Country { get; set; }
}
public class ExpressionSerializerTests
{
private readonly ExpressionSerializer _serializer = new ExpressionSerializer();
[Fact]
public void Serializes_SimpleBinaryExpression()
{
Expression<Func<int, bool>> expr = e => e > 10;
Assert.Equal("e => (e > 10)", _serializer.Serialize(expr));
}
[Fact]
public void Serializes_StringEquality()
{
Expression<Func<TestEntity, bool>> expr = e => e.Name == "John";
Assert.Equal("e => (e.Name == \"John\")", _serializer.Serialize(expr));
}
[Fact]
public void Serializes_IntComparison()
{
Expression<Func<TestEntity, bool>> expr = e => e.Age > 18;
Assert.Equal("e => (e.Age > 18)", _serializer.Serialize(expr));
}
[Fact]
public void Serializes_DoubleComparison()
{
Expression<Func<TestEntity, bool>> expr = e => e.Salary < 50000.50;
Assert.Equal("e => (e.Salary < 50000.5)", _serializer.Serialize(expr));
}
[Fact]
public void Serializes_FloatComparison()
{
Expression<Func<TestEntity, bool>> expr = e => e.Score >= 85.3f;
Assert.Equal("e => (e.Score >= 85.3)", _serializer.Serialize(expr));
}
[Fact]
public void Serializes_DecimalComparison()
{
Expression<Func<TestEntity, bool>> expr = e => e.Balance <= 1000.75m;
Assert.Equal("e => (e.Balance <= 1000.75)", _serializer.Serialize(expr));
}
[Fact]
public void Serializes_ShortComparison()
{
Expression<Func<TestEntity, bool>> expr = e => e.Level == 3;
Assert.Equal("e => (e.Level == 3)", _serializer.Serialize(expr));
}
[Fact]
public void Serializes_LongComparison()
{
Expression<Func<TestEntity, bool>> expr = e => e.Population > 1000000L;
Assert.Equal("e => (e.Population > 1000000)", _serializer.Serialize(expr));
}
[Fact]
public void Serializes_EnumComparison()
{
Expression<Func<TestEntity, bool>> expr = e => e.AccountStatus == Status.Inactive;
Assert.Equal("e => (e.AccountStatus == 1)", _serializer.Serialize(expr));
}
[Fact]
public void Serializes_ArrayContainsValue()
{
Expression<Func<TestEntity, bool>> expr = e => e.Scores.Contains(100);
Assert.Equal("e => e.Scores.Contains(100)", _serializer.Serialize(expr));
}
[Fact]
public void Serializes_ArrayNotContainsValue()
{
Expression<Func<TestEntity, bool>> expr = e => !e.Scores.Contains(100);
Assert.Equal("e => (!(e.Scores.Contains(100)))", _serializer.Serialize(expr));
}
[Fact]
public void Serializes_ArrayInValue()
{
Expression<Func<TestEntity, bool>> expr = e => e.Scores.Intersect(new [] { 100 }).Any();
Assert.Equal("e => e.Scores.Intersect(new [] { 100 }).Any()", _serializer.Serialize(expr));
}
[Fact]
public void Serializes_ArrayNotInValue()
{
Expression<Func<TestEntity, bool>> expr = e => e.Scores.Except(new[] { 100 }).Any();
Assert.Equal("e => e.Scores.Except(new [] { 100 }).Any()", _serializer.Serialize(expr));
}
[Fact]
public void Serializes_ArrayInValueOposite()
{
Expression<Func<TestEntity, bool>> expr = e => new[] { 100 }.Intersect(e.Scores).Any();
Assert.Equal("e => new [] { 100 }.Intersect(e.Scores).Any()", _serializer.Serialize(expr));
}
[Fact]
public void Serializes_ArrayNotInValueOposite()
{
Expression<Func<TestEntity, bool>> expr = e => new[] { 100 }.Except(e.Scores).Any();
Assert.Equal("e => new [] { 100 }.Except(e.Scores).Any()", _serializer.Serialize(expr));
}
[Fact]
public void Serializes_IntArrayInValueOposite()
{
Expression<Func<TestEntity, bool>> expr = e => new[] { 100 }.Intersect(e.Scores).Any();
Assert.Equal("e => new [] { 100 }.Intersect(e.Scores).Any()", _serializer.Serialize(expr));
}
[Fact]
public void Serializes_IntArrayNotInValueOposite()
{
Expression<Func<TestEntity, bool>> expr = e => !new[] { 100 }.Intersect(e.Scores).Any();
Assert.Equal("e => (!(new [] { 100 }.Intersect(e.Scores).Any()))", _serializer.Serialize(expr));
}
[Fact]
public void Serializes_DoubleArrayInValueOposite()
{
Expression<Func<TestEntity, bool>> expr = e => new[] { 99.99 }.Intersect(e.Salaries).Any();
Assert.Equal("e => new [] { 99.99 }.Intersect(e.Salaries).Any()", _serializer.Serialize(expr));
}
[Fact]
public void Serializes_FloatArrayInValueOposite()
{
Expression<Func<TestEntity, bool>> expr = e => new[] { 5.5f }.Intersect(e.Heights).Any();
Assert.Equal("e => new [] { 5.5 }.Intersect(e.Heights).Any()", _serializer.Serialize(expr));
}
[Fact]
public void Serializes_DecimalArrayInValueOposite()
{
Expression<Func<TestEntity, bool>> expr = e => new[] { 1000.75m }.Intersect(e.Balances).Any();
Assert.Equal("e => new [] { 1000.75 }.Intersect(e.Balances).Any()", _serializer.Serialize(expr));
}
[Fact]
public void Serializes_ShortArrayInValueOposite()
{
Expression<Func<TestEntity, bool>> expr = e => new [] { (short)3 }.Intersect(e.Levels).Any();
Assert.Equal("e => new [] { 3 }.Intersect(e.Levels).Any()", _serializer.Serialize(expr));
}
[Fact]
public void Serializes_LongArrayInValueOposite()
{
Expression<Func<TestEntity, bool>> expr = e => new [] { 1000000L }.Intersect(e.Populations).Any();
Assert.Equal("e => new [] { 1000000 }.Intersect(e.Populations).Any()", _serializer.Serialize(expr));
}
[Fact]
public void Serializes_StringArrayInValueOposite()
{
Expression<Func<TestEntity, bool>> expr = e => new[] { "Alice", "Bob" }.Intersect(e.Names).Any();
Assert.Equal("e => (new [] { \"Alice\", \"Bob\" }).Intersect(e.Names).Any()", _serializer.Serialize(expr));
}
[Fact]
public void Serializes_GuidArrayInValueOposite()
{
Expression<Func<TestEntity, bool>> expr = e => new[] { Guid.Parse("12345678-1234-1234-1234-123456789abc") }.Intersect(e.Ids).Any();
Assert.Equal("e => (new [] { Guid.Parse(\"12345678-1234-1234-1234-123456789abc\") }).Intersect(e.Ids).Any()", _serializer.Serialize(expr));
}
[Fact]
public void Serializes_DateTimeArrayInValueOposite()
{
Expression<Func<TestEntity, bool>> expr = e => new[] { DateTime.Parse("2023-01-01T00:00:00.000Z") }.Intersect(e.CreatedDates).Any();
Assert.Equal("e => (new [] { DateTime.Parse(\"2023-01-01T00:00:00.000Z\") }).Intersect(e.CreatedDates).Any()", _serializer.Serialize(expr));
}
[Fact]
public void Serializes_DateTimeOffsetArrayInValueOposite()
{
Expression<Func<TestEntity, bool>> expr = e => new[] { DateTimeOffset.Parse("2023-01-01T10:30:00.000+00:00") }.Intersect(e.UpdatedDates).Any();
Assert.Equal("e => (new [] { DateTimeOffset.Parse(\"2023-01-01T10:30:00.000+00:00\") }).Intersect(e.UpdatedDates).Any()", _serializer.Serialize(expr));
}
[Fact]
public void Serializes_DateTimeWithRoundtripKind()
{
Expression<Func<TestEntity, bool>> expr = e =>
DateTime.Parse("2023-01-01T00:00:00.000Z", null, DateTimeStyles.RoundtripKind) > e.CreatedAt;
Assert.Equal(
"e => (DateTime.Parse(\"2023-01-01T00:00:00.000Z\", null, (System.Globalization.DateTimeStyles)128) > e.CreatedAt)",
_serializer.Serialize(expr));
}
[Fact]
public void Serializes_TimeOnlyArrayInValueOposite()
{
Expression<Func<TestEntity, bool>> expr = e => new[] { TimeOnly.Parse("12:00:00") }.Intersect(e.StartTimes).Any();
Assert.Equal("e => (new [] { TimeOnly.Parse(\"12:00:00\") }).Intersect(e.StartTimes).Any()", _serializer.Serialize(expr));
}
[Fact]
public void Serializes_DateOnlyArrayInValueOposite()
{
Expression<Func<TestEntity, bool>> expr = e => new[] { DateOnly.Parse("2000-01-01") }.Intersect(e.BirthDates).Any();
Assert.Equal("e => (new [] { DateOnly.Parse(\"2000-01-01\") }).Intersect(e.BirthDates).Any()", _serializer.Serialize(expr));
}
[Fact]
public void Serializes_EnumArrayInValueOposite()
{
Expression<Func<TestEntity, bool>> expr = e => new[] { Status.Active, Status.Inactive }.Intersect(e.Statuses).Any();
Assert.Equal("e => (new [] { (Radzen.Blazor.Tests.Status)0, (Radzen.Blazor.Tests.Status)1 }).Intersect(e.Statuses).Any()", _serializer.Serialize(expr));
}
[Fact]
public void Serializes_ListContainsValue()
{
Expression<Func<TestEntity, bool>> expr = e => e.Tags.Contains("VIP");
Assert.Equal("e => e.Tags.Contains(\"VIP\")", _serializer.Serialize(expr));
}
[Fact]
public void Serializes_ListNotContainsValue()
{
Expression<Func<TestEntity, bool>> expr = e => !e.Tags.Contains("VIP");
Assert.Equal("e => (!(e.Tags.Contains(\"VIP\")))", _serializer.Serialize(expr));
}
[Fact]
public void Serializes_ListAnyCheck()
{
Expression<Func<TestEntity, bool>> expr = e => e.Children.Any(c => c.Age > 18);
Assert.Equal("e => e.Children.Any(c => (c.Age > 18))", _serializer.Serialize(expr));
}
[Fact]
public void Serializes_ListNotAnyCheck()
{
Expression<Func<TestEntity, bool>> expr = e => !e.Children.Any(c => c.Age > 18);
Assert.Equal("e => (!(e.Children.Any(c => (c.Age > 18))))", _serializer.Serialize(expr));
}
[Fact]
public void Serializes_EntitySubPropertyCheck()
{
Expression<Func<TestEntity, bool>> expr = e => e.Address.City == "New York";
Assert.Equal("e => (e.Address.City == \"New York\")", _serializer.Serialize(expr));
}
[Fact]
public void Serializes_ComplexExpressionWithProperties()
{
Expression<Func<TestEntity, bool>> expr = e => e.Age > 18 && e.Tags.Contains("Member") || e.Address.City == "London";
Assert.Equal("e => (((e.Age > 18) && e.Tags.Contains(\"Member\")) || (e.Address.City == \"London\"))", _serializer.Serialize(expr));
}
[Fact]
public void Serializes_NotContains()
{
Expression<Func<TestEntity, bool>> expr = e => !e.Tags.Contains("Member");
Assert.Equal("e => (!(e.Tags.Contains(\"Member\")))", _serializer.Serialize(expr));
}
}
}

View File

@@ -46,7 +46,7 @@ namespace Radzen.Blazor.Tests
component.SetParametersAndRender(parameters => parameters.Add(p => p.Icon, value));
Assert.Contains(@$"<i class=""rzi"">{value}</i>", component.Markup);
Assert.Contains(@$"<i class=""notranslate rzi"">{value}</i>", component.Markup);
}
[Fact]
@@ -104,11 +104,11 @@ namespace Radzen.Blazor.Tests
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AllowCollapse, true));
Assert.Contains(@"<span class=""rz-fieldset-toggler rzi rzi-w rzi-minus""></span>", component.Markup);
Assert.Contains(@"<span class=""notranslate rz-fieldset-toggler rzi rzi-w rzi-minus""></span>", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.Collapsed, true));
Assert.Contains(@"<span class=""rz-fieldset-toggler rzi rzi-w rzi-plus""></span>", component.Markup);
Assert.Contains(@"<span class=""notranslate rz-fieldset-toggler rzi rzi-w rzi-plus""></span>", component.Markup);
}
[Fact]
@@ -184,13 +184,13 @@ namespace Radzen.Blazor.Tests
Assert.Contains("SummaryContent", component.Markup);
Assert.Equal(
"",
component.Find(".rz-fieldset-content-summary").ParentElement.Attributes.First(attr => attr.Name == "style").Value
"false",
component.Find(".rz-fieldset-content-summary").ParentElement.ParentElement.Attributes.First(attr => attr.Name == "aria-hidden").Value
);
}
[Fact]
public void Fieldset_DontRenders_SummaryWhenOpen()
public void Fieldset_DoesNotRender_SummaryWhenOpen()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenFieldset>();
@@ -210,8 +210,8 @@ namespace Radzen.Blazor.Tests
Assert.Contains("SummaryContent", component.Markup);
Assert.Equal(
"display: none",
component.Find(".rz-fieldset-content-summary").ParentElement.Attributes.First(attr => attr.Name == "style").Value
"true",
component.Find(".rz-fieldset-content-summary").ParentElement.ParentElement.Attributes.First(attr => attr.Name == "aria-hidden").Value
);
}
}

View File

@@ -0,0 +1,182 @@
using Bunit;
using Xunit;
namespace Radzen.Blazor.Tests
{
public class FileInputTests
{
[Fact]
public void FileInput_Renders_WithClassName()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenFileInput<string>>();
Assert.Contains(@"rz-fileupload", component.Markup);
}
[Fact]
public void FileInput_Renders_ChooseButton()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenFileInput<string>>();
Assert.Contains("rz-fileupload-choose", component.Markup);
Assert.Contains("rz-button", component.Markup);
}
[Fact]
public void FileInput_Renders_ChooseText()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenFileInput<string>>(parameters =>
{
parameters.Add(p => p.ChooseText, "Select File");
});
Assert.Contains("Select File", component.Markup);
}
[Fact]
public void FileInput_Renders_DefaultChooseText()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenFileInput<string>>();
Assert.Contains("Choose", component.Markup);
}
[Fact]
public void FileInput_Renders_Disabled()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenFileInput<string>>(parameters =>
{
parameters.Add(p => p.Disabled, true);
});
Assert.Contains("rz-state-disabled", component.Markup);
Assert.Contains("disabled", component.Markup);
}
[Fact]
public void FileInput_Renders_Accept()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenFileInput<string>>(parameters =>
{
parameters.Add(p => p.Accept, "application/pdf");
});
Assert.Contains("accept=\"application/pdf\"", component.Markup);
}
[Fact]
public void FileInput_Renders_DefaultAccept()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenFileInput<string>>();
Assert.Contains("accept=\"image/*\"", component.Markup);
}
[Fact]
public void FileInput_Renders_FileInputElement()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenFileInput<string>>();
Assert.Contains("type=\"file\"", component.Markup);
}
[Fact]
public void FileInput_Renders_Title_WhenSet()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenFileInput<string>>(parameters =>
{
parameters.Add(p => p.Title, "MyDocument.pdf");
parameters.Add(p => p.Value, "data:application/pdf;base64,test");
});
Assert.Contains("MyDocument.pdf", component.Markup);
}
[Fact]
public void FileInput_Renders_FileName_WhenTitleNotSet()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenFileInput<string>>(parameters =>
{
parameters.Add(p => p.FileName, "document.pdf");
parameters.Add(p => p.Value, "data:application/pdf;base64,test");
});
Assert.Contains("document.pdf", component.Markup);
}
[Fact]
public void FileInput_Renders_DeleteButton_WhenValueSet()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenFileInput<string>>(parameters =>
{
parameters.Add(p => p.Value, "data:text/plain;base64,test");
});
Assert.Contains("rz-icon-trash", component.Markup);
}
[Fact]
public void FileInput_Renders_CustomDeleteText()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenFileInput<string>>(parameters =>
{
parameters.Add(p => p.DeleteText, "Remove File");
parameters.Add(p => p.Value, "data:text/plain;base64,test");
});
Assert.Contains("title=\"Remove File\"", component.Markup);
}
[Fact]
public void FileInput_Renders_ImagePreview_ForImageFile()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenFileInput<string>>(parameters =>
{
parameters.Add(p => p.Value, "data:image/png;base64,test");
});
Assert.Contains("<img", component.Markup);
}
[Fact]
public void FileInput_Renders_ImageAlternateText()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenFileInput<string>>(parameters =>
{
parameters.Add(p => p.ImageAlternateText, "User Photo");
parameters.Add(p => p.Value, "data:image/png;base64,test");
});
Assert.Contains("alt=\"User Photo\"", component.Markup);
}
}
}

View File

@@ -0,0 +1,163 @@
using Bunit;
using Xunit;
namespace Radzen.Blazor.Tests
{
public class FormFieldTests
{
[Fact]
public void FormField_Renders_WithClassName()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenFormField>();
Assert.Contains(@"rz-form-field", component.Markup);
}
[Fact]
public void FormField_Renders_Text()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenFormField>(parameters =>
{
parameters.Add(p => p.Text, "Email Address");
});
Assert.Contains("Email Address", component.Markup);
Assert.Contains("rz-form-field-label", component.Markup);
}
[Fact]
public void FormField_Renders_Variant_Outlined()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenFormField>(parameters =>
{
parameters.Add(p => p.Variant, Variant.Outlined);
});
Assert.Contains("rz-variant-outlined", component.Markup);
}
[Fact]
public void FormField_Renders_Variant_Filled()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenFormField>(parameters =>
{
parameters.Add(p => p.Variant, Variant.Filled);
});
Assert.Contains("rz-variant-filled", component.Markup);
}
[Fact]
public void FormField_Renders_Variant_Flat()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenFormField>(parameters =>
{
parameters.Add(p => p.Variant, Variant.Flat);
});
Assert.Contains("rz-variant-flat", component.Markup);
}
[Fact]
public void FormField_Renders_Variant_Text()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenFormField>(parameters =>
{
parameters.Add(p => p.Variant, Variant.Text);
});
Assert.Contains("rz-variant-text", component.Markup);
}
[Fact]
public void FormField_Renders_AllowFloatingLabel_True()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenFormField>(parameters =>
{
parameters.Add(p => p.AllowFloatingLabel, true);
});
Assert.Contains("rz-floating-label", component.Markup);
}
[Fact]
public void FormField_Renders_AllowFloatingLabel_False()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenFormField>(parameters =>
{
parameters.Add(p => p.AllowFloatingLabel, false);
});
Assert.DoesNotContain("rz-floating-label", component.Markup);
}
[Fact]
public void FormField_Renders_Component_Attribute()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenFormField>(parameters =>
{
parameters.Add(p => p.Component, "email-input");
});
Assert.Contains("for=\"email-input\"", component.Markup);
}
[Fact]
public void FormField_Renders_Helper()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenFormField>(parameters =>
{
parameters.Add(p => p.Helper, builder => builder.AddContent(0, "Enter your email address"));
});
Assert.Contains("rz-form-field-helper", component.Markup);
Assert.Contains("Enter your email address", component.Markup);
}
[Fact]
public void FormField_Renders_Start()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenFormField>(parameters =>
{
parameters.Add(p => p.Start, builder => builder.AddMarkupContent(0, "<span>Start</span>"));
});
Assert.Contains("rz-form-field-start", component.Markup);
Assert.Contains("Start", component.Markup);
}
[Fact]
public void FormField_Renders_End()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenFormField>(parameters =>
{
parameters.Add(p => p.End, builder => builder.AddMarkupContent(0, "<span>End</span>"));
});
Assert.Contains("rz-form-field-end", component.Markup);
Assert.Contains("End", component.Markup);
}
[Fact]
public void FormField_Renders_FormFieldContent()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenFormField>();
Assert.Contains("rz-form-field-content", component.Markup);
}
}
}

View File

@@ -0,0 +1,103 @@
using Bunit;
using Xunit;
namespace Radzen.Blazor.Tests
{
public class HeadingTests
{
[Fact]
public void Heading_Renders_WithClassName()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenHeading>();
Assert.Contains(@"rz-heading", component.Markup);
}
[Fact]
public void Heading_Renders_TextParameter()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenHeading>();
var text = "Test Heading";
component.SetParametersAndRender(parameters => parameters.Add(p => p.Text, text));
Assert.Contains(text, component.Markup);
}
[Fact]
public void Heading_Renders_H1_ByDefault()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenHeading>();
var text = "Heading Text";
component.SetParametersAndRender(parameters => parameters.Add(p => p.Text, text));
Assert.Contains("<h1", component.Markup);
}
[Fact]
public void Heading_Renders_H2_Size()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenHeading>();
var text = "Heading 2";
component.SetParametersAndRender(parameters =>
{
parameters.Add(p => p.Text, text);
parameters.Add(p => p.Size, "H2");
});
Assert.Contains("<h2", component.Markup);
Assert.Contains(text, component.Markup);
}
[Fact]
public void Heading_Renders_H3_Size()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenHeading>();
component.SetParametersAndRender(parameters => parameters.Add(p => p.Size, "H3"));
Assert.Contains("<h3", component.Markup);
}
[Fact]
public void Heading_Renders_H4_Size()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenHeading>();
component.SetParametersAndRender(parameters => parameters.Add(p => p.Size, "H4"));
Assert.Contains("<h4", component.Markup);
}
[Fact]
public void Heading_Renders_H5_Size()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenHeading>();
component.SetParametersAndRender(parameters => parameters.Add(p => p.Size, "H5"));
Assert.Contains("<h5", component.Markup);
}
[Fact]
public void Heading_Renders_H6_Size()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenHeading>();
component.SetParametersAndRender(parameters => parameters.Add(p => p.Size, "H6"));
Assert.Contains("<h6", component.Markup);
}
}
}

View File

@@ -0,0 +1,104 @@
using Bunit;
using Microsoft.Extensions.DependencyInjection;
using Xunit;
namespace Radzen.Blazor.Tests
{
public class HtmlEditorTests
{
[Fact]
public void HtmlEditor_Renders_WithClassName()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.Services.AddScoped<DialogService>();
var component = ctx.RenderComponent<RadzenHtmlEditor>();
Assert.Contains(@"rz-html-editor", component.Markup);
}
[Fact]
public void HtmlEditor_Renders_ShowToolbar_True()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.Services.AddScoped<DialogService>();
var component = ctx.RenderComponent<RadzenHtmlEditor>(parameters =>
{
parameters.Add(p => p.ShowToolbar, true);
});
Assert.Contains("rz-html-editor-toolbar", component.Markup);
}
[Fact]
public void HtmlEditor_Renders_ShowToolbar_False()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.Services.AddScoped<DialogService>();
var component = ctx.RenderComponent<RadzenHtmlEditor>(parameters =>
{
parameters.Add(p => p.ShowToolbar, false);
});
Assert.DoesNotContain("rz-html-editor-toolbar", component.Markup);
}
[Fact]
public void HtmlEditor_Renders_Mode_Design()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.Services.AddScoped<DialogService>();
var component = ctx.RenderComponent<RadzenHtmlEditor>(parameters =>
{
parameters.Add(p => p.Mode, HtmlEditorMode.Design);
});
// Design mode shows the content editable div
Assert.Contains("contenteditable", component.Markup);
}
[Fact]
public void HtmlEditor_Renders_Mode_Source()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.Services.AddScoped<DialogService>();
var component = ctx.RenderComponent<RadzenHtmlEditor>(parameters =>
{
parameters.Add(p => p.Mode, HtmlEditorMode.Source);
});
// Source mode shows the textarea for HTML editing
Assert.Contains("rz-html-editor-source", component.Markup);
}
[Fact]
public void HtmlEditor_Renders_Disabled_Attribute()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.Services.AddScoped<DialogService>();
var component = ctx.RenderComponent<RadzenHtmlEditor>(parameters =>
{
parameters.Add(p => p.Disabled, true);
});
Assert.Contains("disabled", component.Markup);
}
[Fact]
public void HtmlEditor_Renders_ContentArea()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.Services.AddScoped<DialogService>();
var component = ctx.RenderComponent<RadzenHtmlEditor>();
Assert.Contains("rz-html-editor-content", component.Markup);
}
}
}

View File

@@ -17,7 +17,7 @@ namespace Radzen.Blazor.Tests
component.SetParametersAndRender(parameters => parameters.Add(p => p.Icon, icon));
Assert.Contains(@$">{icon}</i>", component.Markup);
Assert.Contains(@$"<i class=""rzi""", component.Markup);
Assert.Contains(@$"class=""notranslate rzi""", component.Markup);
}
[Fact]
@@ -58,6 +58,18 @@ namespace Radzen.Blazor.Tests
Assert.Contains(@$"rzi-primary", component.Markup);
}
[Fact]
public void Icon_Renders_IconColor()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenIcon>();
component.SetParametersAndRender(parameters => parameters.Add(icon => icon.IconColor, Colors.Primary));
Assert.Contains(@$"color:", component.Markup);
}
[Fact]
public void Icon_NotRenders_IconStyleClass_WhenNull()
{
@@ -69,5 +81,17 @@ namespace Radzen.Blazor.Tests
Assert.DoesNotContain(@$"rzi-primary", component.Markup);
}
[Fact]
public void Icon_NotRenders_IconColor_WhenNull()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenIcon>();
component.SetParametersAndRender(parameters => parameters.Add(icon => icon.IconColor, null));
Assert.DoesNotContain(@$"color:", component.Markup);
}
}
}

View File

@@ -47,7 +47,7 @@ namespace Radzen.Blazor.Tests
component.SetParametersAndRender(parameters => parameters.Add(p => p.Icon, icon));
Assert.Contains(@$"<i class=""rzi"">{icon}</i>", component.Markup);
Assert.Contains(@$"<i class=""notranslate rzi"">{icon}</i>", component.Markup);
}
[Fact]
@@ -78,6 +78,20 @@ namespace Radzen.Blazor.Tests
Assert.Contains(@$"target=""{target}""", component.Markup);
}
[Fact]
public void Link_Renders_DisabledParameter()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenLink>();
component.SetParametersAndRender(parameters => parameters.Add(p => p.Disabled, true));
Assert.Contains("class=\"rz-link rz-link-disabled active\"", component.Markup);
Assert.DoesNotContain("href=", component.Markup);
}
[Fact]
public void Icon_Renders_UnmatchedParameter()
{

View File

@@ -0,0 +1,197 @@
using Bunit;
using Xunit;
using System.Collections.Generic;
namespace Radzen.Blazor.Tests
{
public class ListBoxTests
{
class Item
{
public int Id { get; set; }
public string Name { get; set; }
}
[Fact]
public void ListBox_Renders_WithClassName()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenListBox<int>>();
Assert.Contains(@"rz-listbox", component.Markup);
}
[Fact]
public void ListBox_Renders_WithData_SimpleList()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var data = new List<string> { "Apple", "Banana", "Cherry" };
var component = ctx.RenderComponent<RadzenListBox<string>>(parameters =>
{
parameters.Add(p => p.Data, data);
});
Assert.Contains("Apple", component.Markup);
Assert.Contains("Banana", component.Markup);
Assert.Contains("Cherry", component.Markup);
}
[Fact]
public void ListBox_Renders_WithData_CustomTextValueProperties()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var data = new List<Item>
{
new Item { Id = 1, Name = "First Item" },
new Item { Id = 2, Name = "Second Item" }
};
var component = ctx.RenderComponent<RadzenListBox<int>>(parameters =>
{
parameters.Add(p => p.Data, data);
parameters.Add(p => p.TextProperty, "Name");
parameters.Add(p => p.ValueProperty, "Id");
});
Assert.Contains("First Item", component.Markup);
Assert.Contains("Second Item", component.Markup);
}
[Fact]
public void ListBox_Renders_AllowFiltering()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenListBox<int>>(parameters =>
{
parameters.Add(p => p.AllowFiltering, true);
parameters.Add(p => p.Data, new List<string> { "Item1", "Item2" });
});
Assert.Contains("rz-listbox-filter", component.Markup);
Assert.Contains("rz-listbox-header", component.Markup);
}
[Fact]
public void ListBox_Renders_Disabled_Attribute()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenListBox<int>>(parameters =>
{
parameters.Add(p => p.Disabled, true);
});
Assert.Contains("disabled", component.Markup);
}
[Fact]
public void ListBox_Renders_Multiple_WithSelectAll()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenListBox<IEnumerable<int>>>(parameters =>
{
parameters.Add(p => p.Multiple, true);
parameters.Add(p => p.SelectAllText, "Select All Items");
parameters.Add(p => p.Data, new List<string> { "Item1", "Item2" });
});
Assert.Contains("Select All Items", component.Markup);
Assert.Contains("rz-chkbox", component.Markup);
}
[Fact]
public void ListBox_Renders_FilterPlaceholder()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenListBox<int>>(parameters =>
{
parameters.Add(p => p.Placeholder, "Select an item");
parameters.Add(p => p.AllowFiltering, true);
parameters.Add(p => p.Data, new List<string> { "Item1", "Item2" });
});
Assert.Contains("Select an item", component.Markup);
}
[Fact]
public void ListBox_Renders_Multiple_WithCheckboxes()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var data = new List<string> { "Item1", "Item2" };
var component = ctx.RenderComponent<RadzenListBox<IEnumerable<string>>>(parameters =>
{
parameters.Add(p => p.Multiple, true);
parameters.Add(p => p.Data, data);
});
// Multiple selection shows checkboxes in header
Assert.Contains("rz-listbox-header-w-checkbox", component.Markup);
}
[Fact]
public void ListBox_Renders_ReadOnly()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenListBox<int>>(parameters =>
{
parameters.Add(p => p.ReadOnly, true);
});
Assert.Contains("readonly", component.Markup);
}
[Fact]
public void ListBox_Renders_TabIndex()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenListBox<int>>();
Assert.Contains("tabindex=", component.Markup);
}
[Fact]
public void ListBox_Renders_ListWrapper()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var data = new List<string> { "Item1" };
var component = ctx.RenderComponent<RadzenListBox<string>>(parameters =>
{
parameters.Add(p => p.Data, data);
});
Assert.Contains("rz-listbox-list-wrapper", component.Markup);
Assert.Contains("rz-listbox-list", component.Markup);
}
[Fact]
public void ListBox_Renders_SearchAriaLabel()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenListBox<int>>(parameters =>
{
parameters.Add(p => p.AllowFiltering, true);
parameters.Add(p => p.SearchAriaLabel, "Search items");
parameters.Add(p => p.Data, new List<string> { "Item1" });
});
Assert.Contains("aria-label=\"Search items\"", component.Markup);
}
}
}

View File

@@ -0,0 +1,314 @@
using Xunit;
namespace Radzen.Blazor.Markdown.Tests;
public class BlockQuoteTests
{
private static string ToXml(string markdown)
{
var document = MarkdownParser.Parse(markdown);
return XmlVisitor.ToXml(document);
}
[Fact]
public void Parse_BasicBlockQuote()
{
Assert.Equal(@"<document>
<block_quote>
<paragraph>
<text>foo</text>
</paragraph>
</block_quote>
</document>", ToXml(@"> foo"));
}
[Theory]
[InlineData(@"> # Foo
> bar
> baz", @"<document>
<block_quote>
<heading level=""1"">
<text>Foo</text>
</heading>
<paragraph>
<text>bar</text>
<softbreak />
<text>baz</text>
</paragraph>
</block_quote>
</document>")]
[InlineData(@"># Foo
>bar
> baz", @"<document>
<block_quote>
<heading level=""1"">
<text>Foo</text>
</heading>
<paragraph>
<text>bar</text>
<softbreak />
<text>baz</text>
</paragraph>
</block_quote>
</document>")]
[InlineData(@" > # Foo
> bar
> baz", @"<document>
<block_quote>
<heading level=""1"">
<text>Foo</text>
</heading>
<paragraph>
<text>bar</text>
<softbreak />
<text>baz</text>
</paragraph>
</block_quote>
</document>")]
[InlineData(@" > # Foo
> bar
> baz", @"<document>
<code_block>&gt; # Foo
&gt; bar
&gt; baz
</code_block>
</document>")]
[InlineData(@"> # Foo
> bar
baz", @"<document>
<block_quote>
<heading level=""1"">
<text>Foo</text>
</heading>
<paragraph>
<text>bar</text>
<softbreak />
<text>baz</text>
</paragraph>
</block_quote>
</document>")]
[InlineData(@"> bar
baz
> foo", @"<document>
<block_quote>
<paragraph>
<text>bar</text>
<softbreak />
<text>baz</text>
<softbreak />
<text>foo</text>
</paragraph>
</block_quote>
</document>")]
[InlineData(@"> foo
---", @"<document>
<block_quote>
<paragraph>
<text>foo</text>
</paragraph>
</block_quote>
<thematic_break />
</document>")]
[InlineData(@"> - foo
- bar", @"<document>
<block_quote>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>foo</text>
</paragraph>
</item>
</list>
</block_quote>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>bar</text>
</paragraph>
</item>
</list>
</document>")]
[InlineData(@"> foo
bar", @"<document>
<block_quote>
<code_block>foo
</code_block>
</block_quote>
<code_block>bar
</code_block>
</document>")]
[InlineData(@"> ```
foo
```", @"<document>
<block_quote>
<code_block></code_block>
</block_quote>
<paragraph>
<text>foo</text>
</paragraph>
<code_block></code_block>
</document>")]
[InlineData(@"> foo
- bar", @"<document>
<block_quote>
<paragraph>
<text>foo</text>
<softbreak />
<text>- bar</text>
</paragraph>
</block_quote>
</document>")]
[InlineData(@">", @"<document>
<block_quote />
</document>")]
[InlineData(@">
>
> ", @"<document>
<block_quote />
</document>")]
[InlineData(@">
> foo
> ", @"<document>
<block_quote>
<paragraph>
<text>foo</text>
</paragraph>
</block_quote>
</document>")]
[InlineData(@"> foo
> bar", @"<document>
<block_quote>
<paragraph>
<text>foo</text>
</paragraph>
</block_quote>
<block_quote>
<paragraph>
<text>bar</text>
</paragraph>
</block_quote>
</document>")]
[InlineData(@"> foo
>
> bar", @"<document>
<block_quote>
<paragraph>
<text>foo</text>
</paragraph>
<paragraph>
<text>bar</text>
</paragraph>
</block_quote>
</document>")]
[InlineData(@"foo
> bar", @"<document>
<paragraph>
<text>foo</text>
</paragraph>
<block_quote>
<paragraph>
<text>bar</text>
</paragraph>
</block_quote>
</document>")]
[InlineData(@"> aaa
***
> bbb", @"<document>
<block_quote>
<paragraph>
<text>aaa</text>
</paragraph>
</block_quote>
<thematic_break />
<block_quote>
<paragraph>
<text>bbb</text>
</paragraph>
</block_quote>
</document>")]
[InlineData(@"> bar
baz", @"<document>
<block_quote>
<paragraph>
<text>bar</text>
<softbreak />
<text>baz</text>
</paragraph>
</block_quote>
</document>")]
[InlineData(@"> bar
baz", @"<document>
<block_quote>
<paragraph>
<text>bar</text>
</paragraph>
</block_quote>
<paragraph>
<text>baz</text>
</paragraph>
</document>")]
[InlineData(@"> bar
>
baz", @"<document>
<block_quote>
<paragraph>
<text>bar</text>
</paragraph>
</block_quote>
<paragraph>
<text>baz</text>
</paragraph>
</document>")]
[InlineData(@"> > > foo
bar", @"<document>
<block_quote>
<block_quote>
<block_quote>
<paragraph>
<text>foo</text>
<softbreak />
<text>bar</text>
</paragraph>
</block_quote>
</block_quote>
</block_quote>
</document>")]
[InlineData(@">>> foo
> bar
>>baz", @"<document>
<block_quote>
<block_quote>
<block_quote>
<paragraph>
<text>foo</text>
<softbreak />
<text>bar</text>
<softbreak />
<text>baz</text>
</paragraph>
</block_quote>
</block_quote>
</block_quote>
</document>")]
[InlineData(@"> code
> not code", @"<document>
<block_quote>
<code_block>code
</code_block>
</block_quote>
<block_quote>
<paragraph>
<text>not code</text>
</paragraph>
</block_quote>
</document>")]
public void Parse_BlockQuote(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
}

View File

@@ -0,0 +1,175 @@
using Xunit;
namespace Radzen.Blazor.Markdown.Tests;
public class CodeTests
{
private static string ToXml(string markdown)
{
var document = MarkdownParser.Parse(markdown);
return XmlVisitor.ToXml(document);
}
[Theory]
[InlineData("`foo`",
@"<document>
<paragraph>
<code>foo</code>
</paragraph>
</document>")]
[InlineData("`` foo ` bar ``",
@"<document>
<paragraph>
<code>foo ` bar</code>
</paragraph>
</document>")]
[InlineData("` `` `",
@"<document>
<paragraph>
<code>``</code>
</paragraph>
</document>")]
public void Parse_BasicCode_ReturnsCodeNode(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
[Theory]
[InlineData("` `` `",
@"<document>
<paragraph>
<code> `` </code>
</paragraph>
</document>")]
[InlineData("` a`",
@"<document>
<paragraph>
<code> a</code>
</paragraph>
</document>")]
[InlineData(@"` `
` `",
@"<document>
<paragraph>
<code> </code>
<softbreak />
<code> </code>
</paragraph>
</document>")]
public void Parse_CodeWithSpaces_PreservesSpaces(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
[Theory]
[InlineData(@"``
foo
bar
baz
``",
@"<document>
<paragraph>
<code>foo bar baz</code>
</paragraph>
</document>")]
[InlineData(@"``
foo
``",
@"<document>
<paragraph>
<code>foo </code>
</paragraph>
</document>")]
[InlineData(@"`foo bar
baz`",
@"<document>
<paragraph>
<code>foo bar baz</code>
</paragraph>
</document>")]
public void Parse_CodeWithLineBreaks_ConvertsToSpace(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
[Theory]
[InlineData("`foo\\`bar`", @"<document>
<paragraph>
<code>foo\</code>
<text>bar</text>
<text>`</text>
</paragraph>
</document>")]
[InlineData("``foo`bar``", @"<document>
<paragraph>
<code>foo`bar</code>
</paragraph>
</document>")]
[InlineData("` foo `` bar `", @"<document>
<paragraph>
<code>foo `` bar</code>
</paragraph>
</document>")]
public void Parse_CodeWithBacktics(string mardown, string expected)
{
Assert.Equal(expected, ToXml(mardown));
}
[Theory]
[InlineData("*foo`*`", @"<document>
<paragraph>
<text>*</text>
<text>foo</text>
<code>*</code>
</paragraph>
</document>")]
[InlineData("[not a `link](/foo`)",
@"<document>
<paragraph>
<text>[</text>
<text>not a </text>
<code>link](/foo</code>
<text>)</text>
</paragraph>
</document>")]
[InlineData("`<https://foo.bar.`baz>`",@"<document>
<paragraph>
<code>&lt;https://foo.bar.</code>
<text>baz&gt;</text>
<text>`</text>
</paragraph>
</document>")]
public void Parse_CodePrecedence(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
[Theory]
[InlineData("```foo``", @"<document>
<paragraph>
<text>```</text>
<text>foo</text>
<text>``</text>
</paragraph>
</document>")]
[InlineData("`foo", @"<document>
<paragraph>
<text>`</text>
<text>foo</text>
</paragraph>
</document>")]
[InlineData("`foo``bar``", @"<document>
<paragraph>
<text>`</text>
<text>foo</text>
<code>bar</code>
</paragraph>
</document>")]
public void Parse_UnmatchingBacktics(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
}

View File

@@ -0,0 +1,272 @@
using Xunit;
namespace Radzen.Blazor.Markdown.Tests;
public class EmphasisTests
{
private static string ToXml(string markdown)
{
var document = MarkdownParser.Parse(markdown);
return XmlVisitor.ToXml(document);
}
[Theory]
[InlineData(@"**foo** bar
baz",@"<document>
<paragraph>
<strong>
<text>foo</text>
</strong>
<text> bar</text>
<softbreak />
<text>baz</text>
</paragraph>
</document>")]
[InlineData("*foo bar*",
@"<document>
<paragraph>
<emph>
<text>foo bar</text>
</emph>
</paragraph>
</document>")]
[InlineData("a * foo bar*",
@"<document>
<paragraph>
<text>a </text>
<text>*</text>
<text> foo bar</text>
<text>*</text>
</paragraph>
</document>")]
[InlineData("a*\"foo\"*",
@"<document>
<paragraph>
<text>a</text>
<text>*</text>
<text>""foo""</text>
<text>*</text>
</paragraph>
</document>")]
[InlineData("* a *",
@"<document>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>a </text>
<text>*</text>
</paragraph>
</item>
</list>
</document>")]
[InlineData("foo*bar*",
@"<document>
<paragraph>
<text>foo</text>
<emph>
<text>bar</text>
</emph>
</paragraph>
</document>")]
[InlineData("5*6*78",
@"<document>
<paragraph>
<text>5</text>
<emph>
<text>6</text>
</emph>
<text>78</text>
</paragraph>
</document>")]
[InlineData("_foo bar_",
@"<document>
<paragraph>
<emph>
<text>foo bar</text>
</emph>
</paragraph>
</document>")]
[InlineData("_ foo bar_",
@"<document>
<paragraph>
<text>_</text>
<text> foo bar</text>
<text>_</text>
</paragraph>
</document>")]
[InlineData("a_\"foo\"_",
@"<document>
<paragraph>
<text>a</text>
<text>_</text>
<text>""foo""</text>
<text>_</text>
</paragraph>
</document>")]
[InlineData("foo_bar_",
@"<document>
<paragraph>
<text>foo</text>
<text>_</text>
<text>bar</text>
<text>_</text>
</paragraph>
</document>")]
[InlineData("5_6_78",
@"<document>
<paragraph>
<text>5</text>
<text>_</text>
<text>6</text>
<text>_</text>
<text>78</text>
</paragraph>
</document>")]
[InlineData("пристаням_стремятся_",
@"<document>
<paragraph>
<text>пристаням</text>
<text>_</text>
<text>стремятся</text>
<text>_</text>
</paragraph>
</document>")]
[InlineData("aa_\"bb\"_cc",
@"<document>
<paragraph>
<text>aa</text>
<text>_</text>
<text>""bb""</text>
<text>_</text>
<text>cc</text>
</paragraph>
</document>")]
[InlineData("foo-_(bar)_",
@"<document>
<paragraph>
<text>foo-</text>
<emph>
<text>(bar)</text>
</emph>
</paragraph>
</document>")]
[InlineData("_foo*",
@"<document>
<paragraph>
<text>_</text>
<text>foo</text>
<text>*</text>
</paragraph>
</document>")]
[InlineData("*foo bar *",
@"<document>
<paragraph>
<text>*</text>
<text>foo bar </text>
<text>*</text>
</paragraph>
</document>")]
[InlineData("*foo bar\nbaz*",
@"<document>
<paragraph>
<emph>
<text>foo bar</text>
<softbreak />
<text>baz</text>
</emph>
</paragraph>
</document>")]
[InlineData("*(*foo)",
@"<document>
<paragraph>
<text>*</text>
<text>(</text>
<text>*</text>
<text>foo)</text>
</paragraph>
</document>")]
[InlineData("*(*foo*)*",
@"<document>
<paragraph>
<emph>
<text>(</text>
<emph>
<text>foo</text>
</emph>
<text>)</text>
</emph>
</paragraph>
</document>")]
[InlineData("*foo*bar",
@"<document>
<paragraph>
<emph>
<text>foo</text>
</emph>
<text>bar</text>
</paragraph>
</document>")]
[InlineData("_foo bar _",
@"<document>
<paragraph>
<text>_</text>
<text>foo bar </text>
<text>_</text>
</paragraph>
</document>")]
[InlineData("_(_foo_)_",
@"<document>
<paragraph>
<emph>
<text>(</text>
<emph>
<text>foo</text>
</emph>
<text>)</text>
</emph>
</paragraph>
</document>")]
[InlineData("_foo_bar",
@"<document>
<paragraph>
<text>_</text>
<text>foo</text>
<text>_</text>
<text>bar</text>
</paragraph>
</document>")]
[InlineData("_пристаням_стремятся",
@"<document>
<paragraph>
<text>_</text>
<text>пристаням</text>
<text>_</text>
<text>стремятся</text>
</paragraph>
</document>")]
[InlineData("_foo_bar_baz_",
@"<document>
<paragraph>
<emph>
<text>foo</text>
<text>_</text>
<text>bar</text>
<text>_</text>
<text>baz</text>
</emph>
</paragraph>
</document>")]
[InlineData("_(bar)_.",
@"<document>
<paragraph>
<emph>
<text>(bar)</text>
</emph>
<text>.</text>
</paragraph>
</document>")]
public void Parse_EmphasisRules_AdheresToCommonMarkSpec(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
}

View File

@@ -0,0 +1,264 @@
using Xunit;
namespace Radzen.Blazor.Markdown.Tests;
public class FencedCodeBlockTests
{
private static string ToXml(string markdown)
{
var document = MarkdownParser.Parse(markdown);
return XmlVisitor.ToXml(document);
}
[Fact]
public void Parse_BasicFencedCodeBlock()
{
Assert.Equal(@"<document>
<code_block>foo
</code_block>
</document>", ToXml(@"```
foo
```"));
}
[Theory]
[InlineData(@"```
<
>
```", @"<document>
<code_block>&lt;
&gt;
</code_block>
</document>")]
[InlineData(@"~~~
<
>
~~~", @"<document>
<code_block>&lt;
&gt;
</code_block>
</document>")]
[InlineData(@"``
foo
``", @"<document>
<paragraph>
<code>foo</code>
</paragraph>
</document>")]
[InlineData(@"```
aaa
~~~
```", @"<document>
<code_block>aaa
~~~
</code_block>
</document>")]
[InlineData(@"~~~
aaa
```
~~~", @"<document>
<code_block>aaa
```
</code_block>
</document>")]
[InlineData(@"````
aaa
```
``````", @"<document>
<code_block>aaa
```
</code_block>
</document>")]
[InlineData(@"~~~~
aaa
~~~
~~~~", @"<document>
<code_block>aaa
~~~
</code_block>
</document>")]
[InlineData(@"```", @"<document>
<code_block></code_block>
</document>")]
[InlineData(@"`````
```
aaa", @"<document>
<code_block>
```
aaa
</code_block>
</document>")]
[InlineData(@"> ```
> aaa
bbb", @"<document>
<block_quote>
<code_block>aaa
</code_block>
</block_quote>
<paragraph>
<text>bbb</text>
</paragraph>
</document>")]
[InlineData(@"```
```", @"<document>
<code_block>
</code_block>
</document>")]
[InlineData(@"```
```", @"<document>
<code_block></code_block>
</document>")]
[InlineData(@" ```
aaa
aaa
```", @"<document>
<code_block>aaa
aaa
</code_block>
</document>")]
[InlineData(@" ```
aaa
aaa
aaa
```", @"<document>
<code_block>aaa
aaa
aaa
</code_block>
</document>")]
[InlineData(@" ```
aaa
aaa
aaa
```", @"<document>
<code_block>aaa
aaa
aaa
</code_block>
</document>")]
[InlineData(@" ```
aaa
```", @"<document>
<code_block>```
aaa
```
</code_block>
</document>")]
[InlineData(@"```
aaa
```", @"<document>
<code_block>aaa
</code_block>
</document>")]
[InlineData(@" ```
aaa
````", @"<document>
<code_block>aaa
</code_block>
</document>")]
[InlineData(@"```
aaa
```", @"<document>
<code_block>aaa
```
</code_block>
</document>")]
[InlineData(@"``` ```
aaa", @"<document>
<paragraph>
<code> </code>
<softbreak />
<text>aaa</text>
</paragraph>
</document>")]
[InlineData(@"~~~~~~
aaa
~~~ ~~", @"<document>
<code_block>aaa
~~~ ~~
</code_block>
</document>")]
[InlineData(@"foo
```
bar
```
baz", @"<document>
<paragraph>
<text>foo</text>
</paragraph>
<code_block>bar
</code_block>
<paragraph>
<text>baz</text>
</paragraph>
</document>")]
[InlineData(@"foo
---
~~~
bar
~~~
# baz", @"<document>
<heading level=""2"">
<text>foo</text>
</heading>
<code_block>bar
</code_block>
<heading level=""1"">
<text>baz</text>
</heading>
</document>")]
[InlineData(@"```ruby
def foo(x)
return 3
end
```", @"<document>
<code_block info=""ruby"">def foo(x)
return 3
end
</code_block>
</document>")]
[InlineData(@"~~~~ ruby startline=3 $%@#$
def foo(x)
return 3
end
~~~~~~~", @"<document>
<code_block info=""ruby startline=3 $%@#$"">def foo(x)
return 3
end
</code_block>
</document>")]
[InlineData(@"````;
````", @"<document>
<code_block info="";""></code_block>
</document>")]
[InlineData(@"``` aa ```
foo", @"<document>
<paragraph>
<code>aa</code>
<softbreak />
<text>foo</text>
</paragraph>
</document>")]
[InlineData(@"~~~ aa ``` ~~~
foo
~~~", @"<document>
<code_block info=""aa ``` ~~~"">foo
</code_block>
</document>")]
[InlineData(@"```
``` aaa
```", @"<document>
<code_block>``` aaa
</code_block>
</document>")]
public void Parse_FencedCodeBlock(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
}

View File

@@ -0,0 +1,132 @@
using Xunit;
namespace Radzen.Blazor.Markdown.Tests;
public class HardLineBreakTests
{
private static string ToXml(string markdown)
{
var document = MarkdownParser.Parse(markdown);
return XmlVisitor.ToXml(document);
}
[Theory]
[InlineData(@"foo
baz", @"<document>
<paragraph>
<text>foo</text>
<linebreak />
<text>baz</text>
</paragraph>
</document>")]
[InlineData("foo \r\nbaz", @"<document>
<paragraph>
<text>foo</text>
<linebreak />
<text>baz</text>
</paragraph>
</document>")]
[InlineData(@"foo\
baz", @"<document>
<paragraph>
<text>foo</text>
<linebreak />
<text>baz</text>
</paragraph>
</document>")]
[InlineData(@"foo
baz", @"<document>
<paragraph>
<text>foo</text>
<linebreak />
<text>baz</text>
</paragraph>
</document>")]
[InlineData(@"foo
bar", @"<document>
<paragraph>
<text>foo</text>
<linebreak />
<text>bar</text>
</paragraph>
</document>")]
[InlineData(@"foo\
bar", @"<document>
<paragraph>
<text>foo</text>
<linebreak />
<text>bar</text>
</paragraph>
</document>")]
[InlineData(@"*foo
bar*", @"<document>
<paragraph>
<emph>
<text>foo</text>
<linebreak />
<text>bar</text>
</emph>
</paragraph>
</document>")]
[InlineData(@"*foo\
bar*", @"<document>
<paragraph>
<emph>
<text>foo</text>
<linebreak />
<text>bar</text>
</emph>
</paragraph>
</document>")]
[InlineData(@"`code\
span`", @"<document>
<paragraph>
<code>code\ span</code>
</paragraph>
</document>")]
[InlineData(@"`code
span`", @"<document>
<paragraph>
<code>code span</code>
</paragraph>
</document>")]
[InlineData(@"<a href=""foo
bar"">", @"<document>
<paragraph>
<html_inline>&lt;a href=""foo
bar""&gt;</html_inline>
</paragraph>
</document>")]
[InlineData(@"<a href=""foo\
bar"">", @"<document>
<paragraph>
<html_inline>&lt;a href=""foo\
bar""&gt;</html_inline>
</paragraph>
</document>")]
[InlineData(@"foo\", @"<document>
<paragraph>
<text>foo\</text>
</paragraph>
</document>")]
[InlineData(@"foo ", @"<document>
<paragraph>
<text>foo</text>
</paragraph>
</document>")]
[InlineData(@"### foo\", @"<document>
<heading level=""3"">
<text>foo\</text>
</heading>
</document>")]
[InlineData(@"### foo ", @"<document>
<heading level=""3"">
<text>foo</text>
</heading>
</document>")]
public void Parse_HardLineBreak(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
}

View File

@@ -0,0 +1,511 @@
using Xunit;
namespace Radzen.Blazor.Markdown.Tests;
public class HeadingTests
{
private static string ToXml(string markdown)
{
var document = MarkdownParser.Parse(markdown);
return XmlVisitor.ToXml(document);
}
[Fact]
public void Parse_BasicAtxHeading()
{
Assert.Equal(@"<document>
<heading level=""1"">
<text>foo</text>
</heading>
</document>", ToXml("# foo"));
}
[Theory]
[InlineData(@"# foo
## foo
### foo
#### foo
##### foo
###### foo", @"<document>
<heading level=""1"">
<text>foo</text>
</heading>
<heading level=""2"">
<text>foo</text>
</heading>
<heading level=""3"">
<text>foo</text>
</heading>
<heading level=""4"">
<text>foo</text>
</heading>
<heading level=""5"">
<text>foo</text>
</heading>
<heading level=""6"">
<text>foo</text>
</heading>
</document>")]
[InlineData(@"####### foo", @"<document>
<paragraph>
<text>####### foo</text>
</paragraph>
</document>")]
[InlineData(@"#5 bolt
#hashtag", @"<document>
<paragraph>
<text>#5 bolt</text>
</paragraph>
<paragraph>
<text>#hashtag</text>
</paragraph>
</document>")]
[InlineData(@"\## foo", @"<document>
<paragraph>
<text>#</text>
<text># foo</text>
</paragraph>
</document>")]
[InlineData(@"# foo *bar* \*baz\*", @"<document>
<heading level=""1"">
<text>foo </text>
<emph>
<text>bar</text>
</emph>
<text> </text>
<text>*</text>
<text>baz</text>
<text>*</text>
</heading>
</document>")]
[InlineData(@"# foo ", @"<document>
<heading level=""1"">
<text>foo</text>
</heading>
</document>")]
[InlineData(@" ### foo
## foo
# foo", @"<document>
<heading level=""3"">
<text>foo</text>
</heading>
<heading level=""2"">
<text>foo</text>
</heading>
<heading level=""1"">
<text>foo</text>
</heading>
</document>")]
[InlineData(@" # foo", @"<document>
<code_block># foo
</code_block>
</document>")]
[InlineData(@"foo
# bar", @"<document>
<paragraph>
<text>foo</text>
<softbreak />
<text># bar</text>
</paragraph>
</document>")]
[InlineData(@"## foo ##
### bar ###", @"<document>
<heading level=""2"">
<text>foo</text>
</heading>
<heading level=""3"">
<text>bar</text>
</heading>
</document>")]
[InlineData(@"# foo ##################################
##### foo ##", @"<document>
<heading level=""1"">
<text>foo</text>
</heading>
<heading level=""5"">
<text>foo</text>
</heading>
</document>")]
[InlineData(@"### foo ### ", @"<document>
<heading level=""3"">
<text>foo</text>
</heading>
</document>")]
[InlineData(@"### foo ### b", @"<document>
<heading level=""3"">
<text>foo ### b</text>
</heading>
</document>")]
[InlineData(@"# foo#", @"<document>
<heading level=""1"">
<text>foo#</text>
</heading>
</document>")]
[InlineData(@"### foo \###
## foo #\##
# foo \#", @"<document>
<heading level=""3"">
<text>foo </text>
<text>#</text>
<text>##</text>
</heading>
<heading level=""2"">
<text>foo #</text>
<text>#</text>
<text>#</text>
</heading>
<heading level=""1"">
<text>foo </text>
<text>#</text>
</heading>
</document>")]
[InlineData(@"****
## foo
****", @"<document>
<thematic_break />
<heading level=""2"">
<text>foo</text>
</heading>
<thematic_break />
</document>")]
[InlineData(@"Foo bar
# baz
Bar foo", @"<document>
<paragraph>
<text>Foo bar</text>
</paragraph>
<heading level=""1"">
<text>baz</text>
</heading>
<paragraph>
<text>Bar foo</text>
</paragraph>
</document>")]
[InlineData(@"##
#
### ###", @"<document>
<heading level=""2"" />
<heading level=""1"" />
<heading level=""3"" />
</document>")]
public void Parse_AtxHeading(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
[Theory]
[InlineData(@"Foo *bar*
=========
Foo *baz*
---------", @"<document>
<heading level=""1"">
<text>Foo </text>
<emph>
<text>bar</text>
</emph>
</heading>
<heading level=""2"">
<text>Foo </text>
<emph>
<text>baz</text>
</emph>
</heading>
</document>")]
[InlineData(@"Foo *bar
baz*
====", @"<document>
<heading level=""1"">
<text>Foo </text>
<emph>
<text>bar</text>
<softbreak />
<text>baz</text>
</emph>
</heading>
</document>")]
[InlineData(@" Foo *bar
baz*
====", @"<document>
<heading level=""1"">
<text>Foo </text>
<emph>
<text>bar</text>
<softbreak />
<text>baz</text>
</emph>
</heading>
</document>")]
[InlineData(@"Foo
-------------------------
Foo
=", @"<document>
<heading level=""2"">
<text>Foo</text>
</heading>
<heading level=""1"">
<text>Foo</text>
</heading>
</document>")]
[InlineData(@" Foo
---
Foo
-----
Foo
===", @"<document>
<heading level=""2"">
<text>Foo</text>
</heading>
<heading level=""2"">
<text>Foo</text>
</heading>
<heading level=""1"">
<text>Foo</text>
</heading>
</document>")]
[InlineData(@" Foo
---
Foo
---", @"<document>
<code_block>Foo
---
Foo
</code_block>
<thematic_break />
</document>")]
[InlineData(@"Foo
---- ", @"<document>
<heading level=""2"">
<text>Foo</text>
</heading>
</document>")]
[InlineData(@"Foo
---", @"<document>
<paragraph>
<text>Foo</text>
<softbreak />
<text>---</text>
</paragraph>
</document>")]
[InlineData(@"Foo
= =
Foo
--- -", @"<document>
<paragraph>
<text>Foo</text>
<softbreak />
<text>= =</text>
</paragraph>
<paragraph>
<text>Foo</text>
</paragraph>
<thematic_break />
</document>")]
[InlineData(@"Foo
-----", @"<document>
<heading level=""2"">
<text>Foo</text>
</heading>
</document>")]
[InlineData(@"Foo\
----", @"<document>
<heading level=""2"">
<text>Foo\</text>
</heading>
</document>")]
[InlineData(@"`Foo
----
`
<a title=""a lot
---
of dashes""/>", @"<document>
<heading level=""2"">
<text>`</text>
<text>Foo</text>
</heading>
<paragraph>
<text>`</text>
</paragraph>
<heading level=""2"">
<text>&lt;a title=""a lot</text>
</heading>
<paragraph>
<text>of dashes""/&gt;</text>
</paragraph>
</document>")]
[InlineData(@"> Foo
---", @"<document>
<block_quote>
<paragraph>
<text>Foo</text>
</paragraph>
</block_quote>
<thematic_break />
</document>")]
[InlineData(@"> foo
bar
===", @"<document>
<block_quote>
<paragraph>
<text>foo</text>
<softbreak />
<text>bar</text>
<softbreak />
<text>===</text>
</paragraph>
</block_quote>
</document>")]
[InlineData(@"- Foo
---", @"<document>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>Foo</text>
</paragraph>
</item>
</list>
<thematic_break />
</document>")]
[InlineData(@"Foo
Bar
---", @"<document>
<heading level=""2"">
<text>Foo</text>
<softbreak />
<text>Bar</text>
</heading>
</document>")]
[InlineData(@"---
Foo
---
Bar
---
Baz", @"<document>
<thematic_break />
<heading level=""2"">
<text>Foo</text>
</heading>
<heading level=""2"">
<text>Bar</text>
</heading>
<paragraph>
<text>Baz</text>
</paragraph>
</document>")]
[InlineData(@"
====", @"<document>
<paragraph>
<text>====</text>
</paragraph>
</document>")]
[InlineData(@"---
---", @"<document>
<thematic_break />
<thematic_break />
</document>")]
[InlineData(@"- foo
-----", @"<document>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>foo</text>
</paragraph>
</item>
</list>
<thematic_break />
</document>")]
[InlineData(@" foo
---", @"<document>
<code_block>foo
</code_block>
<thematic_break />
</document>")]
[InlineData(@"> foo
-----", @"<document>
<block_quote>
<paragraph>
<text>foo</text>
</paragraph>
</block_quote>
<thematic_break />
</document>")]
[InlineData(@"\> foo
------", @"<document>
<heading level=""2"">
<text>&gt; foo</text>
</heading>
</document>")]
[InlineData(@"Foo
bar
---
baz", @"<document>
<paragraph>
<text>Foo</text>
</paragraph>
<heading level=""2"">
<text>bar</text>
</heading>
<paragraph>
<text>baz</text>
</paragraph>
</document>")]
[InlineData(@"Foo
bar
---
baz", @"<document>
<paragraph>
<text>Foo</text>
<softbreak />
<text>bar</text>
</paragraph>
<thematic_break />
<paragraph>
<text>baz</text>
</paragraph>
</document>")]
[InlineData(@"Foo
bar
* * *
baz", @"<document>
<paragraph>
<text>Foo</text>
<softbreak />
<text>bar</text>
</paragraph>
<thematic_break />
<paragraph>
<text>baz</text>
</paragraph>
</document>")]
[InlineData(@"Foo
bar
\---
baz", @"<document>
<paragraph>
<text>Foo</text>
<softbreak />
<text>bar</text>
<softbreak />
<text>-</text>
<text>--</text>
<softbreak />
<text>baz</text>
</paragraph>
</document>")]
public void Parse_SetExtHeading(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
}

View File

@@ -0,0 +1,487 @@
using Xunit;
namespace Radzen.Blazor.Markdown.Tests;
public class HtmlBlockTests
{
private static string ToXml(string markdown)
{
var document = MarkdownParser.Parse(markdown);
return XmlVisitor.ToXml(document);
}
[Theory]
[InlineData(@"<table><tr><td>
<pre>
**Hello**,
_world_.
</pre>
</td></tr></table>", @"<document>
<html_block>&lt;table&gt;&lt;tr&gt;&lt;td&gt;
&lt;pre&gt;
**Hello**,</html_block>
<paragraph>
<emph>
<text>world</text>
</emph>
<text>.</text>
<softbreak />
<html_inline>&lt;/pre&gt;</html_inline>
</paragraph>
<html_block>&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</html_block>
</document>")]
[InlineData(@"<table>
<tr>
<td>
hi
</td>
</tr>
</table>
okay.", @"<document>
<html_block>&lt;table&gt;
&lt;tr&gt;
&lt;td&gt;
hi
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;</html_block>
<paragraph>
<text>okay.</text>
</paragraph>
</document>")]
[InlineData(@" <div>
*hello*
<foo><a>", @"<document>
<html_block> &lt;div&gt;
*hello*
&lt;foo&gt;&lt;a&gt;</html_block>
</document>")]
[InlineData(@"</div>
*foo*", @"<document>
<html_block>&lt;/div&gt;
*foo*</html_block>
</document>")]
[InlineData(@"<DIV CLASS=""foo"">
*Markdown*
</DIV>", @"<document>
<html_block>&lt;DIV CLASS=""foo""&gt;</html_block>
<paragraph>
<emph>
<text>Markdown</text>
</emph>
</paragraph>
<html_block>&lt;/DIV&gt;</html_block>
</document>")]
[InlineData(@"<div id=""foo""
class=""bar"">
</div>", @"<document>
<html_block>&lt;div id=""foo""
class=""bar""&gt;
&lt;/div&gt;</html_block>
</document>")]
[InlineData(@"<div id=""foo"" class=""bar
baz"">
</div>", @"<document>
<html_block>&lt;div id=""foo"" class=""bar
baz""&gt;
&lt;/div&gt;</html_block>
</document>")]
[InlineData(@"<div>
*foo*
*bar*", @"<document>
<html_block>&lt;div&gt;
*foo*</html_block>
<paragraph>
<emph>
<text>bar</text>
</emph>
</paragraph>
</document>")]
[InlineData(@"<div id=""foo""
*hi*", @"<document>
<html_block>&lt;div id=""foo""
*hi*</html_block>
</document>")]
[InlineData(@"<div class
foo", @"<document>
<html_block>&lt;div class
foo</html_block>
</document>")]
[InlineData(@"<div *???-&&&-<---
*foo*", @"<document>
<html_block>&lt;div *???-&amp;&amp;&amp;-&lt;---
*foo*</html_block>
</document>")]
[InlineData(@"<div><a href=""bar"">*foo*</a></div>", @"<document>
<html_block>&lt;div&gt;&lt;a href=""bar""&gt;*foo*&lt;/a&gt;&lt;/div&gt;</html_block>
</document>")]
[InlineData(@"<table><tr><td>
foo
</td></tr></table>", @"<document>
<html_block>&lt;table&gt;&lt;tr&gt;&lt;td&gt;
foo
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</html_block>
</document>")]
[InlineData(@"<div></div>
``` c
int x = 33;
```", @"<document>
<html_block>&lt;div&gt;&lt;/div&gt;
``` c
int x = 33;
```</html_block>
</document>")]
[InlineData(@"<a href=""foo"">
*bar*
</a>", @"<document>
<html_block>&lt;a href=""foo""&gt;
*bar*
&lt;/a&gt;</html_block>
</document>")]
[InlineData(@"<Warning>
*bar*
</Warning>", @"<document>
<html_block>&lt;Warning&gt;
*bar*
&lt;/Warning&gt;</html_block>
</document>")]
[InlineData(@"<i class=""foo"">
*bar*
</i>", @"<document>
<html_block>&lt;i class=""foo""&gt;
*bar*
&lt;/i&gt;</html_block>
</document>")]
[InlineData(@"</ins>
*bar*", @"<document>
<html_block>&lt;/ins&gt;
*bar*</html_block>
</document>")]
[InlineData(@"<del>
*foo*
</del>", @"<document>
<html_block>&lt;del&gt;
*foo*
&lt;/del&gt;</html_block>
</document>")]
[InlineData(@"<del>
*foo*
</del>", @"<document>
<html_block>&lt;del&gt;</html_block>
<paragraph>
<emph>
<text>foo</text>
</emph>
</paragraph>
<html_block>&lt;/del&gt;</html_block>
</document>")]
[InlineData(@"<del>*foo*</del>", @"<document>
<paragraph>
<html_inline>&lt;del&gt;</html_inline>
<emph>
<text>foo</text>
</emph>
<html_inline>&lt;/del&gt;</html_inline>
</paragraph>
</document>")]
[InlineData(@"<pre language=""haskell""><code>
import Text.HTML.TagSoup
main :: IO ()
main = print $ parseTags tags
</code></pre>
okay", @"<document>
<html_block>&lt;pre language=""haskell""&gt;&lt;code&gt;
import Text.HTML.TagSoup
main :: IO ()
main = print $ parseTags tags
&lt;/code&gt;&lt;/pre&gt;</html_block>
<paragraph>
<text>okay</text>
</paragraph>
</document>")]
[InlineData(@"<script type=""text/javascript"">
// JavaScript example
document.getElementById(""demo"").innerHTML = ""Hello JavaScript!"";
</script>
okay", @"<document>
<html_block>&lt;script type=""text/javascript""&gt;
// JavaScript example
document.getElementById(""demo"").innerHTML = ""Hello JavaScript!"";
&lt;/script&gt;</html_block>
<paragraph>
<text>okay</text>
</paragraph>
</document>")]
[InlineData(@"<textarea>
*foo*
_bar_
</textarea>", @"<document>
<html_block>&lt;textarea&gt;
*foo*
_bar_
&lt;/textarea&gt;</html_block>
</document>")]
[InlineData(@"<style
type=""text/css"">
h1 {color:red;}
p {color:blue;}
</style>
okay",@"<document>
<html_block>&lt;style
type=""text/css""&gt;
h1 {color:red;}
p {color:blue;}
&lt;/style&gt;</html_block>
<paragraph>
<text>okay</text>
</paragraph>
</document>")]
[InlineData(@"<style
type=""text/css"">
foo", @"<document>
<html_block>&lt;style
type=""text/css""&gt;
foo</html_block>
</document>")]
[InlineData(@"> <div>
> foo
bar", @"<document>
<block_quote>
<html_block>&lt;div&gt;
foo</html_block>
</block_quote>
<paragraph>
<text>bar</text>
</paragraph>
</document>")]
[InlineData(@"- <div>
- foo", @"<document>
<list type=""bullet"" tight=""true"">
<item>
<html_block>&lt;div&gt;</html_block>
</item>
<item>
<paragraph>
<text>foo</text>
</paragraph>
</item>
</list>
</document>")]
[InlineData(@"<style>p{color:red;}</style>
*foo*", @"<document>
<html_block>&lt;style&gt;p{color:red;}&lt;/style&gt;</html_block>
<paragraph>
<emph>
<text>foo</text>
</emph>
</paragraph>
</document>")]
[InlineData(@"<!-- foo -->*bar*
*baz*", @"<document>
<html_block>&lt;!-- foo --&gt;*bar*</html_block>
<paragraph>
<emph>
<text>baz</text>
</emph>
</paragraph>
</document>")]
[InlineData(@"<script>
foo
</script>1. *bar*", @"<document>
<html_block>&lt;script&gt;
foo
&lt;/script&gt;1. *bar*</html_block>
</document>")]
[InlineData(@"<!-- Foo
bar
baz -->
okay", @"<document>
<html_block>&lt;!-- Foo
bar
baz --&gt;</html_block>
<paragraph>
<text>okay</text>
</paragraph>
</document>")]
[InlineData(@"<?php
echo '>';
?>
okay", @"<document>
<html_block>&lt;?php
echo '&gt;';
?&gt;</html_block>
<paragraph>
<text>okay</text>
</paragraph>
</document>")]
[InlineData(@"<!DOCTYPE html>", @"<document>
<html_block>&lt;!DOCTYPE html&gt;</html_block>
</document>")]
[InlineData(@"<![CDATA[
function matchwo(a,b)
{
if (a < b && a < 0) then {
return 1;
} else {
return 0;
}
}
]]>
okay", @"<document>
<html_block>&lt;![CDATA[
function matchwo(a,b)
{
if (a &lt; b &amp;&amp; a &lt; 0) then {
return 1;
} else {
return 0;
}
}
]]&gt;</html_block>
<paragraph>
<text>okay</text>
</paragraph>
</document>")]
[InlineData(@" <!-- foo -->
<!-- foo -->", @"<document>
<html_block> &lt;!-- foo --&gt;</html_block>
<code_block>&lt;!-- foo --&gt;
</code_block>
</document>")]
[InlineData(@" <div>
<div>", @"<document>
<html_block> &lt;div&gt;</html_block>
<code_block>&lt;div&gt;
</code_block>
</document>")]
[InlineData(@"Foo
<div>
bar
</div>", @"<document>
<paragraph>
<text>Foo</text>
</paragraph>
<html_block>&lt;div&gt;
bar
&lt;/div&gt;</html_block>
</document>")]
[InlineData(@"<div>
bar
</div>
*foo*", @"<document>
<html_block>&lt;div&gt;
bar
&lt;/div&gt;
*foo*</html_block>
</document>")]
[InlineData(@"Foo
<a href=""bar"">
baz", @"<document>
<paragraph>
<text>Foo</text>
<softbreak />
<html_inline>&lt;a href=""bar""&gt;</html_inline>
<softbreak />
<text>baz</text>
</paragraph>
</document>")]
[InlineData(@"<div>
*Emphasized* text.
</div>", @"<document>
<html_block>&lt;div&gt;</html_block>
<paragraph>
<emph>
<text>Emphasized</text>
</emph>
<text> text.</text>
</paragraph>
<html_block>&lt;/div&gt;</html_block>
</document>")]
[InlineData(@"<div>
*Emphasized* text.
</div>", @"<document>
<html_block>&lt;div&gt;
*Emphasized* text.
&lt;/div&gt;</html_block>
</document>")]
[InlineData(@"<table>
<tr>
<td>
Hi
</td>
</tr>
</table>", @"<document>
<html_block>&lt;table&gt;</html_block>
<html_block>&lt;tr&gt;</html_block>
<html_block>&lt;td&gt;
Hi
&lt;/td&gt;</html_block>
<html_block>&lt;/tr&gt;</html_block>
<html_block>&lt;/table&gt;</html_block>
</document>")]
[InlineData(@"<table>
<tr>
<td>
Hi
</td>
</tr>
</table>", @"<document>
<html_block>&lt;table&gt;</html_block>
<html_block> &lt;tr&gt;</html_block>
<code_block>&lt;td&gt;
Hi
&lt;/td&gt;
</code_block>
<html_block> &lt;/tr&gt;</html_block>
<html_block>&lt;/table&gt;</html_block>
</document>")]
public void Parse_HtmlBlock(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
}

View File

@@ -0,0 +1,144 @@
using Xunit;
namespace Radzen.Blazor.Markdown.Tests;
public class HtmlInlineTests
{
private static string ToXml(string markdown)
{
var document = MarkdownParser.Parse(markdown);
return XmlVisitor.ToXml(document);
}
[Theory]
[InlineData(@"<a><bab><c2c>", @"<document>
<paragraph>
<html_inline>&lt;a&gt;</html_inline>
<html_inline>&lt;bab&gt;</html_inline>
<html_inline>&lt;c2c&gt;</html_inline>
</paragraph>
</document>")]
[InlineData(@"<a/><b2/>", @"<document>
<paragraph>
<html_inline>&lt;a/&gt;</html_inline>
<html_inline>&lt;b2/&gt;</html_inline>
</paragraph>
</document>")]
[InlineData(@"<a /><b2
data=""foo"" >", @"<document>
<paragraph>
<html_inline>&lt;a /&gt;</html_inline>
<html_inline>&lt;b2
data=""foo"" &gt;</html_inline>
</paragraph>
</document>")]
[InlineData(@"<a foo=""bar"" bam = 'baz <em>""</em>'
_boolean zoop:33=zoop:33 />", @"<document>
<paragraph>
<html_inline>&lt;a foo=""bar"" bam = 'baz &lt;em&gt;""&lt;/em&gt;'
_boolean zoop:33=zoop:33 /&gt;</html_inline>
</paragraph>
</document>")]
[InlineData(@"Foo <responsive-image src=""foo.jpg"" />", @"<document>
<paragraph>
<text>Foo </text>
<html_inline>&lt;responsive-image src=""foo.jpg"" /&gt;</html_inline>
</paragraph>
</document>")]
[InlineData("<33> <__>", @"<document>
<paragraph>
<text>&lt;33&gt; &lt;</text>
<text>__</text>
<text>&gt;</text>
</paragraph>
</document>")]
[InlineData(@"<a h*#ref=""hi"">", @"<document>
<paragraph>
<text>&lt;a h</text>
<text>*</text>
<text>#ref=""hi""&gt;</text>
</paragraph>
</document>")]
[InlineData(@"<a href='bar'title=title>", @"<document>
<paragraph>
<text>&lt;a href='bar'title=title&gt;</text>
</paragraph>
</document>")]
[InlineData(@"</a></foo >", @"<document>
<paragraph>
<html_inline>&lt;/a&gt;</html_inline>
<html_inline>&lt;/foo &gt;</html_inline>
</paragraph>
</document>")]
[InlineData(@"</a href=""foo"">", @"<document>
<paragraph>
<text>&lt;/a href=""foo""&gt;</text>
</paragraph>
</document>")]
[InlineData(@"foo <!-- this is a --
comment - with hyphens -->", @"<document>
<paragraph>
<text>foo </text>
<html_inline>&lt;!-- this is a --
comment - with hyphens --&gt;</html_inline>
</paragraph>
</document>")]
[InlineData(@"foo <!--> foo -->
foo <!---> foo -->
", @"<document>
<paragraph>
<text>foo </text>
<html_inline>&lt;!--&gt;</html_inline>
<text> foo --&gt;</text>
</paragraph>
<paragraph>
<text>foo </text>
<html_inline>&lt;!---&gt;</html_inline>
<text> foo --&gt;</text>
</paragraph>
</document>")]
[InlineData(@"foo <?php echo $a; ?>", @"<document>
<paragraph>
<text>foo </text>
<html_inline>&lt;?php echo $a; ?&gt;</html_inline>
</paragraph>
</document>")]
[InlineData(@"foo <!ELEMENT br EMPTY>", @"<document>
<paragraph>
<text>foo </text>
<html_inline>&lt;!ELEMENT br EMPTY&gt;</html_inline>
</paragraph>
</document>")]
[InlineData(@"foo <![CDATA[>&<]]>", @"<document>
<paragraph>
<text>foo </text>
<html_inline>&lt;![CDATA[&gt;&amp;&lt;]]&gt;</html_inline>
</paragraph>
</document>")]
[InlineData(@"foo <a href=""&ouml;"">", @"<document>
<paragraph>
<text>foo </text>
<html_inline>&lt;a href=""&amp;ouml;""&gt;</html_inline>
</paragraph>
</document>")]
[InlineData(@"foo <a href=""\*"">", @"<document>
<paragraph>
<text>foo </text>
<html_inline>&lt;a href=""\*""&gt;</html_inline>
</paragraph>
</document>")]
[InlineData(@"foo <a href=""\"""">", @"<document>
<paragraph>
<text>foo &lt;a href=""</text>
<text>""</text>
<text>""&gt;</text>
</paragraph>
</document>")]
public void Parse_Html(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
}

View File

@@ -0,0 +1,85 @@
using Xunit;
namespace Radzen.Blazor.Markdown.Tests;
public class ImageTests
{
private static string ToXml(string markdown)
{
var document = MarkdownParser.Parse(markdown);
return XmlVisitor.ToXml(document);
}
[Theory]
[InlineData(@"![foo](/url ""title"")", @"<document>
<paragraph>
<image destination=""/url"" title=""title"">
<text>foo</text>
</image>
</paragraph>
</document>")]
[InlineData(@"![foo ![bar](/url)](/url2)", @"<document>
<paragraph>
<image destination=""/url2"" title="""">
<text>foo </text>
<image destination=""/url"" title="""">
<text>bar</text>
</image>
</image>
</paragraph>
</document>")]
[InlineData(@"![foo [bar](/url)](/url2)", @"<document>
<paragraph>
<image destination=""/url2"" title="""">
<text>foo </text>
<link destination=""/url"" title="""">
<text>bar</text>
</link>
</image>
</paragraph>
</document>")]
[InlineData(@"![foo](train.jpg)", @"<document>
<paragraph>
<image destination=""train.jpg"" title="""">
<text>foo</text>
</image>
</paragraph>
</document>")]
[InlineData(@"My ![foo bar](/path/to/train.jpg ""title"" )", @"<document>
<paragraph>
<text>My </text>
<image destination=""/path/to/train.jpg"" title=""title"">
<text>foo bar</text>
</image>
</paragraph>
</document>")]
[InlineData(@"![foo](<url>)", @"<document>
<paragraph>
<image destination=""url"" title="""">
<text>foo</text>
</image>
</paragraph>
</document>")]
[InlineData(@"![](/url)", @"<document>
<paragraph>
<image destination=""/url"" title="""" />
</paragraph>
</document>")]
[InlineData(@"__Applications__ ![macOS DMG](/assets/img/macOS-drag-and-drop.png)", @"<document>
<paragraph>
<strong>
<text>Applications</text>
</strong>
<text> </text>
<image destination=""/assets/img/macOS-drag-and-drop.png"" title="""">
<text>macOS DMG</text>
</image>
</paragraph>
</document>")]
public void Parse_BasicImages_ReturnsImageElement(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
}

View File

@@ -0,0 +1,145 @@
using Xunit;
namespace Radzen.Blazor.Markdown.Tests;
public class IndentedCodeBlockTests
{
private static string ToXml(string markdown)
{
var document = MarkdownParser.Parse(markdown);
return XmlVisitor.ToXml(document);
}
[Theory]
[InlineData(@" a simple
indented code block
", @"<document>
<code_block>a simple
indented code block
</code_block>
</document>")]
[InlineData(@" - foo
bar", @"<document>
<list type=""bullet"" tight=""false"">
<item>
<paragraph>
<text>foo</text>
</paragraph>
<paragraph>
<text>bar</text>
</paragraph>
</item>
</list>
</document>")]
[InlineData(
@"
1. foo
- bar", @"<document>
<list type=""ordered"" start=""1"" tight=""false"">
<item>
<paragraph>
<text>foo</text>
</paragraph>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>bar</text>
</paragraph>
</item>
</list>
</item>
</list>
</document>")]
[InlineData(@" <a/>
*hi*
- one", @"<document>
<code_block>&lt;a/&gt;
*hi*
- one
</code_block>
</document>")]
[InlineData(@" chunk1
chunk2
chunk3", @"<document>
<code_block>chunk1
chunk2
chunk3
</code_block>
</document>")]
[InlineData(@" chunk1
chunk2", @"<document>
<code_block>chunk1
chunk2
</code_block>
</document>")]
[InlineData(@"Foo
bar", @"<document>
<paragraph>
<text>Foo</text>
<softbreak />
<text>bar</text>
</paragraph>
</document>")]
[InlineData(@" foo
bar", @"<document>
<code_block>foo
</code_block>
<paragraph>
<text>bar</text>
</paragraph>
</document>")]
[InlineData(@"# Heading
foo
Heading
------
foo
----", @"<document>
<heading level=""1"">
<text>Heading</text>
</heading>
<code_block>foo
</code_block>
<heading level=""2"">
<text>Heading</text>
</heading>
<code_block>foo
</code_block>
<thematic_break />
</document>")]
[InlineData(@" foo
bar", @"<document>
<code_block> foo
bar
</code_block>
</document>")]
[InlineData(@"
foo
", @"<document>
<code_block>foo
</code_block>
</document>")]
[InlineData(@" foo ", @"<document>
<code_block>foo
</code_block>
</document>")]
public void Parse_IndentedCodeBlock(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
}

View File

@@ -0,0 +1,852 @@
using System.Runtime.InteropServices;
using Xunit;
namespace Radzen.Blazor.Markdown.Tests;
public class LinkTests
{
private static string ToXml(string markdown)
{
var document = MarkdownParser.Parse(markdown);
return XmlVisitor.ToXml(document);
}
[Theory]
[InlineData("[link](/uri \"title\")",
@"<document>
<paragraph>
<link destination=""/uri"" title=""title"">
<text>link</text>
</link>
</paragraph>
</document>")]
[InlineData("[link](/uri)", @"<document>
<paragraph>
<link destination=""/uri"" title="""">
<text>link</text>
</link>
</paragraph>
</document>")]
[InlineData("[](./target.md)", @"<document>
<paragraph>
<link destination=""./target.md"" title="""" />
</paragraph>
</document>")]
[InlineData("[link]()", @"<document>
<paragraph>
<link destination="""" title="""">
<text>link</text>
</link>
</paragraph>
</document>")]
[InlineData("[link](<>)", @"<document>
<paragraph>
<link destination="""" title="""">
<text>link</text>
</link>
</paragraph>
</document>")]
[InlineData("[]()", @"<document>
<paragraph>
<link destination="""" title="""" />
</paragraph>
</document>")]
public void Parse_BasicLinks_ReturnsLinkNode(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
[Theory]
[InlineData("[link](/my uri)", @"<document>
<paragraph>
<text>[</text>
<text>link</text>
<text>](/my uri)</text>
</paragraph>
</document>")]
[InlineData("[link](</my uri>)", @"<document>
<paragraph>
<link destination=""/my uri"" title="""">
<text>link</text>
</link>
</paragraph>
</document>")]
public void Parse_LinkDestinationWithSpaces(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
[Theory]
[InlineData(@"[link](foo
bar)", @"<document>
<paragraph>
<text>[</text>
<text>link</text>
<text>](foo</text>
<softbreak />
<text>bar)</text>
</paragraph>
</document>")]
public void Parse_LinkDestinationWithNewLines(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
[Theory]
[InlineData(@"[a](<b)c>)", @"<document>
<paragraph>
<link destination=""b)c"" title="""">
<text>a</text>
</link>
</paragraph>
</document>")]
public void Parse_LinkDestinationWithCloseParenthesis(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
[Theory]
[InlineData(@"[link](<foo\>)", @"<document>
<paragraph>
<text>[</text>
<text>link</text>
<text>](&lt;foo&gt;)</text>
</paragraph>
</document>")]
[InlineData(@"[a](<b)c
[a](<b)c>
[a](<b>c)", @"<document>
<paragraph>
<text>[</text>
<text>a</text>
<text>](&lt;b)c</text>
<softbreak />
<text>[</text>
<text>a</text>
<text>](&lt;b)c&gt;</text>
<softbreak />
<text>[</text>
<text>a</text>
<text>](</text>
<html_inline>&lt;b&gt;</html_inline>
<text>c)</text>
</paragraph>
</document>")]
public void Parse_LinkDestinationUnclosedPointyBracket(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
[Theory]
[InlineData(@"[link](\(foo\))", @"<document>
<paragraph>
<link destination=""(foo)"" title="""">
<text>link</text>
</link>
</paragraph>
</document>")]
[InlineData(@"[link](foo\)\:)", @"<document>
<paragraph>
<link destination=""foo):"" title="""">
<text>link</text>
</link>
</paragraph>
</document>")]
[InlineData(@"[link](foo\bar)", @"<document>
<paragraph>
<link destination=""foo\bar"" title="""">
<text>link</text>
</link>
</paragraph>
</document>")]
public void Parse_Escapes(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
[Theory]
[InlineData(@"[link](foo(and(bar)))", @"<document>
<paragraph>
<link destination=""foo(and(bar))"" title="""">
<text>link</text>
</link>
</paragraph>
</document>")]
[InlineData(@"[link](foo(and(bar))", @"<document>
<paragraph>
<text>[</text>
<text>link</text>
<text>](foo(and(bar))</text>
</paragraph>
</document>")]
[InlineData(@"[link](foo\(and\(bar\))", @"<document>
<paragraph>
<link destination=""foo(and(bar)"" title="""">
<text>link</text>
</link>
</paragraph>
</document>")]
[InlineData(@"[link](<foo(and(bar)>)", @"<document>
<paragraph>
<link destination=""foo(and(bar)"" title="""">
<text>link</text>
</link>
</paragraph>
</document>")]
public void Parse_BallancedParenthesisInLinkDestination(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
[Theory]
[InlineData(@"[link](#fragment)
[link](https://example.com#fragment)
[link](https://example.com?foo=3#frag)", @"<document>
<paragraph>
<link destination=""#fragment"" title="""">
<text>link</text>
</link>
<softbreak />
<link destination=""https://example.com#fragment"" title="""">
<text>link</text>
</link>
<softbreak />
<link destination=""https://example.com?foo=3#frag"" title="""">
<text>link</text>
</link>
</paragraph>
</document>")]
public void Parse_FragmentAndQueryStringInLinkDestination(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
[Theory]
[InlineData(@"[link](""title"")", @"<document>
<paragraph>
<link destination=""&quot;title&quot;"" title="""">
<text>link</text>
</link>
</paragraph>
</document>")]
public void Parse_QuotesInDestination(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
[Theory]
[InlineData(@"[link](/url ""title"")
[link](/url 'title')
[link](/url (title))", @"<document>
<paragraph>
<link destination=""/url"" title=""title"">
<text>link</text>
</link>
<softbreak />
<link destination=""/url"" title=""title"">
<text>link</text>
</link>
<softbreak />
<link destination=""/url"" title=""title"">
<text>link</text>
</link>
</paragraph>
</document>")]
[InlineData(@"[link](/url ""title ""and"" title"")", @"<document>
<paragraph>
<text>[</text>
<text>link</text>
<text>](/url ""title ""and"" title"")</text>
</paragraph>
</document>")]
[InlineData(@"[link](/url 'title ""and"" title')", @"<document>
<paragraph>
<link destination=""/url"" title=""title &quot;and&quot; title"">
<text>link</text>
</link>
</paragraph>
</document>")]
public void Parse_Title(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
[Theory]
[InlineData(@"[link]( /url
""title"" )", @"<document>
<paragraph>
<link destination=""/url"" title=""title"">
<text>link</text>
</link>
</paragraph>
</document>")]
[InlineData(@"[link] (/uri)", @"<document>
<paragraph>
<text>[</text>
<text>link</text>
<text>] (/uri)</text>
</paragraph>
</document>")]
public void Parse_SpacesInLink(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
[Theory]
[InlineData(@"[link [foo [bar]]](/uri)", @"<document>
<paragraph>
<link destination=""/uri"" title="""">
<text>link </text>
<text>[</text>
<text>foo </text>
<text>[</text>
<text>bar</text>
<text>]</text>
<text>]</text>
</link>
</paragraph>
</document>")]
[InlineData(@"[link] bar](/uri)", @"<document>
<paragraph>
<text>[</text>
<text>link</text>
<text>] bar](/uri)</text>
</paragraph>
</document>")]
[InlineData(@"[link [bar](/uri)", @"<document>
<paragraph>
<text>[</text>
<text>link </text>
<link destination=""/uri"" title="""">
<text>bar</text>
</link>
</paragraph>
</document>")]
[InlineData(@"[link \[bar](/uri)", @"<document>
<paragraph>
<link destination=""/uri"" title="""">
<text>link </text>
<text>[</text>
<text>bar</text>
</link>
</paragraph>
</document>")]
public void Parse_BracketsInText(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
[Theory]
[InlineData(@"[link *foo **bar** `#`*](/uri)", @"<document>
<paragraph>
<link destination=""/uri"" title="""">
<text>link </text>
<emph>
<text>foo </text>
<strong>
<text>bar</text>
</strong>
<text> </text>
<code>#</code>
</emph>
</link>
</paragraph>
</document>")]
[InlineData(@"[![alt](img)](url)", @"<document>
<paragraph>
<link destination=""url"" title="""">
<image destination=""img"" title="""">
<text>alt</text>
</image>
</link>
</paragraph>
</document>")]
public void Parse_LinkTextIsInlineContent(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
[Theory]
[InlineData(@"[foo [bar](/uri)](/uri)", @"<document>
<paragraph>
<text>[</text>
<text>foo </text>
<link destination=""/uri"" title="""">
<text>bar</text>
</link>
<text>](/uri)</text>
</paragraph>
</document>")]
[InlineData(@"[foo *[bar [baz](/uri)](/uri)*](/uri)", @"<document>
<paragraph>
<text>[</text>
<text>foo </text>
<emph>
<text>[</text>
<text>bar </text>
<link destination=""/uri"" title="""">
<text>baz</text>
</link>
<text>](/uri)</text>
</emph>
<text>](/uri)</text>
</paragraph>
</document>")]
public void Parse_NestedLinks(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
[Theory]
[InlineData(@"*[foo*](/uri)", @"<document>
<paragraph>
<text>*</text>
<link destination=""/uri"" title="""">
<text>foo</text>
<text>*</text>
</link>
</paragraph>
</document>")]
[InlineData(@"[foo *bar](baz*)", @"<document>
<paragraph>
<link destination=""baz*"" title="""">
<text>foo </text>
<text>*</text>
<text>bar</text>
</link>
</paragraph>
</document>")]
[InlineData(@"*foo [bar* baz]", @"<document>
<paragraph>
<emph>
<text>foo </text>
<text>[</text>
<text>bar</text>
</emph>
<text> baz</text>
<text>]</text>
</paragraph>
</document>")]
[InlineData(@"[foo`](/uri)`", @"<document>
<paragraph>
<text>[</text>
<text>foo</text>
<code>](/uri)</code>
</paragraph>
</document>")]
public void Parse_Precedence(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
[Theory]
[InlineData(@"<http://foo.bar.baz>", @"<document>
<paragraph>
<link destination=""http://foo.bar.baz"" title="""">
<text>http://foo.bar.baz</text>
</link>
</paragraph>
</document>")]
[InlineData(@"<https://foo.bar.baz/test?q=hello&id=22&boolean>", @"<document>
<paragraph>
<link destination=""https://foo.bar.baz/test?q=hello&amp;id=22&amp;boolean"" title="""">
<text>https://foo.bar.baz/test?q=hello&amp;id=22&amp;boolean</text>
</link>
</paragraph>
</document>")]
[InlineData(@"<irc://foo.bar:2233/baz>", @"<document>
<paragraph>
<link destination=""irc://foo.bar:2233/baz"" title="""">
<text>irc://foo.bar:2233/baz</text>
</link>
</paragraph>
</document>")]
[InlineData(@"<MAILTO:FOO@BAR.BAZ>", @"<document>
<paragraph>
<link destination=""MAILTO:FOO@BAR.BAZ"" title="""">
<text>MAILTO:FOO@BAR.BAZ</text>
</link>
</paragraph>
</document>")]
[InlineData(@"<https://foo.bar/baz bim>", @"<document>
<paragraph>
<text>&lt;https://foo.bar/baz bim&gt;</text>
</paragraph>
</document>")]
[InlineData(@"<https://example.com/\[\>", @"<document>
<paragraph>
<link destination=""https://example.com/\[\"" title="""">
<text>https://example.com/\[\</text>
</link>
</paragraph>
</document>")]
[InlineData(@"<foo@bar.example.com>", @"<document>
<paragraph>
<link destination=""mailto:foo@bar.example.com"" title="""">
<text>foo@bar.example.com</text>
</link>
</paragraph>
</document>")]
[InlineData(@"<foo+special@Bar.baz-bar0.com>", @"<document>
<paragraph>
<link destination=""mailto:foo+special@Bar.baz-bar0.com"" title="""">
<text>foo+special@Bar.baz-bar0.com</text>
</link>
</paragraph>
</document>")]
[InlineData(@"<foo\+@bar.example.com>", @"<document>
<paragraph>
<text>&lt;foo+@bar.example.com&gt;</text>
</paragraph>
</document>")]
[InlineData(@"<>", @"<document>
<paragraph>
<text>&lt;&gt;</text>
</paragraph>
</document>")]
[InlineData(@"< https://foo.bar >", @"<document>
<paragraph>
<text>&lt; https://foo.bar &gt;</text>
</paragraph>
</document>")]
[InlineData(@"<m:abc>", @"<document>
<paragraph>
<text>&lt;m:abc&gt;</text>
</paragraph>
</document>")]
[InlineData(@"<foo.bar.baz>", @"<document>
<paragraph>
<text>&lt;foo.bar.baz&gt;</text>
</paragraph>
</document>")]
[InlineData(@"https://example.com", @"<document>
<paragraph>
<text>https://example.com</text>
</paragraph>
</document>")]
[InlineData(@"foo@bar.example.com", @"<document>
<paragraph>
<text>foo@bar.example.com</text>
</paragraph>
</document>")]
public void Parse_AutoLink(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
[Theory]
[InlineData(@"[foo]: /url ""title""
[foo]", @"<document>
<paragraph>
<link destination=""/url"" title=""title"">
<text>foo</text>
</link>
</paragraph>
</document>")]
[InlineData(@" [foo]:
/url
'the title'
[foo]", @"<document>
<paragraph>
<link destination=""/url"" title=""the title"">
<text>foo</text>
</link>
</paragraph>
</document>")]
[InlineData(@"[Foo*bar\]]:my_(url) 'title (with parens)'
[Foo*bar\]]", @"<document>
<paragraph>
<link destination=""my_(url)"" title=""title (with parens)"">
<text>Foo</text>
<text>*</text>
<text>bar</text>
<text>]</text>
</link>
</paragraph>
</document>")]
[InlineData(@"[Foo bar]:
<my url>
'title'
[Foo bar]", @"<document>
<paragraph>
<link destination=""my url"" title=""title"">
<text>Foo bar</text>
</link>
</paragraph>
</document>")]
[InlineData(@"[foo]: /url '
title
line1
line2
'
[foo]", @"<document>
<paragraph>
<link destination=""/url"" title=""&#xA;title&#xA;line1&#xA;line2&#xA;"">
<text>foo</text>
</link>
</paragraph>
</document>")]
[InlineData(@"[foo]: /url 'title
with blank line'
[foo]", @"<document>
<paragraph>
<text>[</text>
<text>foo</text>
<text>]: /url 'title</text>
</paragraph>
<paragraph>
<text>with blank line'</text>
</paragraph>
<paragraph>
<text>[</text>
<text>foo</text>
<text>]</text>
</paragraph>
</document>")]
[InlineData(@"[foo]:
/url
[foo]", @"<document>
<paragraph>
<link destination=""/url"" title="""">
<text>foo</text>
</link>
</paragraph>
</document>")]
[InlineData(@"[foo]:
[foo]", @"<document>
<paragraph>
<text>[</text>
<text>foo</text>
<text>]:</text>
</paragraph>
<paragraph>
<text>[</text>
<text>foo</text>
<text>]</text>
</paragraph>
</document>")]
[InlineData(@"[foo]: <>
[foo]", @"<document>
<paragraph>
<link destination="""" title="""">
<text>foo</text>
</link>
</paragraph>
</document>")]
[InlineData(@"[foo]: <bar>(baz)
[foo]", @"<document>
<paragraph>
<text>[</text>
<text>foo</text>
<text>]: </text>
<html_inline>&lt;bar&gt;</html_inline>
<text>(baz)</text>
</paragraph>
<paragraph>
<text>[</text>
<text>foo</text>
<text>]</text>
</paragraph>
</document>")]
[InlineData(@"[foo]: /url\bar\*baz ""foo\""bar\baz""
[foo]
", @"<document>
<paragraph>
<link destination=""/url\bar*baz"" title=""foo\&quot;bar\baz"">
<text>foo</text>
</link>
</paragraph>
</document>")]
[InlineData(@"[foo]
[foo]: url", @"<document>
<paragraph>
<link destination=""url"" title="""">
<text>foo</text>
</link>
</paragraph>
</document>")]
[InlineData(@"[foo]
[foo]: first
[foo]: second", @"<document>
<paragraph>
<link destination=""first"" title="""">
<text>foo</text>
</link>
</paragraph>
</document>")]
[InlineData(@"[FOO]: /url
[Foo]", @"<document>
<paragraph>
<link destination=""/url"" title="""">
<text>Foo</text>
</link>
</paragraph>
</document>")]
[InlineData(@"[ΑΓΩ]: /φου
[αγω]", @"<document>
<paragraph>
<link destination=""/φου"" title="""">
<text>αγω</text>
</link>
</paragraph>
</document>")]
[InlineData(@"[foo]: /url", @"<document />")]
[InlineData(@"[
foo
]: /url
bar", @"<document>
<paragraph>
<text>bar</text>
</paragraph>
</document>")]
[InlineData(@"[foo]: /url ""title"" ok", @"<document>
<paragraph>
<text>[</text>
<text>foo</text>
<text>]: /url ""title"" ok</text>
</paragraph>
</document>")]
[InlineData(@"[foo]: /url
""title"" ok", @"<document>
<paragraph>
<text>""title"" ok</text>
</paragraph>
</document>")]
[InlineData(@" [foo]: /url ""title""
[foo]", @"<document>
<code_block>[foo]: /url ""title""
</code_block>
<paragraph>
<text>[</text>
<text>foo</text>
<text>]</text>
</paragraph>
</document>")]
[InlineData(@"```
[foo]: /url
```
[foo]", @"<document>
<code_block>[foo]: /url
</code_block>
<paragraph>
<text>[</text>
<text>foo</text>
<text>]</text>
</paragraph>
</document>")]
[InlineData(@"Foo
[bar]: /baz
[bar]", @"<document>
<paragraph>
<text>Foo</text>
<softbreak />
<text>[</text>
<text>bar</text>
<text>]: /baz</text>
</paragraph>
<paragraph>
<text>[</text>
<text>bar</text>
<text>]</text>
</paragraph>
</document>")]
[InlineData(@"# [Foo]
[foo]: /url
> bar", @"<document>
<heading level=""1"">
<link destination=""/url"" title="""">
<text>Foo</text>
</link>
</heading>
<block_quote>
<paragraph>
<text>bar</text>
</paragraph>
</block_quote>
</document>")]
[InlineData(@"[foo]: /url
bar
===
[foo]", @"<document>
<heading level=""1"">
<text>bar</text>
</heading>
<paragraph>
<link destination=""/url"" title="""">
<text>foo</text>
</link>
</paragraph>
</document>")]
[InlineData(@"[foo]: /url
===
[foo]", @"<document>
<paragraph>
<text>===</text>
<softbreak />
<link destination=""/url"" title="""">
<text>foo</text>
</link>
</paragraph>
</document>")]
[InlineData(@"[foo]: /foo-url ""foo""
[bar]: /bar-url
""bar""
[baz]: /baz-url
[foo],
[bar],
[baz]", @"<document>
<paragraph>
<link destination=""/foo-url"" title=""foo"">
<text>foo</text>
</link>
<text>,</text>
<softbreak />
<link destination=""/bar-url"" title=""bar"">
<text>bar</text>
</link>
<text>,</text>
<softbreak />
<link destination=""/baz-url"" title="""">
<text>baz</text>
</link>
</paragraph>
</document>")]
[InlineData(@"[foo]
> [foo]: /url
", @"<document>
<paragraph>
<link destination=""/url"" title="""">
<text>foo</text>
</link>
</paragraph>
<block_quote />
</document>")]
public void Parse_LinkReference(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
}

View File

@@ -0,0 +1,880 @@
using Xunit;
namespace Radzen.Blazor.Markdown.Tests;
public class ListItemTests
{
private static string ToXml(string markdown)
{
var document = MarkdownParser.Parse(markdown);
return XmlVisitor.ToXml(document);
}
[Theory]
[InlineData(@"1. A paragraph
with two lines.
indented code
> A block quote.", @"<document>
<list type=""ordered"" start=""1"" tight=""false"">
<item>
<paragraph>
<text>A paragraph</text>
<softbreak />
<text>with two lines.</text>
</paragraph>
<code_block>indented code
</code_block>
<block_quote>
<paragraph>
<text>A block quote.</text>
</paragraph>
</block_quote>
</item>
</list>
</document>")]
[InlineData(@"- one
two", @"<document>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>one</text>
</paragraph>
</item>
</list>
<paragraph>
<text>two</text>
</paragraph>
</document>")]
[InlineData(@"- one
two", @"<document>
<list type=""bullet"" tight=""false"">
<item>
<paragraph>
<text>one</text>
</paragraph>
<paragraph>
<text>two</text>
</paragraph>
</item>
</list>
</document>")]
[InlineData(@" - one
two", @"<document>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>one</text>
</paragraph>
</item>
</list>
<code_block> two
</code_block>
</document>")]
[InlineData(@" - one
two", @"<document>
<list type=""bullet"" tight=""false"">
<item>
<paragraph>
<text>one</text>
</paragraph>
<paragraph>
<text>two</text>
</paragraph>
</item>
</list>
</document>")]
[InlineData(@" > > 1. one
>>
>> two
", @"<document>
<block_quote>
<block_quote>
<list type=""ordered"" start=""1"" tight=""false"">
<item>
<paragraph>
<text>one</text>
</paragraph>
<paragraph>
<text>two</text>
</paragraph>
</item>
</list>
</block_quote>
</block_quote>
</document>")]
[InlineData(@">>- one
>>
> > two
", @"<document>
<block_quote>
<block_quote>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>one</text>
</paragraph>
</item>
</list>
<paragraph>
<text>two</text>
</paragraph>
</block_quote>
</block_quote>
</document>")]
[InlineData(@"-one
2.two
", @"<document>
<paragraph>
<text>-one</text>
</paragraph>
<paragraph>
<text>2.two</text>
</paragraph>
</document>")]
[InlineData(@"- foo
bar", @"<document>
<list type=""bullet"" tight=""false"">
<item>
<paragraph>
<text>foo</text>
</paragraph>
<paragraph>
<text>bar</text>
</paragraph>
</item>
</list>
</document>")]
[InlineData(@"1. foo
```
bar
```
baz
> bam", @"<document>
<list type=""ordered"" start=""1"" tight=""false"">
<item>
<paragraph>
<text>foo</text>
</paragraph>
<code_block>bar
</code_block>
<paragraph>
<text>baz</text>
</paragraph>
<block_quote>
<paragraph>
<text>bam</text>
</paragraph>
</block_quote>
</item>
</list>
</document>")]
[InlineData(@"- Foo
bar
baz", @"<document>
<list type=""bullet"" tight=""false"">
<item>
<paragraph>
<text>Foo</text>
</paragraph>
<code_block>bar
baz
</code_block>
</item>
</list>
</document>")]
[InlineData(@"123456789. ok", @"<document>
<list type=""ordered"" start=""123456789"" tight=""true"">
<item>
<paragraph>
<text>ok</text>
</paragraph>
</item>
</list>
</document>")]
[InlineData(@"1234567890. not ok", @"<document>
<paragraph>
<text>1234567890. not ok</text>
</paragraph>
</document>")]
[InlineData(@"0. ok", @"<document>
<list type=""ordered"" start=""0"" tight=""true"">
<item>
<paragraph>
<text>ok</text>
</paragraph>
</item>
</list>
</document>")]
[InlineData(@"003. ok", @"<document>
<list type=""ordered"" start=""3"" tight=""true"">
<item>
<paragraph>
<text>ok</text>
</paragraph>
</item>
</list>
</document>")]
[InlineData(@"-1. not ok", @"<document>
<paragraph>
<text>-1. not ok</text>
</paragraph>
</document>")]
[InlineData(@"- foo
bar", @"<document>
<list type=""bullet"" tight=""false"">
<item>
<paragraph>
<text>foo</text>
</paragraph>
<code_block>bar
</code_block>
</item>
</list>
</document>")]
[InlineData(@" 10. foo
bar", @"<document>
<list type=""ordered"" start=""10"" tight=""false"">
<item>
<paragraph>
<text>foo</text>
</paragraph>
<code_block>bar
</code_block>
</item>
</list>
</document>")]
[InlineData(@"1. indented code
paragraph
more code", @"<document>
<list type=""ordered"" start=""1"" tight=""false"">
<item>
<code_block>indented code
</code_block>
<paragraph>
<text>paragraph</text>
</paragraph>
<code_block>more code
</code_block>
</item>
</list>
</document>")]
[InlineData(@"- indented code
paragraph
more code", @"<document>
<list type=""bullet"" tight=""false"">
<item>
<code_block>indented code
</code_block>
<paragraph>
<text>paragraph</text>
</paragraph>
<code_block>more code
</code_block>
</item>
</list>
</document>")]
[InlineData(@"1. indented code
paragraph
more code", @"<document>
<list type=""ordered"" start=""1"" tight=""false"">
<item>
<code_block> indented code
</code_block>
<paragraph>
<text>paragraph</text>
</paragraph>
<code_block>more code
</code_block>
</item>
</list>
</document>")]
[InlineData(@"- foo
bar", @"<document>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>foo</text>
</paragraph>
</item>
</list>
<paragraph>
<text>bar</text>
</paragraph>
</document>")]
[InlineData(@"- foo
bar", @"<document>
<list type=""bullet"" tight=""false"">
<item>
<paragraph>
<text>foo</text>
</paragraph>
<paragraph>
<text>bar</text>
</paragraph>
</item>
</list>
</document>")]
[InlineData(@"-
foo
-
```
bar
```
-
baz", @"<document>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>foo</text>
</paragraph>
</item>
<item>
<code_block>bar
</code_block>
</item>
<item>
<code_block>baz
</code_block>
</item>
</list>
</document>")]
[InlineData(@"1.
foo", @"<document>
<list type=""ordered"" start=""1"" tight=""true"">
<item>
<paragraph>
<text>foo</text>
</paragraph>
</item>
</list>
</document>")]
[InlineData(@"-
foo", @"<document>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>foo</text>
</paragraph>
</item>
</list>
</document>")]
[InlineData(@"-
foo", @"<document>
<list type=""bullet"" tight=""true"">
<item />
</list>
<paragraph>
<text>foo</text>
</paragraph>
</document>")]
[InlineData(@"- foo
-
- bar", @"<document>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>foo</text>
</paragraph>
</item>
<item />
<item>
<paragraph>
<text>bar</text>
</paragraph>
</item>
</list>
</document>")]
[InlineData(@"- foo
-
- bar", @"<document>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>foo</text>
</paragraph>
</item>
<item />
<item>
<paragraph>
<text>bar</text>
</paragraph>
</item>
</list>
</document>")]
[InlineData(@"1. foo
2.
3. bar", @"<document>
<list type=""ordered"" start=""1"" tight=""true"">
<item>
<paragraph>
<text>foo</text>
</paragraph>
</item>
<item />
<item>
<paragraph>
<text>bar</text>
</paragraph>
</item>
</list>
</document>")]
[InlineData(@"*", @"<document>
<list type=""bullet"" tight=""true"">
<item />
</list>
</document>")]
[InlineData(@"foo
*
foo
1.", @"<document>
<paragraph>
<text>foo</text>
<softbreak />
<text>*</text>
</paragraph>
<paragraph>
<text>foo</text>
<softbreak />
<text>1.</text>
</paragraph>
</document>")]
[InlineData(@" 1. A paragraph
with two lines.
indented code
> A block quote.", @"<document>
<list type=""ordered"" start=""1"" tight=""false"">
<item>
<paragraph>
<text>A paragraph</text>
<softbreak />
<text>with two lines.</text>
</paragraph>
<code_block>indented code
</code_block>
<block_quote>
<paragraph>
<text>A block quote.</text>
</paragraph>
</block_quote>
</item>
</list>
</document>")]
[InlineData(@" 1. A paragraph
with two lines.
indented code
> A block quote.", @"<document>
<list type=""ordered"" start=""1"" tight=""false"">
<item>
<paragraph>
<text>A paragraph</text>
<softbreak />
<text>with two lines.</text>
</paragraph>
<code_block>indented code
</code_block>
<block_quote>
<paragraph>
<text>A block quote.</text>
</paragraph>
</block_quote>
</item>
</list>
</document>")]
[InlineData(@" 1. A paragraph
with two lines.
indented code
> A block quote.", @"<document>
<list type=""ordered"" start=""1"" tight=""false"">
<item>
<paragraph>
<text>A paragraph</text>
<softbreak />
<text>with two lines.</text>
</paragraph>
<code_block>indented code
</code_block>
<block_quote>
<paragraph>
<text>A block quote.</text>
</paragraph>
</block_quote>
</item>
</list>
</document>")]
[InlineData(@" 1. A paragraph
with two lines.
indented code
> A block quote.", @"<document>
<code_block>1. A paragraph
with two lines.
indented code
&gt; A block quote.
</code_block>
</document>")]
public void Parse_ListItem(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
[Theory]
[InlineData(@" 1. A paragraph
with two lines.
indented code
> A block quote.", @"<document>
<list type=""ordered"" start=""1"" tight=""false"">
<item>
<paragraph>
<text>A paragraph</text>
<softbreak />
<text>with two lines.</text>
</paragraph>
<paragraph>
<text>indented code</text>
</paragraph>
</item>
</list>
<code_block> &gt; A block quote.
</code_block>
</document>")]
[InlineData(@" 1. A paragraph
with two lines.", @"<document>
<list type=""ordered"" start=""1"" tight=""true"">
<item>
<paragraph>
<text>A paragraph</text>
<softbreak />
<text>with two lines.</text>
</paragraph>
</item>
</list>
</document>")]
[InlineData(@"> 1. > Blockquote
continued here.", @"<document>
<block_quote>
<list type=""ordered"" start=""1"" tight=""true"">
<item>
<block_quote>
<paragraph>
<text>Blockquote</text>
<softbreak />
<text>continued here.</text>
</paragraph>
</block_quote>
</item>
</list>
</block_quote>
</document>")]
[InlineData(@"> 1. > Blockquote
> continued here.", @"<document>
<block_quote>
<list type=""ordered"" start=""1"" tight=""true"">
<item>
<block_quote>
<paragraph>
<text>Blockquote</text>
<softbreak />
<text>continued here.</text>
</paragraph>
</block_quote>
</item>
</list>
</block_quote>
</document>")]
public void Parse_ListItem_WithLazyContinuation(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
[Theory]
[InlineData(@"- foo
- bar
- baz
- boo", @"<document>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>foo</text>
</paragraph>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>bar</text>
</paragraph>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>baz</text>
</paragraph>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>boo</text>
</paragraph>
</item>
</list>
</item>
</list>
</item>
</list>
</item>
</list>
</document>")]
[InlineData(@"- foo
- bar
- baz
- boo", @"<document>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>foo</text>
</paragraph>
</item>
<item>
<paragraph>
<text>bar</text>
</paragraph>
</item>
<item>
<paragraph>
<text>baz</text>
</paragraph>
</item>
<item>
<paragraph>
<text>boo</text>
</paragraph>
</item>
</list>
</document>")]
[InlineData(@"1. foo
1. bar
1. baz
1. boo", @"<document>
<list type=""ordered"" start=""1"" tight=""true"">
<item>
<paragraph>
<text>foo</text>
</paragraph>
</item>
<item>
<paragraph>
<text>bar</text>
</paragraph>
</item>
<item>
<paragraph>
<text>baz</text>
</paragraph>
</item>
<item>
<paragraph>
<text>boo</text>
</paragraph>
</item>
</list>
</document>")]
[InlineData(@"
1. foo
1. bar
1. baz
1. boo", @"<document>
<list type=""ordered"" start=""1"" tight=""true"">
<item>
<paragraph>
<text>foo</text>
</paragraph>
<list type=""ordered"" start=""1"" tight=""true"">
<item>
<paragraph>
<text>bar</text>
</paragraph>
<list type=""ordered"" start=""1"" tight=""true"">
<item>
<paragraph>
<text>baz</text>
</paragraph>
<list type=""ordered"" start=""1"" tight=""true"">
<item>
<paragraph>
<text>boo</text>
</paragraph>
</item>
</list>
</item>
</list>
</item>
</list>
</item>
</list>
</document>")]
[InlineData(@"10) foo
- bar", @"<document>
<list type=""ordered"" start=""10"" tight=""true"">
<item>
<paragraph>
<text>foo</text>
</paragraph>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>bar</text>
</paragraph>
</item>
</list>
</item>
</list>
</document>")]
[InlineData(@"
10) foo
- bar", @"<document>
<list type=""ordered"" start=""10"" tight=""true"">
<item>
<paragraph>
<text>foo</text>
</paragraph>
</item>
</list>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>bar</text>
</paragraph>
</item>
</list>
</document>")]
[InlineData(@"- - foo", @"<document>
<list type=""bullet"" tight=""true"">
<item>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>foo</text>
</paragraph>
</item>
</list>
</item>
</list>
</document>")]
[InlineData(@"1. - foo", @"<document>
<list type=""ordered"" start=""1"" tight=""true"">
<item>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>foo</text>
</paragraph>
</item>
</list>
</item>
</list>
</document>")]
[InlineData(@"1. 1. foo", @"<document>
<list type=""ordered"" start=""1"" tight=""true"">
<item>
<list type=""ordered"" start=""1"" tight=""true"">
<item>
<paragraph>
<text>foo</text>
</paragraph>
</item>
</list>
</item>
</list>
</document>")]
[InlineData(@"- 1. foo", @"<document>
<list type=""bullet"" tight=""true"">
<item>
<list type=""ordered"" start=""1"" tight=""true"">
<item>
<paragraph>
<text>foo</text>
</paragraph>
</item>
</list>
</item>
</list>
</document>")]
[InlineData(@"1. - 2. foo", @"<document>
<list type=""ordered"" start=""1"" tight=""true"">
<item>
<list type=""bullet"" tight=""true"">
<item>
<list type=""ordered"" start=""2"" tight=""true"">
<item>
<paragraph>
<text>foo</text>
</paragraph>
</item>
</list>
</item>
</list>
</item>
</list>
</document>")]
[InlineData(@"- # Foo
- Bar
---
baz", @"<document>
<list type=""bullet"" tight=""true"">
<item>
<heading level=""1"">
<text>Foo</text>
</heading>
</item>
<item>
<heading level=""2"">
<text>Bar</text>
</heading>
<paragraph>
<text>baz</text>
</paragraph>
</item>
</list>
</document>")]
public void Parse_ListItem_WithNesting(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
}

View File

@@ -0,0 +1,693 @@
using Xunit;
namespace Radzen.Blazor.Markdown.Tests;
public class ListTests
{
private static string ToXml(string markdown)
{
var document = MarkdownParser.Parse(markdown);
return XmlVisitor.ToXml(document);
}
[Theory]
[InlineData(@"- foo
- bar
+ baz", @"<document>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>foo</text>
</paragraph>
</item>
<item>
<paragraph>
<text>bar</text>
</paragraph>
</item>
</list>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>baz</text>
</paragraph>
</item>
</list>
</document>")]
[InlineData(@"1. foo
2. bar
3) baz", @"<document>
<list type=""ordered"" start=""1"" tight=""true"">
<item>
<paragraph>
<text>foo</text>
</paragraph>
</item>
<item>
<paragraph>
<text>bar</text>
</paragraph>
</item>
</list>
<list type=""ordered"" start=""3"" tight=""true"">
<item>
<paragraph>
<text>baz</text>
</paragraph>
</item>
</list>
</document>")]
[InlineData(@"Foo
- bar
- baz", @"<document>
<paragraph>
<text>Foo</text>
</paragraph>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>bar</text>
</paragraph>
</item>
<item>
<paragraph>
<text>baz</text>
</paragraph>
</item>
</list>
</document>")]
public void Parse_List(string markdown, string expected)
{
var actual = ToXml(markdown);
Assert.Equal(expected, actual);
}
[Theory]
[InlineData(@"The number of windows in my house is
14. The number of doors is 6.", @"<document>
<paragraph>
<text>The number of windows in my house is</text>
<softbreak />
<text>14. The number of doors is 6.</text>
</paragraph>
</document>")]
[InlineData(@"The number of windows in my house is
1. The number of doors is 6.", @"<document>
<paragraph>
<text>The number of windows in my house is</text>
</paragraph>
<list type=""ordered"" start=""1"" tight=""true"">
<item>
<paragraph>
<text>The number of doors is 6.</text>
</paragraph>
</item>
</list>
</document>")]
public void Parse_OnlyNumberedListsThatStartWithOneCanInterruptParagraphs(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
[Theory]
[InlineData(@"- foo
- bar
- baz", @"<document>
<list type=""bullet"" tight=""false"">
<item>
<paragraph>
<text>foo</text>
</paragraph>
</item>
<item>
<paragraph>
<text>bar</text>
</paragraph>
</item>
<item>
<paragraph>
<text>baz</text>
</paragraph>
</item>
</list>
</document>")]
[InlineData(@"- foo
- bar
- baz
bim
", @"<document>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>foo</text>
</paragraph>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>bar</text>
</paragraph>
<list type=""bullet"" tight=""false"">
<item>
<paragraph>
<text>baz</text>
</paragraph>
<paragraph>
<text>bim</text>
</paragraph>
</item>
</list>
</item>
</list>
</item>
</list>
</document>")]
[InlineData(@"- a
- b
- c", @"<document>
<list type=""bullet"" tight=""false"">
<item>
<paragraph>
<text>a</text>
</paragraph>
</item>
<item>
<paragraph>
<text>b</text>
</paragraph>
</item>
<item>
<paragraph>
<text>c</text>
</paragraph>
</item>
</list>
</document>")]
[InlineData(@"* a
*
* c", @"<document>
<list type=""bullet"" tight=""false"">
<item>
<paragraph>
<text>a</text>
</paragraph>
</item>
<item />
<item>
<paragraph>
<text>c</text>
</paragraph>
</item>
</list>
</document>")]
[InlineData(@"- a
- b
c
- d", @"<document>
<list type=""bullet"" tight=""false"">
<item>
<paragraph>
<text>a</text>
</paragraph>
</item>
<item>
<paragraph>
<text>b</text>
</paragraph>
<paragraph>
<text>c</text>
</paragraph>
</item>
<item>
<paragraph>
<text>d</text>
</paragraph>
</item>
</list>
</document>")]
[InlineData(@"- a
- b
[ref]: /url
- d", @"<document>
<list type=""bullet"" tight=""false"">
<item>
<paragraph>
<text>a</text>
</paragraph>
</item>
<item>
<paragraph>
<text>b</text>
</paragraph>
</item>
<item>
<paragraph>
<text>d</text>
</paragraph>
</item>
</list>
</document>")]
[InlineData(@"- a
- ```
b
```
- c", @"<document>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>a</text>
</paragraph>
</item>
<item>
<code_block>b
</code_block>
</item>
<item>
<paragraph>
<text>c</text>
</paragraph>
</item>
</list>
</document>")]
[InlineData(@"- a
- b
c
- d", @"<document>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>a</text>
</paragraph>
<list type=""bullet"" tight=""false"">
<item>
<paragraph>
<text>b</text>
</paragraph>
<paragraph>
<text>c</text>
</paragraph>
</item>
</list>
</item>
<item>
<paragraph>
<text>d</text>
</paragraph>
</item>
</list>
</document>")]
[InlineData(@"* a
> b
>
* c", @"<document>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>a</text>
</paragraph>
<block_quote>
<paragraph>
<text>b</text>
</paragraph>
</block_quote>
</item>
<item>
<paragraph>
<text>c</text>
</paragraph>
</item>
</list>
</document>")]
[InlineData(@"- a
> b
```
c
```
- d
", @"<document>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>a</text>
</paragraph>
<block_quote>
<paragraph>
<text>b</text>
</paragraph>
</block_quote>
<code_block>c
</code_block>
</item>
<item>
<paragraph>
<text>d</text>
</paragraph>
</item>
</list>
</document>")]
[InlineData(@"- a", @"<document>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>a</text>
</paragraph>
</item>
</list>
</document>")]
[InlineData(@"- a
- b", @"<document>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>a</text>
</paragraph>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>b</text>
</paragraph>
</item>
</list>
</item>
</list>
</document>")]
[InlineData(@"1. ```
foo
```
bar", @"<document>
<list type=""ordered"" start=""1"" tight=""false"">
<item>
<code_block>foo
</code_block>
<paragraph>
<text>bar</text>
</paragraph>
</item>
</list>
</document>")]
[InlineData(@"* foo
* bar
baz", @"<document>
<list type=""bullet"" tight=""false"">
<item>
<paragraph>
<text>foo</text>
</paragraph>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>bar</text>
</paragraph>
</item>
</list>
<paragraph>
<text>baz</text>
</paragraph>
</item>
</list>
</document>")]
[InlineData(@"- a
- b
- c
- d
- e
- f", @"<document>
<list type=""bullet"" tight=""false"">
<item>
<paragraph>
<text>a</text>
</paragraph>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>b</text>
</paragraph>
</item>
<item>
<paragraph>
<text>c</text>
</paragraph>
</item>
</list>
</item>
<item>
<paragraph>
<text>d</text>
</paragraph>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>e</text>
</paragraph>
</item>
<item>
<paragraph>
<text>f</text>
</paragraph>
</item>
</list>
</item>
</list>
</document>")]
public void Parse_TightAndLooseLists(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
[Theory]
[InlineData(@"- foo
- bar
<!-- -->
- baz
- bim", @"<document>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>foo</text>
</paragraph>
</item>
<item>
<paragraph>
<text>bar</text>
</paragraph>
</item>
</list>
<html_block>&lt;!-- --&gt;</html_block>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>baz</text>
</paragraph>
</item>
<item>
<paragraph>
<text>bim</text>
</paragraph>
</item>
</list>
</document>")]
[InlineData(@"- foo
notcode
- foo
<!-- -->
code", @"<document>
<list type=""bullet"" tight=""false"">
<item>
<paragraph>
<text>foo</text>
</paragraph>
<paragraph>
<text>notcode</text>
</paragraph>
</item>
<item>
<paragraph>
<text>foo</text>
</paragraph>
</item>
</list>
<html_block>&lt;!-- --&gt;</html_block>
<code_block>code
</code_block>
</document>")]
public void Parse_List_Separators(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
[Theory]
[InlineData(@"- a
- b
- c
- d
- e
- f
- g", @"<document>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>a</text>
</paragraph>
</item>
<item>
<paragraph>
<text>b</text>
</paragraph>
</item>
<item>
<paragraph>
<text>c</text>
</paragraph>
</item>
<item>
<paragraph>
<text>d</text>
</paragraph>
</item>
<item>
<paragraph>
<text>e</text>
</paragraph>
</item>
<item>
<paragraph>
<text>f</text>
</paragraph>
</item>
<item>
<paragraph>
<text>g</text>
</paragraph>
</item>
</list>
</document>")]
[InlineData(@"1. a
2. b
3. c
", @"<document>
<list type=""ordered"" start=""1"" tight=""false"">
<item>
<paragraph>
<text>a</text>
</paragraph>
</item>
<item>
<paragraph>
<text>b</text>
</paragraph>
</item>
<item>
<paragraph>
<text>c</text>
</paragraph>
</item>
</list>
</document>")]
[InlineData(@"- a
- b
- c
- d
- e", @"<document>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>a</text>
</paragraph>
</item>
<item>
<paragraph>
<text>b</text>
</paragraph>
</item>
<item>
<paragraph>
<text>c</text>
</paragraph>
</item>
<item>
<paragraph>
<text>d</text>
<softbreak />
<text>- e</text>
</paragraph>
</item>
</list>
</document>")]
[InlineData(@"1. a
2. b
3. c", @"<document>
<list type=""ordered"" start=""1"" tight=""false"">
<item>
<paragraph>
<text>a</text>
</paragraph>
</item>
<item>
<paragraph>
<text>b</text>
</paragraph>
</item>
</list>
<code_block>3. c
</code_block>
</document>")]
public void Parse_List_Identation(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
[Fact]
public void Parse_BasicNestedLists()
{
Assert.Equal(@"<document>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>a</text>
</paragraph>
</item>
<item>
<paragraph>
<text>b</text>
</paragraph>
</item>
<item>
<paragraph>
<text>c</text>
</paragraph>
</item>
</list>
</document>", ToXml(@"
- a
- b
- c"));
}
}

View File

@@ -0,0 +1,109 @@
using Xunit;
namespace Radzen.Blazor.Markdown.Tests;
public class ParagraphTests
{
private static string ToXml(string markdown)
{
var document = MarkdownParser.Parse(markdown);
return XmlVisitor.ToXml(document);
}
[Fact]
public void Parse_BasicParagraph()
{
Assert.Equal(@"<document>
<paragraph>
<text>foo</text>
</paragraph>
</document>", ToXml(@"foo"));
}
[Theory]
[InlineData(@"aaa
bbb", @"<document>
<paragraph>
<text>aaa</text>
</paragraph>
<paragraph>
<text>bbb</text>
</paragraph>
</document>")]
[InlineData(@"aaa
bbb
ccc
ddd", @"<document>
<paragraph>
<text>aaa</text>
<softbreak />
<text>bbb</text>
</paragraph>
<paragraph>
<text>ccc</text>
<softbreak />
<text>ddd</text>
</paragraph>
</document>")]
[InlineData(@"aaa
bbb
", @"<document>
<paragraph>
<text>aaa</text>
</paragraph>
<paragraph>
<text>bbb</text>
</paragraph>
</document>")]
[InlineData(@" aaa
bbb", @"<document>
<paragraph>
<text>aaa</text>
<softbreak />
<text>bbb</text>
</paragraph>
</document>")]
[InlineData(@"aaa
bbb
ccc", @"<document>
<paragraph>
<text>aaa</text>
<softbreak />
<text>bbb</text>
<softbreak />
<text>ccc</text>
</paragraph>
</document>")]
[InlineData(@" aaa
bbb", @"<document>
<paragraph>
<text>aaa</text>
<softbreak />
<text>bbb</text>
</paragraph>
</document>")]
[InlineData(@" aaa
bbb", @"<document>
<code_block>aaa
</code_block>
<paragraph>
<text>bbb</text>
</paragraph>
</document>")]
[InlineData(@"aaa
bbb ", @"<document>
<paragraph>
<text>aaa</text>
<linebreak />
<text>bbb</text>
</paragraph>
</document>")]
public void Parse_Paragraph(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
}

View File

@@ -0,0 +1,41 @@
using Xunit;
namespace Radzen.Blazor.Markdown.Tests;
public class SoftLineBreakTests
{
private static string ToXml(string markdown)
{
var document = MarkdownParser.Parse(markdown);
return XmlVisitor.ToXml(document);
}
[Theory]
[InlineData(@"foo
baz", @"<document>
<paragraph>
<text>foo</text>
<softbreak />
<text>baz</text>
</paragraph>
</document>")]
public void Parse_SoftLineBreak(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
[Theory]
[InlineData(@"foo
baz", @"<document>
<paragraph>
<text>foo</text>
<softbreak />
<text>baz</text>
</paragraph>
</document>")]
public void Parse_SoftLine_RemovesSpacesAtEndAndStartOfLine(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
}

View File

@@ -0,0 +1,135 @@
using Xunit;
namespace Radzen.Blazor.Markdown.Tests;
public class StrongTests
{
private static string ToXml(string markdown)
{
var document = MarkdownParser.Parse(markdown);
return XmlVisitor.ToXml(document);
}
[Theory]
[InlineData("**foo bar**",
@"<document>
<paragraph>
<strong>
<text>foo bar</text>
</strong>
</paragraph>
</document>")]
[InlineData("** foo bar**",
@"<document>
<paragraph>
<text>**</text>
<text> foo bar</text>
<text>**</text>
</paragraph>
</document>")]
[InlineData("a**\"foo\"**",
@"<document>
<paragraph>
<text>a</text>
<text>**</text>
<text>""foo""</text>
<text>**</text>
</paragraph>
</document>")]
[InlineData("foo**bar**",
@"<document>
<paragraph>
<text>foo</text>
<strong>
<text>bar</text>
</strong>
</paragraph>
</document>")]
[InlineData("__foo bar__",
@"<document>
<paragraph>
<strong>
<text>foo bar</text>
</strong>
</paragraph>
</document>")]
[InlineData("__ foo bar__",
@"<document>
<paragraph>
<text>__</text>
<text> foo bar</text>
<text>__</text>
</paragraph>
</document>")]
[InlineData("__\nfoo bar__",
@"<document>
<paragraph>
<text>__</text>
<softbreak />
<text>foo bar</text>
<text>__</text>
</paragraph>
</document>")]
[InlineData("a__\"foo\"__",
@"<document>
<paragraph>
<text>a</text>
<text>__</text>
<text>""foo""</text>
<text>__</text>
</paragraph>
</document>")]
[InlineData("foo__bar__",
@"<document>
<paragraph>
<text>foo</text>
<text>__</text>
<text>bar</text>
<text>__</text>
</paragraph>
</document>")]
[InlineData("5__6__78",
@"<document>
<paragraph>
<text>5</text>
<text>__</text>
<text>6</text>
<text>__</text>
<text>78</text>
</paragraph>
</document>")]
[InlineData("пристаням__стремятся__",
@"<document>
<paragraph>
<text>пристаням</text>
<text>__</text>
<text>стремятся</text>
<text>__</text>
</paragraph>
</document>")]
[InlineData("__foo, __bar__, baz__",
@"<document>
<paragraph>
<strong>
<text>foo, </text>
<strong>
<text>bar</text>
</strong>
<text>, baz</text>
</strong>
</paragraph>
</document>")]
[InlineData("foo-__(bar)__",
@"<document>
<paragraph>
<text>foo-</text>
<strong>
<text>(bar)</text>
</strong>
</paragraph>
</document>")]
public void Parse_StrongEmphasisRules_AdheresToCommonMarkSpec(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
}

View File

@@ -0,0 +1,414 @@
using Xunit;
namespace Radzen.Blazor.Markdown.Tests;
public class TableTests
{
private static string ToXml(string markdown)
{
var document = MarkdownParser.Parse(markdown);
return XmlVisitor.ToXml(document);
}
[Fact]
public void Parse_BasicTable()
{
Assert.Equal(
@"<document>
<table>
<header>
<cell>
<text>foo</text>
</cell>
<cell>
<text>bar</text>
</cell>
</header>
<row>
<cell>
<text>baz</text>
</cell>
<cell>
<text>bim</text>
</cell>
</row>
</table>
</document>",
ToXml(@"
foo|bar
--|--
baz|bim"));
}
[Theory]
[InlineData(@"| foo | bar |
| --- | --- |
| baz | bim |", @"<document>
<table>
<header>
<cell>
<text>foo</text>
</cell>
<cell>
<text>bar</text>
</cell>
</header>
<row>
<cell>
<text>baz</text>
</cell>
<cell>
<text>bim</text>
</cell>
</row>
</table>
</document>")]
[InlineData(@"| f\|oo |
| ------ |
| b `\|` az |
| b **\|** im |", @"<document>
<table>
<header>
<cell>
<text>f|oo</text>
</cell>
</header>
<row>
<cell>
<text>b </text>
<code>|</code>
<text> az</text>
</cell>
</row>
<row>
<cell>
<text>b </text>
<strong>
<text>|</text>
</strong>
<text> im</text>
</cell>
</row>
</table>
</document>")]
[InlineData(@"| abc | defghi |
:-: | -----------:
bar | baz", @"<document>
<table>
<header>
<cell align=""center"">
<text>abc</text>
</cell>
<cell align=""right"">
<text>defghi</text>
</cell>
</header>
<row>
<cell align=""center"">
<text>bar</text>
</cell>
<cell align=""right"">
<text>baz</text>
</cell>
</row>
</table>
</document>")]
[InlineData(@"| abc | def |
| --- | --- |
bar", @"<document>
<table>
<header>
<cell>
<text>abc</text>
</cell>
<cell>
<text>def</text>
</cell>
</header>
<row>
<cell>
<text>bar</text>
</cell>
<cell />
</row>
</table>
</document>")]
[InlineData(@"| abc | def |
| --- | --- |
c:\\foo", @"<document>
<table>
<header>
<cell>
<text>abc</text>
</cell>
<cell>
<text>def</text>
</cell>
</header>
<row>
<cell>
<text>c:</text>
<text>\</text>
<text>foo</text>
</cell>
<cell />
</row>
</table>
</document>")]
public void Parse_Table(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
[Theory]
[InlineData(@"| abc | def |
| --- | --- |
| bar | baz |
boo", @"<document>
<table>
<header>
<cell>
<text>abc</text>
</cell>
<cell>
<text>def</text>
</cell>
</header>
<row>
<cell>
<text>bar</text>
</cell>
<cell>
<text>baz</text>
</cell>
</row>
</table>
<paragraph>
<text>boo</text>
</paragraph>
</document>")]
[InlineData(@"| foo |
| --- |
# bar", @"<document>
<table>
<header>
<cell>
<text>foo</text>
</cell>
</header>
</table>
<heading level=""1"">
<text>bar</text>
</heading>
</document>")]
[InlineData(@"| foo |
| --- |
- bar", @"<document>
<table>
<header>
<cell>
<text>foo</text>
</cell>
</header>
</table>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>bar</text>
</paragraph>
</item>
</list>
</document>")]
[InlineData(@"| foo |
| --- |
1. bar", @"<document>
<table>
<header>
<cell>
<text>foo</text>
</cell>
</header>
</table>
<list type=""ordered"" start=""1"" tight=""true"">
<item>
<paragraph>
<text>bar</text>
</paragraph>
</item>
</list>
</document>")]
[InlineData(@"| abc | def |
| --- | --- |
| bar | baz |
> bar", @"<document>
<table>
<header>
<cell>
<text>abc</text>
</cell>
<cell>
<text>def</text>
</cell>
</header>
<row>
<cell>
<text>bar</text>
</cell>
<cell>
<text>baz</text>
</cell>
</row>
</table>
<block_quote>
<paragraph>
<text>bar</text>
</paragraph>
</block_quote>
</document>")]
[InlineData(@"| abc | def |
| --- | --- |
| bar | baz |
bar", @"<document>
<table>
<header>
<cell>
<text>abc</text>
</cell>
<cell>
<text>def</text>
</cell>
</header>
<row>
<cell>
<text>bar</text>
</cell>
<cell>
<text>baz</text>
</cell>
</row>
</table>
<code_block>bar
</code_block>
</document>")]
[InlineData(@"| abc | def |
| --- | --- |
| bar | baz |
```
bar
```", @"<document>
<table>
<header>
<cell>
<text>abc</text>
</cell>
<cell>
<text>def</text>
</cell>
</header>
<row>
<cell>
<text>bar</text>
</cell>
<cell>
<text>baz</text>
</cell>
</row>
</table>
<code_block>bar
</code_block>
</document>")]
[InlineData(@"| abc | def |
| --- | --- |
| bar | baz |
<div>
</div>", @"<document>
<table>
<header>
<cell>
<text>abc</text>
</cell>
<cell>
<text>def</text>
</cell>
</header>
<row>
<cell>
<text>bar</text>
</cell>
<cell>
<text>baz</text>
</cell>
</row>
</table>
<html_block>&lt;div&gt;
&lt;/div&gt;</html_block>
</document>")]
[InlineData(@"| abc | def |
| --- | --- |
| bar | baz |
---", @"<document>
<table>
<header>
<cell>
<text>abc</text>
</cell>
<cell>
<text>def</text>
</cell>
</header>
<row>
<cell>
<text>bar</text>
</cell>
<cell>
<text>baz</text>
</cell>
</row>
</table>
<thematic_break />
</document>")]
public void Parse_Table_AnyBlockOrEmptyLineBreaksTable(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
[Theory]
[InlineData(@"| abc | def |
| --- |", @"<document>
<paragraph>
<text>| abc | def |</text>
<softbreak />
<text>| --- |</text>
</paragraph>
</document>")]
public void Parse_Table_ChecksHeaderAndDelimiter(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
[Theory]
[InlineData(@"| abc |
| --- |
| bar | baz |", @"<document>
<table>
<header>
<cell>
<text>abc</text>
</cell>
</header>
<row>
<cell>
<text>bar</text>
</cell>
</row>
</table>
</document>")]
public void Parse_Table_IgnoresExtraCells(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
}

View File

@@ -0,0 +1,162 @@
using Xunit;
namespace Radzen.Blazor.Markdown.Tests;
public class ThematicBreakTests
{
private static string ToXml(string markdown)
{
var document = MarkdownParser.Parse(markdown);
return XmlVisitor.ToXml(document);
}
[Theory]
[InlineData(@"***
---
___", @"<document>
<thematic_break />
<thematic_break />
<thematic_break />
</document>")]
[InlineData(@"--
**
__", @"<document>
<paragraph>
<text>--</text>
<softbreak />
<text>**</text>
<softbreak />
<text>__</text>
</paragraph>
</document>")]
[InlineData(@" ***
***
***", @"<document>
<thematic_break />
<thematic_break />
<thematic_break />
</document>")]
[InlineData(@" ***", @"<document>
<code_block>***
</code_block>
</document>")]
[InlineData(@"Foo
***", @"<document>
<paragraph>
<text>Foo</text>
<softbreak />
<text>***</text>
</paragraph>
</document>")]
[InlineData(@"_____________________________________", @"<document>
<thematic_break />
</document>")]
[InlineData(@"- - -", @"<document>
<thematic_break />
</document>")]
[InlineData(@" ** * ** * ** * **", @"<document>
<thematic_break />
</document>")]
[InlineData(@"- - - -", @"<document>
<thematic_break />
</document>")]
[InlineData(@"- - - - ", @"<document>
<thematic_break />
</document>")]
[InlineData(@"_ _ _ _ a
a------
---a---", @"<document>
<paragraph>
<text>_</text>
<text> </text>
<text>_</text>
<text> </text>
<text>_</text>
<text> </text>
<text>_</text>
<text> a</text>
</paragraph>
<paragraph>
<text>a------</text>
</paragraph>
<paragraph>
<text>---a---</text>
</paragraph>
</document>")]
[InlineData(@" *-*", @"<document>
<paragraph>
<emph>
<text>-</text>
</emph>
</paragraph>
</document>")]
[InlineData(@"- foo
***
- bar", @"<document>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>foo</text>
</paragraph>
</item>
</list>
<thematic_break />
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>bar</text>
</paragraph>
</item>
</list>
</document>")]
[InlineData(@"Foo
***
bar", @"<document>
<paragraph>
<text>Foo</text>
</paragraph>
<thematic_break />
<paragraph>
<text>bar</text>
</paragraph>
</document>")]
[InlineData(@"* Foo
* * *
* Bar", @"<document>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>Foo</text>
</paragraph>
</item>
</list>
<thematic_break />
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>Bar</text>
</paragraph>
</item>
</list>
</document>")]
[InlineData(@"- Foo
- * * *", @"<document>
<list type=""bullet"" tight=""true"">
<item>
<paragraph>
<text>Foo</text>
</paragraph>
</item>
<item>
<thematic_break />
</item>
</list>
</document>")]
public void Parse_ThematicBreak(string markdown, string expected)
{
Assert.Equal(expected, ToXml(markdown));
}
}

View File

@@ -0,0 +1,210 @@
using System;
using System.Text;
using System.Xml;
namespace Radzen.Blazor.Markdown.Tests;
public class XmlVisitor : NodeVisitorBase, IDisposable
{
private readonly XmlWriter writer;
private XmlVisitor(StringBuilder xml)
{
writer = XmlWriter.Create(xml, new XmlWriterSettings { OmitXmlDeclaration = true, Indent = true, IndentChars = " ", });
}
public void Dispose()
{
writer.Dispose();
}
public void Close()
{
writer.Close();
}
public static string ToXml(Document document)
{
var xml = new StringBuilder();
using var visitor = new XmlVisitor(xml);
document.Accept(visitor);
visitor.Close();
return xml.ToString()!;
}
public override void VisitBlockQuote(BlockQuote blockQuote)
{
writer.WriteStartElement("block_quote");
base.VisitBlockQuote(blockQuote);
writer.WriteEndElement();
}
public override void VisitDocument(Document document)
{
writer.WriteStartDocument();
writer.WriteStartElement("document");
base.VisitDocument(document);
writer.WriteEndElement();
writer.WriteEndDocument();
}
public override void VisitHeading(Heading heading)
{
writer.WriteStartElement($"heading");
writer.WriteAttributeString("level", heading.Level.ToString());
base.VisitHeading(heading);
writer.WriteEndElement();
}
public override void VisitListItem(ListItem listItem)
{
writer.WriteStartElement("item");
base.VisitListItem(listItem);
writer.WriteEndElement();
}
public override void VisitParagraph(Paragraph paragraph)
{
writer.WriteStartElement("paragraph");
base.VisitParagraph(paragraph);
writer.WriteEndElement();
}
public override void VisitUnorderedList(UnorderedList unorderedList)
{
writer.WriteStartElement("list");
writer.WriteAttributeString("type", "bullet");
writer.WriteAttributeString("tight", unorderedList.Tight.ToString().ToLowerInvariant());
base.VisitUnorderedList(unorderedList);
writer.WriteEndElement();
}
public override void VisitText(Text text)
{
writer.WriteElementString("text", text.Value);
}
public override void VisitOrderedList(OrderedList orderedList)
{
writer.WriteStartElement("list");
writer.WriteAttributeString("type", "ordered");
writer.WriteAttributeString("start", orderedList.Start.ToString());
writer.WriteAttributeString("tight", orderedList.Tight.ToString().ToLowerInvariant());
base.VisitOrderedList(orderedList);
writer.WriteEndElement();
}
public override void VisitLink(Link link)
{
writer.WriteStartElement("link");
writer.WriteAttributeString("destination", link.Destination);
writer.WriteAttributeString("title", link.Title);
base.VisitLink(link);
writer.WriteEndElement();
}
public override void VisitImage(Image image)
{
writer.WriteStartElement("image");
writer.WriteAttributeString("destination", image.Destination);
writer.WriteAttributeString("title", image.Title);
base.VisitImage(image);
writer.WriteEndElement();
}
public override void VisitEmphasis(Emphasis emphasis)
{
writer.WriteStartElement("emph");
base.VisitEmphasis(emphasis);
writer.WriteEndElement();
}
public override void VisitStrong(Strong strong)
{
writer.WriteStartElement("strong");
base.VisitStrong(strong);
writer.WriteEndElement();
}
public override void VisitCode(Code code)
{
writer.WriteElementString("code", code.Value);
}
public override void VisitHtmlInline(HtmlInline html)
{
writer.WriteElementString("html_inline", html.Value);
}
public override void VisitLineBreak(LineBreak lineBreak)
{
writer.WriteElementString("linebreak", string.Empty);
}
public override void VisitSoftLineBreak(SoftLineBreak softLineBreak)
{
writer.WriteElementString("softbreak", string.Empty);
}
public override void VisitThematicBreak(ThematicBreak thematicBreak)
{
writer.WriteElementString("thematic_break", string.Empty);
}
public override void VisitIndentedCodeBlock(IndentedCodeBlock codeBlock)
{
writer.WriteElementString("code_block", codeBlock.Value);
}
public override void VisitFencedCodeBlock(FencedCodeBlock fencedCodeBlock)
{
writer.WriteStartElement("code_block");
if (!string.IsNullOrEmpty(fencedCodeBlock.Info))
{
writer.WriteAttributeString("info", fencedCodeBlock.Info);
}
writer.WriteString(fencedCodeBlock.Value);
writer.WriteEndElement();
}
public override void VisitHtmlBlock(HtmlBlock htmlBlock)
{
writer.WriteElementString("html_block", htmlBlock.Value);
}
public override void VisitTable(Table table)
{
writer.WriteStartElement("table");
base.VisitTable(table);
writer.WriteEndElement();
}
public override void VisitTableHeaderRow(TableHeaderRow header)
{
writer.WriteStartElement("header");
base.VisitTableHeaderRow(header);
writer.WriteEndElement();
}
public override void VisitTableRow(TableRow row)
{
writer.WriteStartElement("row");
base.VisitTableRow(row);
writer.WriteEndElement();
}
public override void VisitTableCell(TableCell cell)
{
writer.WriteStartElement("cell");
if (cell.Alignment != TableCellAlignment.None)
{
writer.WriteAttributeString("align", cell.Alignment.ToString().ToLowerInvariant());
}
base.VisitTableCell(cell);
writer.WriteEndElement();
}
}

View File

@@ -119,13 +119,26 @@ namespace Radzen.Blazor.Tests
var component = ctx.RenderComponent<RadzenMask>();
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, false));
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", false));
Assert.Contains(@$"autocomplete=""off""", component.Markup);
Assert.Contains(@$"aria-autocomplete=""none""", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
Assert.Contains(@$"autocomplete=""on""", component.Markup);
Assert.DoesNotContain(@$"aria-autocomplete", component.Markup);
component.SetParametersAndRender(parameters => parameters.AddUnmatched("autocomplete", "custom"));
Assert.Contains(@$"autocomplete=""custom""", component.Markup);
Assert.DoesNotContain(@$"aria-autocomplete", component.Markup);
component.Instance.DefaultAutoCompleteAttribute = "autocomplete-custom";
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", false));
Assert.Contains(@$"autocomplete=""autocomplete-custom""", component.Markup);
Assert.Contains(@$"aria-autocomplete=""none""", component.Markup);
}
[Fact]
@@ -135,22 +148,22 @@ namespace Radzen.Blazor.Tests
var component = ctx.RenderComponent<RadzenMask>();
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, false));
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", false));
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.On));
Assert.Contains(@$"autocomplete=""off""", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.Off));
Assert.Contains(@$"autocomplete=""off""", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.AdditionalName));
Assert.Contains(@$"autocomplete=""{AutoCompleteType.AdditionalName.GetAutoCompleteValue()}""", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.Email));
Assert.Contains(@$"autocomplete=""{AutoCompleteType.Email.GetAutoCompleteValue()}""", component.Markup);

View File

@@ -0,0 +1,65 @@
using Bunit;
using Microsoft.AspNetCore.Components;
using Xunit;
namespace Radzen.Blazor.Tests
{
public class MediaQueryTests
{
[Fact]
public void MediaQuery_Renders()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenMediaQuery>(parameters =>
{
parameters.Add(p => p.Query, "(max-width: 768px)");
});
Assert.NotNull(component.Instance);
}
[Fact]
public void MediaQuery_HasQueryParameter()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var query = "(max-width: 1024px)";
var component = ctx.RenderComponent<RadzenMediaQuery>(parameters =>
{
parameters.Add(p => p.Query, query);
});
Assert.Equal(query, component.Instance.Query);
}
[Fact]
public void MediaQuery_InvokesChangeCallback()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
bool changeInvoked = false;
bool matchResult = false;
var component = ctx.RenderComponent<RadzenMediaQuery>(parameters =>
{
parameters.Add(p => p.Query, "(max-width: 768px)");
parameters.Add(p => p.Change, EventCallback.Factory.Create<bool>(this, (matches) =>
{
changeInvoked = true;
matchResult = matches;
}));
});
// Invoke the JSInvokable method directly
component.Instance.OnChange(true);
Assert.True(changeInvoked);
Assert.True(matchResult);
}
}
}

View File

@@ -0,0 +1,58 @@
using Bunit;
using Xunit;
namespace Radzen.Blazor.Tests
{
public class MenuTests
{
[Fact]
public void Menu_Renders_WithClassName()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenMenu>();
Assert.Contains(@"rz-menu", component.Markup);
}
[Fact]
public void Menu_Renders_Responsive_True()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenMenu>(parameters =>
{
parameters.Add(p => p.Responsive, true);
});
Assert.Contains("rz-menu-closed", component.Markup);
Assert.Contains("rz-menu-toggle", component.Markup);
}
[Fact]
public void Menu_Renders_Responsive_False()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenMenu>(parameters =>
{
parameters.Add(p => p.Responsive, false);
});
Assert.DoesNotContain("rz-menu-toggle", component.Markup);
Assert.DoesNotContain("rz-menu-closed", component.Markup);
}
[Fact]
public void Menu_Renders_CustomToggleAriaLabel()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenMenu>(parameters =>
{
parameters.Add(p => p.Responsive, true);
parameters.Add(p => p.ToggleAriaLabel, "Open navigation");
});
Assert.Contains("Open navigation", component.Markup);
}
}
}

View File

@@ -0,0 +1,214 @@
using System;
using System.Linq;
using Xunit;
namespace Radzen.Blazor.Tests
{
public class NotificationServiceTests
{
[Fact]
public void NotificationService_IsMessageIsNull_ExceptionExpected()
{
NotificationService notificationService = new NotificationService();
NotificationMessage notificationMessage = null;
var exception = Record.Exception(() => notificationService.Notify(notificationMessage));
Assert.IsType<ArgumentNullException>(exception);
}
[Fact]
public void NotificationService_CheckAreTwoMessages_Equals()
{
var messageOne = new NotificationMessage()
{
Severity = NotificationSeverity.Info,
Summary = "Info Summary",
Detail = "Info Detail",
Duration = 4000
};
var messageTwo = new NotificationMessage()
{
Severity = NotificationSeverity.Info,
Summary = "Info Summary",
Detail = "Info Detail",
Duration = 4000
};
Assert.True(messageOne.Equals(messageTwo));
}
[Fact]
public void NotificationService_CheckAreTwoMessages_NotEquals()
{
var messageOne = new NotificationMessage()
{
Severity = NotificationSeverity.Info,
Summary = "Info Summary",
Detail = "Info Detail",
Duration = 4000
};
var messageTwo = new NotificationMessage()
{
Severity = NotificationSeverity.Info,
Summary = "Info Summary Two",
Detail = "Info Detail Two",
Duration = 6000
};
Assert.False(messageOne.Equals(messageTwo));
}
[Fact]
public void NotificationService_CheckAreTwoMessages_EqualsByReference()
{
var messageOne = new NotificationMessage()
{
Severity = NotificationSeverity.Info,
Summary = "Info Summary",
Detail = "Info Detail",
Duration = 4000
};
var messageTwo = messageOne;
Assert.True(messageOne.Equals(messageTwo));
}
[Fact]
public void NotificationService_CheckAreTwoMessages_EqualsByOperator()
{
var messageOne = new NotificationMessage()
{
Severity = NotificationSeverity.Info,
Summary = "Info Summary",
Detail = "Info Detail",
Duration = 4000
};
var messageTwo = new NotificationMessage()
{
Severity = NotificationSeverity.Info,
Summary = "Info Summary",
Detail = "Info Detail",
Duration = 4000
};
Assert.True(messageOne == messageTwo);
}
[Fact]
public void NotificationService_CheckAreTwoMessages_NotEqualsByOperator()
{
var messageOne = new NotificationMessage()
{
Severity = NotificationSeverity.Info,
Summary = "Info Summary",
Detail = "Info Detail",
Duration = 4000
};
var messageTwo = new NotificationMessage()
{
Severity = NotificationSeverity.Info,
Summary = "Info Summary Two",
Detail = "Info Detail Two",
Duration = 6000
};
Assert.True(messageOne != messageTwo);
}
[Fact]
public void NotificationService_CheckAreTwoMessages_EqualsByHashCode()
{
var messageOne = new NotificationMessage()
{
Severity = NotificationSeverity.Info,
Summary = "Info Summary",
Detail = "Info Detail",
Duration = 4000
};
var messageTwo = new NotificationMessage()
{
Severity = NotificationSeverity.Info,
Summary = "Info Summary",
Detail = "Info Detail",
Duration = 4000
};
var messageOneHashCode = messageOne.GetHashCode();
var messageTwoHashCode = messageTwo.GetHashCode();
Assert.Equal(messageOneHashCode, messageTwoHashCode);
}
[Fact]
public void NotificationService_CheckAreTwoMessages_NotEqualsByHashCode()
{
var messageOne = new NotificationMessage()
{
Severity = NotificationSeverity.Info,
Summary = "Info Summary",
Detail = "Info Detail",
Duration = 4000
};
var messageTwo = new NotificationMessage()
{
Severity = NotificationSeverity.Info,
Summary = "Info Summary Two",
Detail = "Info Detail Tow",
Duration = 5000
};
var messageOneHashCode = messageOne.GetHashCode();
var messageTwoHashCode = messageTwo.GetHashCode();
Assert.NotEqual(messageOneHashCode, messageTwoHashCode);
}
[Fact]
public void NotificationService_MessagesCount_AfterAddingMessages()
{
NotificationService notificationService = new NotificationService();
//Messages are the same so only one should be added
notificationService.Notify(NotificationSeverity.Info, "Info Summary", "Info Detail", 4000);
notificationService.Notify(new NotificationMessage()
{
Severity = NotificationSeverity.Info,
Summary = "Info Summary",
Detail = "Info Detail",
Duration = 4000
});
int expectedMessagesNumber = 1;
Assert.Equal(expectedMessagesNumber, notificationService.Messages.Count);
}
[Fact]
public void NotificationService_MessagesCount_AfterAddingTwoDifferentMessages()
{
NotificationService notificationService = new NotificationService();
//Messages are the same so only one should be added
notificationService.Notify(NotificationSeverity.Info, "Info Summary 2", "Info Detail 2", 6000);
notificationService.Notify(new NotificationMessage()
{
Severity = NotificationSeverity.Info,
Summary = "Info Summary",
Detail = "Info Detail",
Duration = 4000
});
int expectedMessagesNumber = 2;
Assert.Equal(expectedMessagesNumber, notificationService.Messages.Count);
}
}
}

View File

@@ -1,4 +1,5 @@
using System;
using System.Threading.Tasks;
using Bunit;
using Microsoft.AspNetCore.Components.Forms;
using Xunit;
@@ -15,13 +16,22 @@ namespace Radzen.Blazor.Tests
public string Name { get; set; }
public FieldIdentifier FieldIdentifier => throw new System.NotImplementedException();
public FieldIdentifier FieldIdentifier { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public object GetValue()
{
return Value;
}
public ValueTask FocusAsync()
{
throw new NotImplementedException();
}
public bool Disabled { get; set; }
public bool Visible { get; set; }
public IFormFieldContext FormFieldContext => null;
public object Value { get; set; }
}
@@ -54,6 +64,19 @@ namespace Radzen.Blazor.Tests
Assert.False(component.Instance.Validate(null));
}
[Fact]
public void Returns_True_If_Value_Is_Null_And_AllowNull_Is_True()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenNumericRangeValidatorTestDouble>();
component.SetParametersAndRender(parameters =>
{
component.SetParametersAndRender(parameters => parameters.Add(p => p.Min, 0).Add(p => p.Max, 10).Add(p => p.AllowNull, true));
});
Assert.True(component.Instance.Validate(null));
}
[Fact]
public void Returns_False_If_Value_Overflows()
@@ -150,4 +173,4 @@ namespace Radzen.Blazor.Tests
Assert.False(component.Instance.Validate(DateTime.Now));
}
}
}
}

View File

@@ -1,4 +1,6 @@
using System;
using Bunit;
using Newtonsoft.Json.Linq;
using Xunit;
namespace Radzen.Blazor.Tests
@@ -14,9 +16,9 @@ namespace Radzen.Blazor.Tests
component.Render();
Assert.Contains(@$"rz-spinner", component.Markup);
Assert.Contains(@$"rz-spinner-up", component.Markup);
Assert.Contains(@$"rz-spinner-down", component.Markup);
Assert.Contains(@$"rz-numeric", component.Markup);
Assert.Contains(@$"rz-numeric-up", component.Markup);
Assert.Contains(@$"rz-numeric-down", component.Markup);
}
[Fact]
@@ -52,11 +54,41 @@ namespace Radzen.Blazor.Tests
parameters.Add<decimal?>(p => p.Min, minValue);
});
component.Find(".rz-spinner-down").Click();
component.Find(".rz-numeric-down").Click();
Assert.False(raised, $"Numeric value should Change event if value is less than min value.");
}
[Fact]
public void Numeric_Respect_Nullable_With_MinParameter()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenNumeric<double?>>();
var raised = false;
var value = 3.5;
object newValue = null;
component.SetParametersAndRender(parameters =>
{
parameters.Add(p => p.Change, args => { raised = true; newValue = args; });
parameters.Add<decimal?>(p => p.Min, 1);
});
component.Find("input").Change(value);
Assert.True(raised);
Assert.True(object.Equals(value, newValue));
component.Find("input").Change("");
Assert.True(raised);
Assert.True(object.Equals(null, newValue));
}
[Fact]
public void Numeric_Respect_MaxParameter()
{
@@ -76,7 +108,7 @@ namespace Radzen.Blazor.Tests
parameters.Add<decimal?>(p => p.Max, maxValue);
});
component.Find(".rz-spinner-up").Click();
component.Find(".rz-numeric-up").Click();
Assert.False(raised, $"Numeric value should Change event if value is less than min value.");
}
@@ -184,13 +216,26 @@ namespace Radzen.Blazor.Tests
var component = ctx.RenderComponent<RadzenNumeric<double>>();
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, false));
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", false));
Assert.Contains(@$"autocomplete=""off""", component.Markup);
Assert.Contains(@$"aria-autocomplete=""none""", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
Assert.Contains(@$"autocomplete=""on""", component.Markup);
Assert.DoesNotContain(@$"aria-autocomplete", component.Markup);
component.SetParametersAndRender(parameters => parameters.AddUnmatched("autocomplete", "custom"));
Assert.Contains(@$"autocomplete=""custom""", component.Markup);
Assert.DoesNotContain(@$"aria-autocomplete", component.Markup);
component.Instance.DefaultAutoCompleteAttribute = "autocomplete-custom";
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", false));
Assert.Contains(@$"autocomplete=""autocomplete-custom""", component.Markup);
Assert.Contains(@$"aria-autocomplete=""none""", component.Markup);
}
[Fact]
@@ -200,22 +245,22 @@ namespace Radzen.Blazor.Tests
var component = ctx.RenderComponent<RadzenNumeric<double>>();
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, false));
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", false));
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.On));
Assert.Contains(@$"autocomplete=""off""", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.Off));
Assert.Contains(@$"autocomplete=""off""", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.BdayMonth));
Assert.Contains(@$"autocomplete=""{AutoCompleteType.BdayMonth.GetAutoCompleteValue()}""", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.BdayYear));
Assert.Contains(@$"autocomplete=""{AutoCompleteType.BdayYear.GetAutoCompleteValue()}""", component.Markup);
@@ -284,7 +329,7 @@ namespace Radzen.Blazor.Tests
parameters.Add(p => p.Change, args => { raised = true; newValue = args; });
});
component.Find(".rz-spinner-up").Click();
component.Find(".rz-numeric-up").Click();
Assert.True(raised, "Numeric Change should be raised on step up");
Assert.True(object.Equals(expectedValue, newValue), $"Numeric value should be incremented on step up. Expected value: {expectedValue}, value: {newValue}");
@@ -293,7 +338,7 @@ namespace Radzen.Blazor.Tests
component.SetParametersAndRender(parameters => parameters.Add(p => p.ValueChanged, args => { raised = true; }));
component.Find(".rz-spinner-up").Click();
component.Find(".rz-numeric-up").Click();
Assert.True(raised, "Numeric ValueChanged should be raised on step up");
}
@@ -319,7 +364,7 @@ namespace Radzen.Blazor.Tests
parameters.Add(p => p.Change, args => { raised = true; newValue = args; });
});
component.Find(".rz-spinner-down").Click();
component.Find(".rz-numeric-down").Click();
Assert.True(raised, "Numeric Change should be raised on step up");
Assert.True(object.Equals(expectedValue, newValue), $"Numeric value should be incremented on step up. Expected value: {expectedValue}, value: {newValue}");
@@ -328,7 +373,7 @@ namespace Radzen.Blazor.Tests
component.SetParametersAndRender(parameters => parameters.Add(p => p.ValueChanged, args => { raised = true; }));
component.Find(".rz-spinner-down").Click();
component.Find(".rz-numeric-down").Click();
Assert.True(raised, "Numeric ValueChanged should be raised on step up");
}
@@ -342,9 +387,9 @@ namespace Radzen.Blazor.Tests
component.Render();
Assert.Contains(@$"rz-spinner-button-icon", component.Markup);
Assert.Contains(@$"rz-spinner-up", component.Markup);
Assert.Contains(@$"rz-spinner-down", component.Markup);
Assert.Contains(@$"rz-numeric-button-icon", component.Markup);
Assert.Contains(@$"rz-numeric-up", component.Markup);
Assert.Contains(@$"rz-numeric-down", component.Markup);
}
[Fact]
@@ -356,9 +401,9 @@ namespace Radzen.Blazor.Tests
component.Render();
Assert.DoesNotContain(@$"rz-spinner-button-icon", component.Markup);
Assert.DoesNotContain(@$"rz-spinner-up", component.Markup);
Assert.DoesNotContain(@$"rz-spinner-down", component.Markup);
Assert.DoesNotContain(@$"rz-numeric-button-icon", component.Markup);
Assert.DoesNotContain(@$"rz-numeric-up", component.Markup);
Assert.DoesNotContain(@$"rz-numeric-down", component.Markup);
}
[Fact]
@@ -378,5 +423,219 @@ namespace Radzen.Blazor.Tests
Assert.Contains($" value=\"{valueToTest.ToString(format)}\"", component.Markup);
}
public static TheoryData<decimal, decimal> NumericFormatterPreservesLeadingZerosData =>
new()
{
{ 10.000m, 100.000m },
{ 100.000m, 10.000m }
};
[Theory]
[MemberData(nameof(NumericFormatterPreservesLeadingZerosData))]
public void Numeric_Formatter_PreservesLeadingZeros(decimal oldValue, decimal newValue)
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
string format = "0.000";
var component = ctx.RenderComponent<RadzenNumeric<decimal>>(
ComponentParameter.CreateParameter(nameof(RadzenNumeric<decimal>.Format), format),
ComponentParameter.CreateParameter(nameof(RadzenNumeric<decimal>.Value), oldValue)
);
component.Render();
Assert.Contains($" value=\"{oldValue.ToString(format)}\"", component.Markup);
component.Find("input").Change(newValue);
Assert.Contains($" value=\"{newValue.ToString(format)}\"", component.Markup);
}
[Fact]
public void Numeric_Uses_ConvertValue()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var value = new Dollars(11m);
Dollars? ConvertFunc(string s) => decimal.TryParse(s, System.Globalization.CultureInfo.InvariantCulture, out var val) ? new Dollars(val) : null;
var component = ctx.RenderComponent<RadzenNumeric<Dollars?>>(
ComponentParameter.CreateParameter(nameof(RadzenNumeric<Dollars?>.ConvertValue), (Func<string, Dollars?>)ConvertFunc),
ComponentParameter.CreateParameter(nameof(RadzenNumeric<Dollars?>.Value), value),
ComponentParameter.CreateParameter(nameof(RadzenNumeric<Dollars>.Culture), System.Globalization.CultureInfo.InvariantCulture)
);
component.Render();
Assert.Contains($" value=\"{value.ToString()}\"", component.Markup);
var newValue = new Dollars(13.53m);
component.Find("input").Change("13.53");
Assert.Contains($" value=\"{newValue.ToString()}\"", component.Markup);
}
[Fact]
public void Numeric_Supports_TypeConverter()
{
using var ctx = new TestContext();
var valueToTest = new Dollars(100.234m);
string format = "0.00";
var component = ctx.RenderComponent<RadzenNumeric<Dollars>>(
ComponentParameter.CreateParameter(nameof(RadzenNumeric<Dollars>.Format), format),
ComponentParameter.CreateParameter(nameof(RadzenNumeric<Dollars>.Value), valueToTest)
);
component.Render();
Assert.Contains($" value=\"{valueToTest.ToString(format, System.Globalization.CultureInfo.CurrentCulture)}\"", component.Markup);
}
[Fact]
public void Numeric_Supports_TypeConverterWithCulture()
{
using var ctx = new TestContext();
var valueToTest = new Dollars(100.234m);
string format = "0.00";
var component = ctx.RenderComponent<RadzenNumeric<Dollars>>(
ComponentParameter.CreateParameter(nameof(RadzenNumeric<Dollars>.Format), format),
ComponentParameter.CreateParameter(nameof(RadzenNumeric<Dollars>.Value), valueToTest),
ComponentParameter.CreateParameter(nameof(RadzenNumeric<Dollars>.Culture), System.Globalization.CultureInfo.InvariantCulture)
);
component.Render();
Assert.Contains($" value=\"{valueToTest.ToString(format, System.Globalization.CultureInfo.InvariantCulture)}\"", component.Markup);
}
[Fact]
public void Numeric_Supports_EmptyString()
{
using var ctx = new TestContext();
var valueToTest = "";
string format = "0.00";
var component = ctx.RenderComponent<RadzenNumeric<string>>(
ComponentParameter.CreateParameter(nameof(RadzenNumeric<string>.Format), format),
ComponentParameter.CreateParameter(nameof(RadzenNumeric<string>.Value), valueToTest),
ComponentParameter.CreateParameter(nameof(RadzenNumeric<Dollars>.Culture), System.Globalization.CultureInfo.InvariantCulture)
);
component.Render();
Assert.Contains($" value=\"0.00\"", component.Markup);
}
[Fact]
public void Numeric_Supports_ValueString()
{
using var ctx = new TestContext();
var valueToTest = "12.50";
string format = "0.00";
var component = ctx.RenderComponent<RadzenNumeric<string>>(
ComponentParameter.CreateParameter(nameof(RadzenNumeric<string>.Format), format),
ComponentParameter.CreateParameter(nameof(RadzenNumeric<string>.Value), valueToTest),
ComponentParameter.CreateParameter(nameof(RadzenNumeric<Dollars>.Culture), System.Globalization.CultureInfo.InvariantCulture)
);
component.Render();
Assert.Contains($" value=\"{valueToTest}\"", component.Markup);
}
[Fact]
public void Numeric_Supports_ValueStringEsCLCulture()
{
using var ctx = new TestContext();
var valueToTest = "12,50";
string format = "0.00";
var component = ctx.RenderComponent<RadzenNumeric<string>>(
ComponentParameter.CreateParameter(nameof(RadzenNumeric<string>.Format), format),
ComponentParameter.CreateParameter(nameof(RadzenNumeric<string>.Value), valueToTest),
ComponentParameter.CreateParameter(nameof(RadzenNumeric<Dollars>.Culture), System.Globalization.CultureInfo.GetCultureInfo("es-CL"))
);
component.Render();
Assert.Contains($" value=\"{valueToTest}\"", component.Markup);
}
[Fact]
public void Numeric_Supports_ValueStringEnUSCulture()
{
using var ctx = new TestContext();
var valueToTest = "12.50";
string format = "0.00";
var component = ctx.RenderComponent<RadzenNumeric<string>>(
ComponentParameter.CreateParameter(nameof(RadzenNumeric<string>.Format), format),
ComponentParameter.CreateParameter(nameof(RadzenNumeric<string>.Value), valueToTest),
ComponentParameter.CreateParameter(nameof(RadzenNumeric<Dollars>.Culture), System.Globalization.CultureInfo.GetCultureInfo("en-US"))
);
component.Render();
Assert.Contains($" value=\"{valueToTest}\"", component.Markup);
}
[Fact]
public void Numeric_Supports_IComparable()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenNumeric<Dollars>>();
var maxValue = 2;
component.SetParametersAndRender(parameters =>
{
component.SetParametersAndRender(parameters =>
{
parameters.Add(p => p.Value, new Dollars(1m));
parameters.Add(p => p.Max, maxValue);
});
});
component.Find("input").Change(13.53);
var maxDollars = new Dollars(maxValue);
Assert.Contains($" value=\"{maxDollars}\"", component.Markup);
Assert.Equal(component.Instance.Value, maxDollars);
}
[Fact]
public void Numeric_Supports_IFormattable()
{
using var ctx = new TestContext();
var valueToTest = new Temperature(60.23m);
const string format = "F";
var component = ctx.RenderComponent<RadzenNumeric<Temperature>>(
ComponentParameter.CreateParameter(nameof(RadzenNumeric<Temperature>.Format), format),
ComponentParameter.CreateParameter(nameof(RadzenNumeric<Temperature>.Value), valueToTest)
);
component.Render();
var input = component.Find("input").GetAttribute("value");
input.MarkupMatches(valueToTest.ToString(format));
}
}
}

View File

@@ -23,14 +23,14 @@ namespace Radzen.Blazor.Tests
component.Render();
Assert.Contains(@$"rz-paginator", component.Markup);
Assert.Contains(@$"rz-pager", component.Markup);
component.SetParametersAndRender(parameters =>
{
parameters.Add<int>(p => p.PageSize, 101);
parameters.Add<int>(p => p.Count, 100);
});
Assert.DoesNotContain(@$"rz-paginator", component.Markup);
Assert.DoesNotContain(@$"rz-pager", component.Markup);
}
[Fact]
@@ -49,7 +49,7 @@ namespace Radzen.Blazor.Tests
component.Render();
Assert.Contains(@$"rz-paginator", component.Markup);
Assert.Contains(@$"rz-pager", component.Markup);
Assert.Contains(@$"rz-dropdown-trigger", component.Markup);
}
@@ -67,13 +67,13 @@ namespace Radzen.Blazor.Tests
await component.Instance.GoToPage(2);
component.Render();
Assert.Contains(@$"rz-paginator-summary", component.Markup);
Assert.Contains(@$"rz-pager-summary", component.Markup);
Assert.Contains(@$"Page 3 of 10 (100 items)", component.Markup);
component.SetParametersAndRender(parameters => {
parameters.Add<bool>(p => p.ShowPagingSummary, false);
});
Assert.DoesNotContain(@$"rz-paginator-summary", component.Markup);
Assert.DoesNotContain(@$"rz-pager-summary", component.Markup);
}
[Fact]
@@ -109,5 +109,51 @@ namespace Radzen.Blazor.Tests
Assert.Contains(@$"rz-density-compact", component.Markup);
}
[Fact]
public async void RadzenPager_First_And_Prev_Buttons_Are_Disabled_When_On_The_First_Page()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenPager>(parameters => {
parameters.Add<int>(p => p.PageSize, 10);
parameters.Add<int>(p => p.Count, 100);
parameters.Add<bool>(p => p.ShowPagingSummary, true);
});
await component.Instance.GoToPage(0);
component.Render();
var firstPageButton = component.Find("a.rz-pager-first");
Assert.True(firstPageButton.HasAttribute("disabled"));
var prevPageButton = component.Find("a.rz-pager-prev");
Assert.True(prevPageButton.HasAttribute("disabled"));
}
[Fact]
public async void RadzenPager_Last_And_Next_Buttons_Are_Disabled_When_On_The_Last_Page()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenPager>(parameters => {
parameters.Add<int>(p => p.PageSize, 10);
parameters.Add<int>(p => p.Count, 100);
parameters.Add<bool>(p => p.ShowPagingSummary, true);
});
await component.Instance.GoToPage(9);
component.Render();
var lastPageButton = component.Find("a.rz-pager-last");
Assert.True(lastPageButton.HasAttribute("disabled"));
var nextPageButton = component.Find("a.rz-pager-next");
Assert.True(nextPageButton.HasAttribute("disabled"));
}
}
}

View File

@@ -1,8 +1,9 @@
using Bunit;
using Bunit.TestDoubles;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Routing;
using Microsoft.Extensions.DependencyInjection.Extensions;
using System.Collections.Generic;
using System.Linq;
using Xunit;
namespace Radzen.Blazor.Tests
@@ -22,6 +23,9 @@ namespace Radzen.Blazor.Tests
}
private static string CreatePanelMenu(string currentAbsoluteUrl, NavLinkMatch match, params string[] urls)
=> CreatePanelMenu(currentAbsoluteUrl, match, new Dictionary<string, bool>(urls.Select(url => new KeyValuePair<string, bool>(url, false))));
private static string CreatePanelMenu(string currentAbsoluteUrl, NavLinkMatch match, Dictionary<string, bool> urls)
{
using var ctx = new TestContext();
@@ -30,12 +34,13 @@ namespace Radzen.Blazor.Tests
var component = ctx.RenderComponent<RadzenPanelMenu>();
component.SetParametersAndRender(parameters => parameters.Add(p => p.Match, match).AddChildContent(builder =>
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.AddAttribute(1, nameof(RadzenPanelMenuItem.Path), url.Key);
builder.AddAttribute(2, nameof(RadzenPanelMenuItem.Disabled), url.Value);
builder.CloseComponent();
}
}));
@@ -55,6 +60,19 @@ namespace Radzen.Blazor.Tests
Assert.Equal(firstIndex, lastIndex);
}
[Fact]
public void RadzenPanelMenu_CanDisableMenuItem()
{
var urls = new Dictionary<string, bool>
{
{"/datagrid", false},
{"/disabled-url", true}
};
var component = CreatePanelMenu("http://www.example.com/", NavLinkMatch.All, urls);
Assert.Contains("rz-state-disabled", component);
}
[Fact]
public void RadzenPanelMenu_MatchesQueryStringParameters()
{

View File

@@ -47,7 +47,7 @@ namespace Radzen.Blazor.Tests
component.SetParametersAndRender(parameters => parameters.Add(p => p.Icon, value));
Assert.Contains(@$"<i class=""rzi"">{value}</i>", component.Markup);
Assert.Contains(@$"<i class=""notranslate rzi"">{value}</i>", component.Markup);
}
[Fact]
@@ -119,11 +119,11 @@ namespace Radzen.Blazor.Tests
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AllowCollapse, true));
Assert.Contains(@"<span class=""rzi rzi-minus""></span>", component.Markup);
Assert.Contains(@"<span class=""notranslate rzi rzi-minus""></span>", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.Collapsed, true));
Assert.Contains(@"<span class=""rzi rzi-plus""></span>", component.Markup);
Assert.Contains(@"<span class=""notranslate rzi rzi-plus""></span>", component.Markup);
}
[Fact]
@@ -198,14 +198,10 @@ namespace Radzen.Blazor.Tests
});
Assert.Contains("SummaryContent", component.Markup);
Assert.Equal(
"display: block",
component.Find(".rz-panel-content-summary").ParentElement.Attributes.First(attr => attr.Name == "style").Value
);
}
[Fact]
public void Panel_DontRenders_SummaryWhenOpen()
public void Panel_DoesNotRender_SummaryWhenOpen()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenPanel>();
@@ -225,8 +221,8 @@ namespace Radzen.Blazor.Tests
Assert.Contains("SummaryContent", component.Markup);
Assert.Equal(
"display: none",
component.Find(".rz-panel-content-summary").ParentElement.Attributes.First(attr => attr.Name == "style").Value
"true",
component.Find(".rz-panel-content-summary").ParentElement.ParentElement.Attributes.First(attr => attr.Name == "aria-hidden").Value
);
}
}

View File

@@ -119,13 +119,17 @@ namespace Radzen.Blazor.Tests
var component = ctx.RenderComponent<RadzenPassword>();
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, false));
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", false));
Assert.Contains(@$"autocomplete=""new-password""", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
Assert.Contains(@$"autocomplete=""on""", component.Markup);
component.SetParametersAndRender(parameters => parameters.AddUnmatched("autocomplete", "custom"));
Assert.Contains(@$"autocomplete=""custom""", component.Markup);
}
[Fact]
@@ -135,22 +139,22 @@ namespace Radzen.Blazor.Tests
var component = ctx.RenderComponent<RadzenPassword>();
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, false));
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", false));
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.On));
Assert.Contains(@$"autocomplete=""new-password""", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.Off));
Assert.Contains(@$"autocomplete=""off""", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.CurrentPassword));
Assert.Contains(@$"autocomplete=""{AutoCompleteType.CurrentPassword.GetAutoCompleteValue()}""", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.NewPassword));
Assert.Contains(@$"autocomplete=""{AutoCompleteType.NewPassword.GetAutoCompleteValue()}""", component.Markup);
@@ -167,24 +171,49 @@ namespace Radzen.Blazor.Tests
Assert.Contains(@$"autofocus", component.Markup);
}
[Fact]
public void Password_Raises_ChangedEvent()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenPassword>();
var raised = false;
var hasRaised = false;
var value = "Test";
object newValue = null;
component.SetParametersAndRender(parameters => parameters.Add(p => p.Change, args => { raised = true; newValue = args; }));
var component = ctx.RenderComponent<RadzenPassword>(parameters =>
{
parameters.Add(p => p.Change, args => { hasRaised = true; newValue = args; });
parameters.Add(p => p.Immediate, false);
});
component.Find("input").Change(value);
var inputElement = component.Find("input");
inputElement.Change(value);
Assert.True(raised);
Assert.True(object.Equals(value, newValue));
Assert.DoesNotContain("oninput", inputElement.ToMarkup());
Assert.True(hasRaised);
Assert.Equal(value, newValue);
}
[Fact]
public void Password_Raises_InputEvent()
{
using var ctx = new TestContext();
var hasRaised = false;
var value = "Test";
object newValue = null;
var component = ctx.RenderComponent<RadzenPassword>(parameters =>
{
parameters.Add(p => p.Change, args => { hasRaised = true; newValue = args; });
parameters.Add(p => p.Immediate, true);
});
var inputElement = component.Find("input");
inputElement.Input(value);
Assert.DoesNotContain("onchange", inputElement.ToMarkup());
Assert.True(hasRaised);
Assert.Equal(value, newValue);
}
[Fact]

View File

@@ -0,0 +1,161 @@
using Bunit;
using Xunit;
using System.Collections.Generic;
namespace Radzen.Blazor.Tests
{
public class PickListTests
{
class Item
{
public int Id { get; set; }
public string Name { get; set; }
}
[Fact]
public void PickList_Renders_WithClassName()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenPickList<Item>>();
Assert.Contains(@"rz-picklist", component.Markup);
}
[Fact]
public void PickList_Renders_SourceAndTargetLists()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenPickList<Item>>();
Assert.Contains("rz-picklist-source-wrapper", component.Markup);
Assert.Contains("rz-picklist-target-wrapper", component.Markup);
}
[Fact]
public void PickList_Renders_TransferButtons()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenPickList<Item>>();
Assert.Contains("rz-picklist-buttons", component.Markup);
}
[Fact]
public void PickList_Renders_Orientation_Horizontal()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenPickList<Item>>(parameters =>
{
parameters.Add(p => p.Orientation, Orientation.Horizontal);
});
Assert.Contains("rz-flex-row", component.Markup);
}
[Fact]
public void PickList_Renders_Orientation_Vertical()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenPickList<Item>>(parameters =>
{
parameters.Add(p => p.Orientation, Orientation.Vertical);
});
Assert.Contains("rz-flex-column", component.Markup);
}
[Fact]
public void PickList_Renders_AllowFiltering()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var data = new List<Item>
{
new Item { Id = 1, Name = "Item 1" }
};
var component = ctx.RenderComponent<RadzenPickList<Item>>(parameters =>
{
parameters.Add(p => p.AllowFiltering, true);
parameters.Add(p => p.Source, data);
parameters.Add(p => p.TextProperty, "Name");
});
Assert.Contains("rz-listbox-filter", component.Markup);
}
[Fact]
public void PickList_Renders_SourceData()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var data = new List<Item>
{
new Item { Id = 1, Name = "Source Item 1" },
new Item { Id = 2, Name = "Source Item 2" }
};
var component = ctx.RenderComponent<RadzenPickList<Item>>(parameters =>
{
parameters.Add(p => p.Source, data);
parameters.Add(p => p.TextProperty, "Name");
});
Assert.Contains("Source Item 1", component.Markup);
Assert.Contains("Source Item 2", component.Markup);
}
[Fact]
public void PickList_Renders_ShowHeader()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenPickList<Item>>(parameters =>
{
parameters.Add(p => p.ShowHeader, true);
parameters.Add(p => p.SourceHeader, builder => builder.AddContent(0, "Available Items"));
parameters.Add(p => p.TargetHeader, builder => builder.AddContent(0, "Selected Items"));
});
Assert.Contains("Available Items", component.Markup);
Assert.Contains("Selected Items", component.Markup);
}
[Fact]
public void PickList_Renders_AllowMoveAll_Buttons()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var data = new List<Item> { new Item { Id = 1, Name = "Item" } };
var component = ctx.RenderComponent<RadzenPickList<Item>>(parameters =>
{
parameters.Add(p => p.AllowMoveAll, true);
parameters.Add(p => p.Source, data);
});
// Should have 4 buttons when AllowMoveAll is true
var buttonCount = System.Text.RegularExpressions.Regex.Matches(component.Markup, "rz-button").Count;
Assert.True(buttonCount >= 4);
}
[Fact]
public void PickList_Renders_Disabled()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenPickList<Item>>(parameters =>
{
parameters.Add(p => p.Disabled, true);
});
Assert.Contains("disabled", component.Markup);
}
}
}

View File

@@ -0,0 +1,644 @@
using Bunit;
using Microsoft.AspNetCore.Components;
using Radzen;
using Radzen.Blazor;
using System;
using System.Collections.Generic;
using System.Linq;
using Xunit;
namespace Radzen.Blazor.Tests
{
public class PivotDataGridTests
{
private static readonly List<SalesData> SampleData = new()
{
new SalesData { Region = "North", Category = "Electronics", Product = "Laptop", Amount = 1000, Year = 2023 },
new SalesData { Region = "North", Category = "Electronics", Product = "Laptop", Amount = 1500, Year = 2024 },
new SalesData { Region = "South", Category = "Home", Product = "Vacuum", Amount = 500, Year = 2023 }
};
public class SalesData
{
public string Region { get; set; }
public string Category { get; set; }
public string Product { get; set; }
public double Amount { get; set; }
public int Year { get; set; }
}
[Fact]
public void PivotDataGrid_Renders_CssClasses()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = RenderPivotDataGrid(ctx);
component.WaitForAssertion(() =>
{
Assert.Contains("rz-pivot-data-grid", component.Markup);
Assert.Contains("rz-pivot-table", component.Markup);
});
}
[Fact]
public void PivotDataGrid_Renders_RowAndColumnHeaders()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = RenderPivotDataGrid(ctx);
component.WaitForAssertion(() =>
{
var table = component.Find(".rz-pivot-content .rz-pivot-table");
var headers = table.GetElementsByClassName("rz-pivot-header-text").Select(h => h.TextContent.Trim()).ToList();
var aggregateHeaders = table.GetElementsByClassName("rz-pivot-aggregate-header").Select(h => h.TextContent.Trim()).ToList();
Assert.Contains("Region", headers);
Assert.Contains("2023", headers);
Assert.Contains("Sales", aggregateHeaders);
});
}
[Fact]
public void PivotDataGrid_AllowSorting_RendersSortableClass()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = RenderPivotDataGrid(ctx, parameters =>
{
parameters.Add(p => p.AllowSorting, true);
});
component.WaitForAssertion(() =>
{
var sortableHeaders = component.FindAll(".rz-pivot-header-content.rz-sortable");
Assert.NotEmpty(sortableHeaders);
});
}
[Fact]
public void PivotDataGrid_AllowFiltering_RendersFilterIcon()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = RenderPivotDataGrid(ctx, parameters =>
{
parameters.Add(p => p.AllowFiltering, true);
});
component.WaitForAssertion(() =>
{
var filterIcons = component.FindAll(".rz-grid-filter-icon");
Assert.NotEmpty(filterIcons);
});
}
[Fact]
public void PivotDataGrid_Renders_AggregateValues()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = RenderPivotDataGrid(ctx);
component.WaitForAssertion(() =>
{
Assert.Contains("1000", component.Markup);
Assert.Contains("1500", component.Markup);
Assert.Contains("500", component.Markup);
});
}
[Fact]
public void PivotDataGrid_DisallowFiltering_HidesFilterIcon()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = RenderPivotDataGrid(ctx, parameters =>
{
parameters.Add(p => p.AllowFiltering, false);
});
component.WaitForAssertion(() =>
{
var filterIcons = component.FindAll(".rz-grid-filter-icon");
Assert.Empty(filterIcons);
});
}
[Fact]
public void PivotDataGrid_DisallowSorting_HidesSortableClass()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = RenderPivotDataGrid(ctx, parameters =>
{
parameters.Add(p => p.AllowSorting, false);
});
component.WaitForAssertion(() =>
{
var sortableHeaders = component.FindAll(".rz-pivot-header-content.rz-sortable");
Assert.Empty(sortableHeaders);
});
}
[Fact]
public void PivotDataGrid_ShowColumnsTotals_RendersFooter()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = RenderPivotDataGrid(ctx, parameters =>
{
parameters.Add(p => p.ShowColumnsTotals, true);
});
component.WaitForAssertion(() =>
{
var footer = component.FindAll(".rz-pivot-footer");
Assert.NotEmpty(footer);
});
}
[Fact]
public void PivotDataGrid_HideColumnsTotals_NoFooter()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = RenderPivotDataGrid(ctx, parameters =>
{
parameters.Add(p => p.ShowColumnsTotals, false);
});
component.WaitForAssertion(() =>
{
var footer = component.FindAll(".rz-pivot-footer");
Assert.Empty(footer);
});
}
[Fact]
public void PivotDataGrid_Renders_DefaultEmptyText()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenPivotDataGrid<SalesData>>(parameters =>
{
parameters.Add(p => p.Data, new List<SalesData>());
parameters.Add(p => p.AllowFieldsPicking, false);
});
component.WaitForAssertion(() =>
{
Assert.Contains("No records to display.", component.Markup);
});
}
[Fact]
public void PivotDataGrid_Renders_CustomEmptyText()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenPivotDataGrid<SalesData>>(parameters =>
{
parameters.Add(p => p.Data, new List<SalesData>());
parameters.Add(p => p.EmptyText, "No data available");
parameters.Add(p => p.AllowFieldsPicking, false);
});
component.WaitForAssertion(() =>
{
Assert.Contains("No data available", component.Markup);
});
}
[Fact]
public void PivotDataGrid_AllowPaging_RendersPager()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = RenderPivotDataGrid(ctx, parameters =>
{
parameters.Add(p => p.AllowPaging, true);
parameters.Add(p => p.PageSize, 2);
});
component.WaitForAssertion(() =>
{
Assert.Contains("rz-pager", component.Markup);
});
}
[Fact]
public void PivotDataGrid_DisallowPaging_HidesPager()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = RenderPivotDataGrid(ctx, parameters =>
{
parameters.Add(p => p.AllowPaging, false);
});
component.WaitForAssertion(() =>
{
Assert.DoesNotContain("rz-pager", component.Markup);
});
}
[Fact]
public void PivotDataGrid_PagerPosition_Top()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = RenderPivotDataGrid(ctx, parameters =>
{
parameters.Add(p => p.AllowPaging, true);
parameters.Add(p => p.PagerPosition, PagerPosition.Top);
parameters.Add(p => p.PageSize, 2);
});
component.WaitForAssertion(() =>
{
Assert.Contains("rz-pager", component.Markup);
});
}
[Fact]
public void PivotDataGrid_PagerPosition_TopAndBottom()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = RenderPivotDataGrid(ctx, parameters =>
{
parameters.Add(p => p.AllowPaging, true);
parameters.Add(p => p.PagerPosition, PagerPosition.TopAndBottom);
parameters.Add(p => p.PageSize, 2);
});
component.WaitForAssertion(() =>
{
var pagers = component.FindAll(".rz-pager");
Assert.True(pagers.Count >= 1); // Should have at least one pager
});
}
[Fact]
public void PivotDataGrid_Density_Compact()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = RenderPivotDataGrid(ctx, parameters =>
{
parameters.Add(p => p.AllowPaging, true);
parameters.Add(p => p.PageSize, 1); // Force pager to show with small page size
parameters.Add(p => p.AllowFieldsPicking, false);
parameters.Add(p => p.Density, Density.Compact);
});
component.WaitForAssertion(() =>
{
Assert.Contains("rz-density-compact", component.Markup);
});
}
[Fact]
public void PivotDataGrid_AllowAlternatingRows_True()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = RenderPivotDataGrid(ctx, parameters =>
{
parameters.Add(p => p.AllowAlternatingRows, true);
});
component.WaitForAssertion(() =>
{
Assert.Contains("rz-grid-table-striped", component.Markup);
});
}
[Fact]
public void PivotDataGrid_AllowAlternatingRows_False()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = RenderPivotDataGrid(ctx, parameters =>
{
parameters.Add(p => p.AllowAlternatingRows, false);
});
component.WaitForAssertion(() =>
{
Assert.DoesNotContain("rz-grid-table-striped", component.Markup);
});
}
[Fact]
public void PivotDataGrid_AllowFieldsPicking_ShowsPanel()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = RenderPivotDataGrid(ctx, parameters =>
{
parameters.Add(p => p.AllowFieldsPicking, true);
});
component.WaitForAssertion(() =>
{
Assert.Contains("rz-panel", component.Markup);
});
}
[Fact]
public void PivotDataGrid_AllowFieldsPicking_False_HidesPanel()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = RenderPivotDataGrid(ctx, parameters =>
{
parameters.Add(p => p.AllowFieldsPicking, false);
});
component.WaitForAssertion(() =>
{
Assert.DoesNotContain("rz-panel", component.Markup);
});
}
[Fact]
public void PivotDataGrid_Renders_AllowDrillDown()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = RenderPivotDataGrid(ctx, parameters =>
{
parameters.Add(p => p.AllowDrillDown, true);
});
component.WaitForAssertion(() =>
{
// Should render pivot content
Assert.Contains("rz-pivot-content", component.Markup);
});
}
[Fact]
public void PivotDataGrid_Renders_RowValues()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = RenderPivotDataGrid(ctx);
component.WaitForAssertion(() =>
{
var cells = component.FindAll(".rz-pivot-row-header");
var cellTexts = cells.Select(c => c.TextContent.Trim()).ToList();
Assert.Contains("North", cellTexts);
Assert.Contains("South", cellTexts);
});
}
[Fact]
public void PivotDataGrid_Renders_MultipleRows()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenPivotDataGrid<SalesData>>(parameters =>
{
parameters.Add(p => p.Data, SampleData);
parameters.Add<RenderFragment>(p => p.Rows, builder =>
{
builder.OpenComponent<RadzenPivotRow<SalesData>>(0);
builder.AddAttribute(1, nameof(RadzenPivotRow<SalesData>.Property), nameof(SalesData.Region));
builder.AddAttribute(2, nameof(RadzenPivotRow<SalesData>.Title), "Region");
builder.CloseComponent();
builder.OpenComponent<RadzenPivotRow<SalesData>>(2);
builder.AddAttribute(3, nameof(RadzenPivotRow<SalesData>.Property), nameof(SalesData.Category));
builder.AddAttribute(4, nameof(RadzenPivotRow<SalesData>.Title), "Category");
builder.CloseComponent();
});
parameters.Add<RenderFragment>(p => p.Columns, builder =>
{
builder.OpenComponent<RadzenPivotColumn<SalesData>>(0);
builder.AddAttribute(1, nameof(RadzenPivotColumn<SalesData>.Property), nameof(SalesData.Year));
builder.AddAttribute(2, nameof(RadzenPivotColumn<SalesData>.Title), "Year");
builder.CloseComponent();
});
parameters.Add<RenderFragment>(p => p.Aggregates, builder =>
{
builder.OpenComponent<RadzenPivotAggregate<SalesData>>(0);
builder.AddAttribute(1, nameof(RadzenPivotAggregate<SalesData>.Property), nameof(SalesData.Amount));
builder.AddAttribute(2, nameof(RadzenPivotAggregate<SalesData>.Title), "Sales");
builder.AddAttribute(3, nameof(RadzenPivotAggregate<SalesData>.Aggregate), AggregateFunction.Sum);
builder.CloseComponent();
});
});
component.WaitForAssertion(() =>
{
var headers = component.FindAll(".rz-pivot-header-text").Select(h => h.TextContent.Trim()).ToList();
Assert.Contains("Region", headers);
Assert.Contains("Category", headers);
});
}
[Fact]
public void PivotDataGrid_Renders_MultipleAggregates()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenPivotDataGrid<SalesData>>(parameters =>
{
parameters.Add(p => p.Data, SampleData);
parameters.Add<RenderFragment>(p => p.Rows, builder =>
{
builder.OpenComponent<RadzenPivotRow<SalesData>>(0);
builder.AddAttribute(1, nameof(RadzenPivotRow<SalesData>.Property), nameof(SalesData.Region));
builder.AddAttribute(2, nameof(RadzenPivotRow<SalesData>.Title), "Region");
builder.CloseComponent();
});
parameters.Add<RenderFragment>(p => p.Columns, builder =>
{
builder.OpenComponent<RadzenPivotColumn<SalesData>>(0);
builder.AddAttribute(1, nameof(RadzenPivotColumn<SalesData>.Property), nameof(SalesData.Year));
builder.AddAttribute(2, nameof(RadzenPivotColumn<SalesData>.Title), "Year");
builder.CloseComponent();
});
parameters.Add<RenderFragment>(p => p.Aggregates, builder =>
{
builder.OpenComponent<RadzenPivotAggregate<SalesData>>(0);
builder.AddAttribute(1, nameof(RadzenPivotAggregate<SalesData>.Property), nameof(SalesData.Amount));
builder.AddAttribute(2, nameof(RadzenPivotAggregate<SalesData>.Title), "Total Sales");
builder.AddAttribute(3, nameof(RadzenPivotAggregate<SalesData>.Aggregate), AggregateFunction.Sum);
builder.CloseComponent();
builder.OpenComponent<RadzenPivotAggregate<SalesData>>(4);
builder.AddAttribute(5, nameof(RadzenPivotAggregate<SalesData>.Property), nameof(SalesData.Amount));
builder.AddAttribute(6, nameof(RadzenPivotAggregate<SalesData>.Title), "Count Sales");
builder.AddAttribute(7, nameof(RadzenPivotAggregate<SalesData>.Aggregate), AggregateFunction.Count);
builder.CloseComponent();
});
});
component.WaitForAssertion(() =>
{
var aggregateHeaders = component.FindAll(".rz-pivot-aggregate-header").Select(h => h.TextContent.Trim()).ToList();
Assert.Contains("Total Sales", aggregateHeaders);
Assert.Contains("Count Sales", aggregateHeaders);
});
}
[Fact]
public void PivotDataGrid_Renders_AlternatingRowClasses()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = RenderPivotDataGrid(ctx, parameters =>
{
parameters.Add(p => p.AllowAlternatingRows, true);
});
component.WaitForAssertion(() =>
{
Assert.Contains("rz-pivot-row-even", component.Markup);
Assert.Contains("rz-pivot-row-odd", component.Markup);
});
}
[Fact]
public void PivotDataGrid_PageSize_DefaultsTo10()
{
var grid = new RadzenPivotDataGrid<SalesData>();
Assert.Equal(10, grid.PageSize);
}
[Fact]
public void PivotDataGrid_AllowSorting_DefaultsToTrue()
{
var grid = new RadzenPivotDataGrid<SalesData>();
Assert.True(grid.AllowSorting);
}
[Fact]
public void PivotDataGrid_AllowFiltering_DefaultsToTrue()
{
var grid = new RadzenPivotDataGrid<SalesData>();
Assert.True(grid.AllowFiltering);
}
[Fact]
public void PivotDataGrid_AllowAlternatingRows_DefaultsToTrue()
{
var grid = new RadzenPivotDataGrid<SalesData>();
Assert.True(grid.AllowAlternatingRows);
}
[Fact]
public void PivotDataGrid_AllowDrillDown_DefaultsToTrue()
{
var grid = new RadzenPivotDataGrid<SalesData>();
Assert.True(grid.AllowDrillDown);
}
[Fact]
public void PivotDataGrid_AllowFieldsPicking_DefaultsToTrue()
{
var grid = new RadzenPivotDataGrid<SalesData>();
Assert.True(grid.AllowFieldsPicking);
}
private static IRenderedComponent<RadzenPivotDataGrid<SalesData>> RenderPivotDataGrid(TestContext ctx, Action<ComponentParameterCollectionBuilder<RadzenPivotDataGrid<SalesData>>>? configure = null)
{
return ctx.RenderComponent<RadzenPivotDataGrid<SalesData>>(parameters =>
{
parameters.Add(p => p.Data, SampleData);
parameters.Add<RenderFragment>(p => p.Rows, builder =>
{
builder.OpenComponent<RadzenPivotRow<SalesData>>(0);
builder.AddAttribute(1, nameof(RadzenPivotRow<SalesData>.Property), nameof(SalesData.Region));
builder.AddAttribute(2, nameof(RadzenPivotRow<SalesData>.Title), "Region");
builder.CloseComponent();
});
parameters.Add<RenderFragment>(p => p.Columns, builder =>
{
builder.OpenComponent<RadzenPivotColumn<SalesData>>(0);
builder.AddAttribute(1, nameof(RadzenPivotColumn<SalesData>.Property), nameof(SalesData.Year));
builder.AddAttribute(2, nameof(RadzenPivotColumn<SalesData>.Title), "Year");
builder.CloseComponent();
});
parameters.Add<RenderFragment>(p => p.Aggregates, builder =>
{
builder.OpenComponent<RadzenPivotAggregate<SalesData>>(0);
builder.AddAttribute(1, nameof(RadzenPivotAggregate<SalesData>.Property), nameof(SalesData.Amount));
builder.AddAttribute(2, nameof(RadzenPivotAggregate<SalesData>.Title), "Sales");
builder.AddAttribute(3, nameof(RadzenPivotAggregate<SalesData>.Aggregate), AggregateFunction.Sum);
builder.CloseComponent();
});
configure?.Invoke(parameters);
});
}
}
}

View File

@@ -0,0 +1,120 @@
using Bunit;
using Microsoft.AspNetCore.Components;
using Xunit;
namespace Radzen.Blazor.Tests
{
public class ProfileMenuItemTests
{
[Fact]
public void ProfileMenuItem_Renders_TextParameter()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenProfileMenu>(parameters =>
{
parameters.Add(p => p.ChildContent, builder =>
{
builder.OpenComponent<RadzenProfileMenuItem>(0);
builder.AddAttribute(1, "Text", "Profile");
builder.CloseComponent();
});
});
Assert.Contains("Profile", component.Markup);
}
[Fact]
public void ProfileMenuItem_Renders_IconParameter()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenProfileMenu>(parameters =>
{
parameters.Add(p => p.ChildContent, builder =>
{
builder.OpenComponent<RadzenProfileMenuItem>(0);
builder.AddAttribute(1, "Icon", "account_circle");
builder.AddAttribute(2, "Text", "Profile");
builder.CloseComponent();
});
});
Assert.Contains("account_circle", component.Markup);
}
[Fact]
public void ProfileMenuItem_Template_OverridesText()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenProfileMenu>(parameters =>
{
parameters.Add(p => p.ChildContent, builder =>
{
builder.OpenComponent<RadzenProfileMenuItem>(0);
builder.AddAttribute(1, "Text", "This should not appear");
builder.AddAttribute(2, "Template", (RenderFragment)((templateBuilder) =>
{
templateBuilder.OpenElement(0, "span");
templateBuilder.AddAttribute(1, "class", "template-content");
templateBuilder.AddContent(2, "Template Content");
templateBuilder.CloseElement();
}));
builder.CloseComponent();
});
});
// Template should be rendered
Assert.Contains("template-content", component.Markup);
// Text should not be rendered in navigation-item-text span when Template is present
Assert.DoesNotContain("<span class=\"rz-navigation-item-text\">This should not appear</span>", component.Markup);
}
[Fact]
public void ProfileMenuItem_Renders_TemplateWithSwitch()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenProfileMenu>(parameters =>
{
parameters.Add(p => p.ChildContent, builder =>
{
builder.OpenComponent<RadzenProfileMenuItem>(0);
builder.AddAttribute(1, "Icon", "settings");
builder.AddAttribute(2, "Template", (RenderFragment)((templateBuilder) =>
{
templateBuilder.OpenComponent<RadzenSwitch>(0);
templateBuilder.CloseComponent();
}));
builder.CloseComponent();
});
});
// Icon should still be rendered
Assert.Contains("settings", component.Markup);
// Switch should be rendered from template
Assert.Contains("rz-switch", component.Markup);
}
[Fact]
public void ProfileMenuItem_Renders_PathParameter()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenProfileMenu>(parameters =>
{
parameters.Add(p => p.ChildContent, builder =>
{
builder.OpenComponent<RadzenProfileMenuItem>(0);
builder.AddAttribute(1, "Text", "Settings");
builder.AddAttribute(2, "Path", "/settings");
builder.CloseComponent();
});
});
Assert.Contains("href=\"/settings\"", component.Markup);
}
}
}

View File

@@ -72,7 +72,7 @@ namespace Radzen.Blazor.Tests
component.SetParametersAndRender(parameters => parameters.Add(p => p.Style, value));
Assert.Contains(@$"style=""{value}""", component.Markup);
Assert.Contains(@$"style=""--rz-progressbar-value: 0%;{value}""", component.Markup);
}
[Fact]
@@ -118,7 +118,7 @@ namespace Radzen.Blazor.Tests
parameters.Add<double>(p => p.Max, max);
});
Assert.Contains(@$"style=""width: {Math.Min(value / max * 100, 100).ToInvariantString()}%;""", component.Markup);
Assert.Contains(@$"style=""--rz-progressbar-value: {Math.Min(value / max * 100, 100).ToInvariantString()}%;""", component.Markup);
}
[Fact]
@@ -129,18 +129,58 @@ namespace Radzen.Blazor.Tests
var component = ctx.RenderComponent<RadzenProgressBar>();
component.SetParametersAndRender(parameters=>parameters.Add(p=>p.ProgressBarStyle, ProgressBarStyle.Success));
Assert.Contains(@$"rz-progressbar-determinate-success", component.Markup);
Assert.Contains(@$"rz-progressbar-success", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add(p => p.ProgressBarStyle, ProgressBarStyle.Info));
Assert.Contains(@$"rz-progressbar-determinate-info", component.Markup);
Assert.Contains(@$"rz-progressbar-info", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add(p => p.ProgressBarStyle, ProgressBarStyle.Success));
component.SetParametersAndRender(parameters => parameters.Add(p => p.Mode, ProgressBarMode.Indeterminate));
Assert.Contains(@$"rz-progressbar-indeterminate-success", component.Markup);
Assert.Contains(@$"rz-progressbar-success", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add(p => p.ProgressBarStyle, ProgressBarStyle.Info));
component.SetParametersAndRender(parameters => parameters.Add(p => p.Mode, ProgressBarMode.Indeterminate));
Assert.Contains(@$"rz-progressbar-indeterminate-info", component.Markup);
Assert.Contains(@$"rz-progressbar-info", component.Markup);
}
[Fact]
public void ProgressBar_Renders_ShowValue_True()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenProgressBar>(parameters =>
{
parameters.Add(p => p.ShowValue, true);
parameters.Add(p => p.Value, 50);
});
Assert.Contains("rz-progressbar-label", component.Markup);
Assert.Contains("50%", component.Markup);
}
[Fact]
public void ProgressBar_Renders_ShowValue_False()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenProgressBar>(parameters =>
{
parameters.Add(p => p.ShowValue, false);
parameters.Add(p => p.Value, 50);
});
Assert.DoesNotContain("rz-progressbar-label", component.Markup);
}
[Fact]
public void ProgressBar_Renders_Template()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenProgressBar>(parameters =>
{
parameters.Add(p => p.Value, 75);
parameters.Add(p => p.Template, builder => builder.AddContent(0, "Custom: 75%"));
});
Assert.Contains("Custom: 75%", component.Markup);
}
}
}

View File

@@ -1,8 +1,5 @@
using AngleSharp.Css;
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using Xunit;
namespace Radzen.Blazor.Tests
@@ -116,5 +113,43 @@ namespace Radzen.Blazor.Tests
{
public List<string> Values { get; set; }
}
[Fact]
public void GetProperty_Should_Resolve_DescriptionProperty()
{
var descriptionProperty = PropertyAccess.GetProperty(typeof(ISimpleInterface), nameof(ISimpleInterface.Description));
Assert.NotNull(descriptionProperty);
}
[Fact]
public void GetProperty_Should_Resolve_NameProperty()
{
var nameProperty = PropertyAccess.GetProperty(typeof(ISimpleInterface), nameof(ISimpleInterface.Name));
Assert.NotNull(nameProperty);
}
[Fact]
public void GetProperty_Should_Resolve_IdProperty()
{
var idProperty = PropertyAccess.GetProperty(typeof(ISimpleInterface), nameof(ISimpleBaseInterface.Id));
Assert.NotNull(idProperty);
}
interface ISimpleInterface : ISimpleNestedInterface
{
string Description { get; set; }
}
interface ISimpleNestedInterface : ISimpleBaseInterface
{
string Name { get; set; }
}
interface ISimpleBaseInterface
{
int Id { get; set; }
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,62 @@
using Bunit;
using System.Collections.Generic;
using Xunit;
namespace Radzen.Blazor.Tests
{
public class RadioButtonListTests
{
[Fact]
public void RadioButtonList_Renders_WithClassName()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenRadioButtonList<int>>();
Assert.Contains(@"rz-radio-button-list", component.Markup);
}
[Fact]
public void RadioButtonList_Renders_Orientation()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenRadioButtonList<int>>(parameters =>
{
parameters.Add(p => p.Items, builder =>
{
builder.OpenComponent<RadzenRadioButtonListItem<int>>(0);
builder.AddAttribute(1, "Text", "Option 1");
builder.AddAttribute(2, "Value", 1);
builder.CloseComponent();
});
});
component.SetParametersAndRender(parameters => parameters.Add(p => p.Orientation, Orientation.Horizontal));
// Orientation is applied via RadzenStack which uses flex-direction
Assert.Contains("rz-flex-row", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add(p => p.Orientation, Orientation.Vertical));
Assert.Contains("rz-flex-column", component.Markup);
}
[Fact]
public void RadioButtonList_Renders_Disabled()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenRadioButtonList<int>>(parameters =>
{
parameters.Add(p => p.Disabled, true);
parameters.Add(p => p.Items, builder =>
{
builder.OpenComponent<RadzenRadioButtonListItem<int>>(0);
builder.AddAttribute(1, "Text", "Option 1");
builder.AddAttribute(2, "Value", 1);
builder.CloseComponent();
});
});
// Disabled class is on the radio button items
Assert.Contains("rz-state-disabled", component.Markup);
}
}
}

View File

@@ -1,14 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
<PackageReference Include="bunit.web" Version="1.2.49" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.0" />
<PackageReference Include="bunit.web" Version="1.36.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>

View File

@@ -0,0 +1,82 @@
using Bunit;
using Xunit;
namespace Radzen.Blazor.Tests
{
public class RatingTests
{
[Fact]
public void Rating_Renders_WithClassName()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenRating>();
Assert.Contains(@"rz-rating", component.Markup);
}
[Fact]
public void Rating_Renders_Stars()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenRating>();
component.SetParametersAndRender(parameters => parameters.Add(p => p.Stars, 5));
// Should render 5 star icons (rzi-star or rzi-star-o) + 1 clear button icon = 6 total
var starCount = System.Text.RegularExpressions.Regex.Matches(component.Markup, "rz-rating-icon").Count;
Assert.Equal(6, starCount); // 5 stars + 1 clear button
}
[Fact]
public void Rating_Renders_CustomStarCount()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenRating>();
component.SetParametersAndRender(parameters => parameters.Add(p => p.Stars, 10));
var starCount = System.Text.RegularExpressions.Regex.Matches(component.Markup, "rz-rating-icon").Count;
Assert.Equal(11, starCount); // 10 stars + 1 clear button
}
[Fact]
public void Rating_Renders_Value()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenRating>();
component.SetParametersAndRender(parameters =>
{
parameters.Add(p => p.Value, 3);
parameters.Add(p => p.Stars, 5);
});
// Should have 3 filled stars (rzi-star) and 2 outline stars (rzi-star-o)
var filledStars = System.Text.RegularExpressions.Regex.Matches(component.Markup, "rzi-star\"").Count;
Assert.Equal(3, filledStars);
}
[Fact]
public void Rating_Renders_ReadOnly()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenRating>();
component.SetParametersAndRender(parameters => parameters.Add(p => p.ReadOnly, true));
Assert.Contains("rz-state-readonly", component.Markup);
}
[Fact]
public void Rating_Renders_Disabled()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenRating>();
component.SetParametersAndRender(parameters => parameters.Add(p => p.Disabled, true));
Assert.Contains("rz-state-disabled", component.Markup);
}
}
}

View File

@@ -0,0 +1,63 @@
using Bunit;
using Xunit;
namespace Radzen.Blazor.Tests
{
public class RowTests
{
[Fact]
public void Row_Renders_WithClassName()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenRow>();
Assert.Contains(@"rz-row", component.Markup);
}
[Fact]
public void Row_Renders_ChildContent()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenRow>(parameters =>
{
parameters.AddChildContent("<div>Row Content</div>");
});
Assert.Contains("Row Content", component.Markup);
}
[Fact]
public void Row_Renders_Gap()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenRow>();
component.SetParametersAndRender(parameters => parameters.Add(p => p.Gap, "2rem"));
Assert.Contains("--rz-gap:2rem", component.Markup);
}
[Fact]
public void Row_Renders_RowGap()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenRow>();
component.SetParametersAndRender(parameters => parameters.Add(p => p.RowGap, "1.5rem"));
Assert.Contains("--rz-row-gap:1.5rem", component.Markup);
}
[Fact]
public void Row_Renders_ColumnGap()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenRow>();
component.SetParametersAndRender(parameters => parameters.Add(p => p.Gap, "1rem"));
Assert.Contains("--rz-gap:1rem", component.Markup);
}
}
}

View File

@@ -0,0 +1,45 @@
using Bunit;
using Xunit;
namespace Radzen.Blazor.Tests
{
public class SecurityCodeTests
{
[Fact]
public void SecurityCode_Renders_WithClassName()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenSecurityCode>();
Assert.Contains(@"rz-security-code", component.Markup);
}
[Fact]
public void SecurityCode_Renders_Count()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenSecurityCode>();
component.SetParametersAndRender(parameters => parameters.Add(p => p.Count, 6));
// Should render 6 input boxes + 1 hidden input for form submission = 7 total
var inputCount = System.Text.RegularExpressions.Regex.Matches(component.Markup, "<input").Count;
Assert.Equal(7, inputCount);
}
[Fact]
public void SecurityCode_Renders_Disabled()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenSecurityCode>();
component.SetParametersAndRender(parameters => parameters.Add(p => p.Disabled, true));
Assert.Contains("disabled", component.Markup);
}
}
}

View File

@@ -0,0 +1,83 @@
using Bunit;
using Xunit;
namespace Radzen.Blazor.Tests
{
public class SelectBarTests
{
[Fact]
public void SelectBar_Renders_WithClassName()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenSelectBar<int>>();
Assert.Contains(@"rz-selectbar", component.Markup);
}
[Fact]
public void SelectBar_Renders_Orientation()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenSelectBar<int>>(parameters =>
{
parameters.Add(p => p.Items, builder =>
{
builder.OpenComponent<RadzenSelectBarItem>(0);
builder.AddAttribute(1, "Text", "Option 1");
builder.AddAttribute(2, "Value", 1);
builder.CloseComponent();
});
});
component.SetParametersAndRender(parameters => parameters.Add(p => p.Orientation, Orientation.Horizontal));
Assert.Contains("rz-selectbar-horizontal", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add(p => p.Orientation, Orientation.Vertical));
Assert.Contains("rz-selectbar-vertical", component.Markup);
}
[Fact]
public void SelectBar_Renders_Multiple()
{
using var ctx = new TestContext();
// When Multiple is true, TValue should be IEnumerable<T>
var component = ctx.RenderComponent<RadzenSelectBar<System.Collections.Generic.IEnumerable<int>>>(parameters =>
{
parameters.Add(p => p.Multiple, true);
parameters.Add(p => p.Items, builder =>
{
builder.OpenComponent<RadzenSelectBarItem>(0);
builder.AddAttribute(1, "Text", "Option 1");
builder.AddAttribute(2, "Value", 1);
builder.CloseComponent();
});
});
Assert.NotNull(component.Instance);
Assert.True(component.Instance.Multiple);
}
[Fact]
public void SelectBar_Renders_Size()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenSelectBar<int>>(parameters =>
{
parameters.Add(p => p.Items, builder =>
{
builder.OpenComponent<RadzenSelectBarItem>(0);
builder.AddAttribute(1, "Text", "Option 1");
builder.AddAttribute(2, "Value", 1);
builder.CloseComponent();
});
});
component.SetParametersAndRender(parameters => parameters.Add(p => p.Size, ButtonSize.Small));
Assert.Contains("rz-button-sm", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add(p => p.Size, ButtonSize.Large));
Assert.Contains("rz-button-lg", component.Markup);
}
}
}

View File

@@ -0,0 +1,65 @@
using Bunit;
using Xunit;
namespace Radzen.Blazor.Tests
{
public class SidebarToggleTests
{
[Fact]
public void SidebarToggle_Renders_WithClassName()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenSidebarToggle>();
Assert.Contains(@"rz-sidebar-toggle", component.Markup);
}
[Fact]
public void SidebarToggle_Renders_DefaultIcon()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenSidebarToggle>();
Assert.Contains("menu", component.Markup);
}
[Fact]
public void SidebarToggle_Renders_CustomIcon()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenSidebarToggle>();
var icon = "close";
component.SetParametersAndRender(parameters => parameters.Add(p => p.Icon, icon));
Assert.Contains(icon, component.Markup);
}
[Fact]
public void SidebarToggle_Renders_AriaLabel()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenSidebarToggle>();
var ariaLabel = "Toggle Navigation";
component.SetParametersAndRender(parameters => parameters.Add(p => p.ToggleAriaLabel, ariaLabel));
Assert.Contains($"aria-label=\"{ariaLabel}\"", component.Markup);
}
[Fact]
public void SidebarToggle_Raises_ClickEvent()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenSidebarToggle>();
var clicked = false;
component.SetParametersAndRender(parameters => parameters.Add(p => p.Click, args => { clicked = true; }));
component.Find("button").Click();
Assert.True(clicked);
}
}
}

View File

@@ -0,0 +1,158 @@
using Bunit;
using Radzen.Blazor.Rendering;
using Xunit;
namespace Radzen.Blazor.Tests
{
public class SkeletonTests
{
[Fact]
public void Skeleton_Renders_CssClass()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenSkeleton>();
Assert.Contains("rz-skeleton", component.Markup);
Assert.Contains("rz-skeleton-text", component.Markup);
}
[Fact]
public void Skeleton_Renders_TypeParameter()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenSkeleton>();
component.SetParametersAndRender(parameters => parameters.Add(p => p.Variant, SkeletonVariant.Circular));
Assert.Contains("rz-skeleton", component.Markup);
Assert.Contains("rz-skeleton-circular", component.Markup);
}
[Theory]
[InlineData(SkeletonVariant.Text, "rz-skeleton-text")]
[InlineData(SkeletonVariant.Circular, "rz-skeleton-circular")]
[InlineData(SkeletonVariant.Rectangular, "rz-skeleton-rectangular")]
public void Skeleton_Renders_AllTypes(SkeletonVariant type, string expectedClass)
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenSkeleton>(parameters => parameters.Add(p => p.Variant, type));
Assert.Contains("rz-skeleton", component.Markup);
Assert.Contains(expectedClass, component.Markup);
}
[Fact]
public void Skeleton_Renders_AnimationParameter()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenSkeleton>();
component.SetParametersAndRender(parameters => parameters.Add(p => p.Animation, SkeletonAnimation.Wave));
Assert.Contains("rz-skeleton", component.Markup);
Assert.Contains("rz-skeleton-wave", component.Markup);
}
[Theory]
[InlineData(SkeletonAnimation.Wave, "rz-skeleton-wave")]
[InlineData(SkeletonAnimation.Pulse, "rz-skeleton-pulse")]
public void Skeleton_Renders_AllAnimations(SkeletonAnimation animation, string expectedClass)
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenSkeleton>(parameters => parameters.Add(p => p.Animation, animation));
Assert.Contains("rz-skeleton", component.Markup);
Assert.Contains(expectedClass, component.Markup);
}
[Fact]
public void Skeleton_Renders_StyleParameter()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenSkeleton>();
var style = "width: 200px; height: 20px;";
component.SetParametersAndRender(parameters => parameters.Add(p => p.Style, style));
Assert.Contains($"style=\"{style}\"", component.Markup);
}
[Fact]
public void Skeleton_Renders_VisibleParameter()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenSkeleton>();
// Should be visible by default
Assert.Contains("rz-skeleton", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add(p => p.Visible, false));
// Should not render when not visible
Assert.DoesNotContain("rz-skeleton", component.Markup);
}
[Fact]
public void Skeleton_Renders_UnmatchedParameter()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenSkeleton>();
component.SetParametersAndRender(parameters => parameters.AddUnmatched("data-testid", "skeleton-test"));
Assert.Contains("data-testid=\"skeleton-test\"", component.Markup);
}
[Fact]
public void Skeleton_DefaultType_IsText()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenSkeleton>();
// Should render with text type by default
Assert.Contains("rz-skeleton-text", component.Markup);
}
[Fact]
public void Skeleton_DefaultAnimation_IsNone()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenSkeleton>();
// Should not render animation classes by default
Assert.DoesNotContain("rz-skeleton-wave", component.Markup);
Assert.DoesNotContain("rz-skeleton-pulse", component.Markup);
}
}
}

View File

@@ -39,7 +39,7 @@ namespace Radzen.Blazor.Tests
component.SetParametersAndRender(parameters => parameters.Add<int>(p => p.Value, value));
Assert.Contains(@$"style=""width: {Math.Round((value / max * 100)).ToInvariantString()}%;""", component.Markup);
Assert.Contains(@$"style=""left: {Math.Round((value / max * 100)).ToInvariantString()}%;""", component.Markup);
Assert.Contains(@$"style=""inset-inline-start: {Math.Round((value / max * 100)).ToInvariantString()}%;""", component.Markup);
}
[Fact]
@@ -55,9 +55,9 @@ namespace Radzen.Blazor.Tests
parameters.Add<IEnumerable<int>>(p => p.Value, new int[] { 4, 30 });
});
Assert.Contains(@$"left: 4%", component.Markup);
Assert.Contains(@$"left: 30%", component.Markup);
Assert.Contains(@$"left: 4%; width: 26%;", component.Markup);
Assert.Contains(@$"inset-inline-start: 4%", component.Markup);
Assert.Contains(@$"inset-inline-start: 30%", component.Markup);
Assert.Contains(@$"inset-inline-start: 4%; width: 26%;", component.Markup);
}
[Fact]
@@ -89,5 +89,71 @@ namespace Radzen.Blazor.Tests
Assert.Contains(@$"autofocus", component.Markup);
}
[Fact]
public void Slider_Renders_Orientation_Vertical()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenSlider<int>>(parameters =>
{
parameters.Add(p => p.Orientation, Orientation.Vertical);
});
Assert.Contains("rz-slider-vertical", component.Markup);
}
[Fact]
public void Slider_Renders_Disabled()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenSlider<int>>(parameters =>
{
parameters.Add(p => p.Disabled, true);
});
Assert.Contains("rz-state-disabled", component.Markup);
}
[Fact]
public void Slider_Renders_SliderHandle()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenSlider<int>>();
Assert.Contains("rz-slider-handle", component.Markup);
}
[Fact]
public void Slider_Renders_SliderRange()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenSlider<int>>();
Assert.Contains("rz-slider-range", component.Markup);
}
[Fact]
public void Slider_Renders_TabIndex()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenSlider<int>>();
Assert.Contains("tabindex=\"0\"", component.Markup);
}
}
}

View File

@@ -1,4 +1,5 @@
using Bunit;
using Microsoft.AspNetCore.Components;
using Xunit;
namespace Radzen.Blazor.Tests
@@ -44,7 +45,7 @@ namespace Radzen.Blazor.Tests
component.SetParametersAndRender(parameters => parameters.Add(p => p.Icon, icon));
Assert.Contains(@$"<i class=""rz-button-icon-left rzi"">{icon}</i>", component.Markup);
Assert.Contains(@$"<i class=""notranslate rz-button-icon-left rzi"">{icon}</i>", component.Markup);
}
[Fact]
@@ -59,10 +60,10 @@ namespace Radzen.Blazor.Tests
component.SetParametersAndRender(parameters => {
parameters.Add(p => p.Text, text);
parameters.Add(p => p.Icon, icon);
parameters.Add(p => p.Icon, icon);
});
Assert.Contains(@$"<i class=""rz-button-icon-left rzi"">{icon}</i>", component.Markup);
Assert.Contains(@$"<i class=""notranslate rz-button-icon-left rzi"">{icon}</i>", component.Markup);
Assert.Contains(@$"<span class=""rz-button-text"">{text}</span>", component.Markup);
}
@@ -77,7 +78,7 @@ namespace Radzen.Blazor.Tests
component.SetParametersAndRender(parameters => parameters.Add(p => p.Image, image));
Assert.Contains(@$"<img class=""rz-button-icon-left rzi"" src=""{image}"" />", component.Markup);
Assert.Contains(@$"<img class=""notranslate rz-button-icon-left rzi"" src=""{image}"" alt=""image"" />", component.Markup);
}
[Fact]
@@ -93,12 +94,29 @@ namespace Radzen.Blazor.Tests
component.SetParametersAndRender(parameters => {
parameters.Add(p => p.Text, text);
parameters.Add(p => p.Image, image);
parameters.Add(p => p.ImageAlternateText, text);
});
Assert.Contains(@$"<img class=""rz-button-icon-left rzi"" src=""{image}"" />", component.Markup);
Assert.Contains(@$"<img class=""notranslate rz-button-icon-left rzi"" src=""{image}"" alt=""{text}"" />", component.Markup);
Assert.Contains(@$"<span class=""rz-button-text"">{text}</span>", component.Markup);
}
[Fact]
public void SplitButton_Renders_ButtonContent()
{
using var ctx = new TestContext();
RenderFragment buttonContent = (builder) => builder.AddMarkupContent(0, "<strong>Custom button content</strong>");
var text = "Test";
var component = ctx.RenderComponent<RadzenSplitButton>(parameters => parameters
.Add(p => p.ButtonContent, buttonContent)
.Add(p => p.Text, text));
Assert.Contains(@$"<strong>Custom button content</strong>", component.Markup);
Assert.DoesNotContain(@$"<span class=""rz-button-text"">{text}</span>", component.Markup);
}
[Fact]
public void SplitButton_Renders_DisabledParameter()
{

View File

@@ -0,0 +1,42 @@
using Bunit;
using Xunit;
namespace Radzen.Blazor.Tests
{
public class SplitterTests
{
[Fact]
public void Splitter_Renders_WithClassName()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenSplitter>();
Assert.Contains(@"rz-splitter", component.Markup);
}
[Fact]
public void Splitter_Renders_Orientation_Horizontal()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenSplitter>(parameters =>
{
parameters.Add(p => p.Orientation, Orientation.Horizontal);
});
Assert.Contains("rz-splitter-horizontal", component.Markup);
}
[Fact]
public void Splitter_Renders_Orientation_Vertical()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenSplitter>(parameters =>
{
parameters.Add(p => p.Orientation, Orientation.Vertical);
});
Assert.Contains("rz-splitter-vertical", component.Markup);
}
}
}

View File

@@ -0,0 +1,98 @@
using Bunit;
using Xunit;
namespace Radzen.Blazor.Tests
{
public class StackTests
{
[Fact]
public void Stack_Renders_WithClassName()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenStack>();
Assert.Contains(@"rz-stack", component.Markup);
}
[Fact]
public void Stack_Renders_ChildContent()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenStack>(parameters =>
{
parameters.AddChildContent("<div>Stack Content</div>");
});
Assert.Contains("Stack Content", component.Markup);
}
[Fact]
public void Stack_Renders_Orientation()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenStack>();
component.SetParametersAndRender(parameters => parameters.Add(p => p.Orientation, Orientation.Horizontal));
Assert.Contains("rz-flex-row", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add(p => p.Orientation, Orientation.Vertical));
Assert.Contains("rz-flex-column", component.Markup);
}
[Fact]
public void Stack_Renders_Gap()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenStack>();
component.SetParametersAndRender(parameters => parameters.Add(p => p.Gap, "1.5rem"));
Assert.Contains("--rz-gap:1.5rem", component.Markup);
}
[Fact]
public void Stack_Renders_AlignItems()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenStack>();
component.SetParametersAndRender(parameters => parameters.Add(p => p.AlignItems, AlignItems.Center));
Assert.Contains("rz-align-items-center", component.Markup);
}
[Fact]
public void Stack_Renders_JustifyContent()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenStack>();
component.SetParametersAndRender(parameters => parameters.Add(p => p.JustifyContent, JustifyContent.SpaceBetween));
Assert.Contains("rz-justify-content-space-between", component.Markup);
}
[Fact]
public void Stack_Renders_Wrap()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenStack>();
component.SetParametersAndRender(parameters => parameters.Add(p => p.Wrap, FlexWrap.Wrap));
Assert.Contains("flex-wrap:wrap", component.Markup);
}
[Fact]
public void Stack_Renders_Reverse()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenStack>();
component.SetParametersAndRender(parameters => parameters.Add(p => p.Reverse, true));
Assert.Contains("rz-flex-column-reverse", component.Markup);
}
}
}

View File

@@ -0,0 +1,70 @@
using Bunit;
using Xunit;
namespace Radzen.Blazor.Tests
{
public class StepsTests
{
[Fact]
public void Steps_Renders_WithClassName()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenSteps>();
Assert.Contains(@"rz-steps", component.Markup);
}
[Fact]
public void Steps_Renders_ShowStepsButtons_True()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenSteps>(parameters =>
{
parameters.Add(p => p.ShowStepsButtons, true);
});
Assert.Contains("rz-steps-buttons", component.Markup);
}
[Fact]
public void Steps_Renders_ShowStepsButtons_False()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenSteps>(parameters =>
{
parameters.Add(p => p.ShowStepsButtons, false);
});
Assert.DoesNotContain("rz-steps-buttons", component.Markup);
}
[Fact]
public void Steps_Renders_StepsButtons()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenSteps>(parameters =>
{
parameters.Add(p => p.ShowStepsButtons, true);
});
Assert.Contains("rz-steps-prev", component.Markup);
Assert.Contains("rz-steps-next", component.Markup);
}
[Fact]
public void Steps_Renders_CustomButtonText()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenSteps>(parameters =>
{
parameters.Add(p => p.ShowStepsButtons, true);
parameters.Add(p => p.NextText, "Continue");
parameters.Add(p => p.PreviousText, "Back");
});
Assert.Contains("Continue", component.Markup);
Assert.Contains("Back", component.Markup);
}
}
}

View File

@@ -41,7 +41,7 @@ namespace Radzen.Blazor.Tests
component.SetParametersAndRender(parameters => parameters.Add(p => p.Style, value));
Assert.Contains(@$"style=""outline: 0 none;{value}""", component.Markup);
Assert.Contains(@$"style=""{value}""", component.Markup);
}
[Fact]
@@ -134,5 +134,18 @@ namespace Radzen.Blazor.Tests
Assert.True(raised);
Assert.True(object.Equals(value, !(bool)newValue));
}
[Fact]
public void Switch_Renders_ReadOnlyParameter()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenSwitch>();
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.ReadOnly, true));
Assert.Contains(@$"rz-readonly", component.Markup);
}
}
}

View File

@@ -0,0 +1,100 @@
using Bunit;
using Xunit;
namespace Radzen.Blazor.Tests
{
public class TableTests
{
[Fact]
public void Table_Renders_WithClassName()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenTable>();
Assert.Contains(@"rz-datatable", component.Markup);
}
[Fact]
public void Table_Renders_TableElement()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenTable>();
Assert.Contains("rz-grid-table", component.Markup);
Assert.Contains("<table", component.Markup);
}
[Fact]
public void Table_Renders_GridLines_None()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenTable>(parameters =>
{
parameters.Add(p => p.GridLines, DataGridGridLines.None);
});
Assert.Contains("rz-grid-gridlines-none", component.Markup);
}
[Fact]
public void Table_Renders_GridLines_Horizontal()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenTable>(parameters =>
{
parameters.Add(p => p.GridLines, DataGridGridLines.Horizontal);
});
Assert.Contains("rz-grid-gridlines-horizontal", component.Markup);
}
[Fact]
public void Table_Renders_GridLines_Vertical()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenTable>(parameters =>
{
parameters.Add(p => p.GridLines, DataGridGridLines.Vertical);
});
Assert.Contains("rz-grid-gridlines-vertical", component.Markup);
}
[Fact]
public void Table_Renders_GridLines_Both()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenTable>(parameters =>
{
parameters.Add(p => p.GridLines, DataGridGridLines.Both);
});
Assert.Contains("rz-grid-gridlines-both", component.Markup);
}
[Fact]
public void Table_Renders_AllowAlternatingRows_True()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenTable>(parameters =>
{
parameters.Add(p => p.AllowAlternatingRows, true);
});
Assert.Contains("rz-grid-table-striped", component.Markup);
}
[Fact]
public void Table_Renders_AllowAlternatingRows_False()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenTable>(parameters =>
{
parameters.Add(p => p.AllowAlternatingRows, false);
});
Assert.DoesNotContain("rz-grid-table-striped", component.Markup);
}
}
}

View File

@@ -0,0 +1,108 @@
using Bunit;
using Xunit;
namespace Radzen.Blazor.Tests
{
public class TabsTests
{
[Fact]
public void Tabs_Renders_WithClassName()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenTabs>();
Assert.Contains(@"rz-tabview", component.Markup);
}
[Fact]
public void Tabs_Renders_TabPosition_Top()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenTabs>(parameters =>
{
parameters.Add(p => p.TabPosition, TabPosition.Top);
});
Assert.Contains("rz-tabview-top", component.Markup);
}
[Fact]
public void Tabs_Renders_TabPosition_Bottom()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenTabs>(parameters =>
{
parameters.Add(p => p.TabPosition, TabPosition.Bottom);
});
Assert.Contains("rz-tabview-bottom", component.Markup);
}
[Fact]
public void Tabs_Renders_TabPosition_Left()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenTabs>(parameters =>
{
parameters.Add(p => p.TabPosition, TabPosition.Left);
});
Assert.Contains("rz-tabview-left", component.Markup);
}
[Fact]
public void Tabs_Renders_TabPosition_Right()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenTabs>(parameters =>
{
parameters.Add(p => p.TabPosition, TabPosition.Right);
});
Assert.Contains("rz-tabview-right", component.Markup);
}
[Fact]
public void Tabs_Renders_TabPosition_TopRight()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenTabs>(parameters =>
{
parameters.Add(p => p.TabPosition, TabPosition.TopRight);
});
Assert.Contains("rz-tabview-top-right", component.Markup);
}
[Fact]
public void Tabs_Renders_TabPosition_BottomRight()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenTabs>(parameters =>
{
parameters.Add(p => p.TabPosition, TabPosition.BottomRight);
});
Assert.Contains("rz-tabview-bottom-right", component.Markup);
}
[Fact]
public void Tabs_Renders_TabNav()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenTabs>();
Assert.Contains("rz-tabview-nav", component.Markup);
}
[Fact]
public void Tabs_Renders_TabPanels()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenTabs>();
Assert.Contains("rz-tabview-panels", component.Markup);
}
}
}

View File

@@ -0,0 +1,35 @@
using System;
using System.Globalization;
namespace Radzen.Blazor.Tests;
public record struct Temperature(decimal DegreesCelsius)
: IFormattable
{
public decimal Celsius => DegreesCelsius;
public decimal Fahrenheit => DegreesCelsius * 9 / 5 + 32;
public decimal Kelvin => DegreesCelsius + 273.15m;
public override string ToString() => ToString("G");
public string ToString(string format) => ToString(format, CultureInfo.CurrentCulture);
public string ToString(string format, IFormatProvider provider)
{
provider ??= CultureInfo.CurrentCulture;
if (string.IsNullOrEmpty(format))
format = "G";
switch (format.ToUpperInvariant())
{
case "G":
case "C":
return $"{Celsius.ToString("F2", provider)} °C";
case "F":
return $"{Fahrenheit.ToString("F2", provider)} °F";
case "K":
return $"{Kelvin.ToString("F2", provider)} K";
default:
throw new FormatException($"The {format} format string is not supported.");
}
}
}

View File

@@ -1,4 +1,6 @@
using Bunit;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
using Xunit;
namespace Radzen.Blazor.Tests
@@ -29,6 +31,26 @@ namespace Radzen.Blazor.Tests
Assert.Contains(@$"value=""{value}""", component.Markup);
}
[Fact]
public void TextboxCanSetFieldIdentifier()
{
using var ctx = new TestContext();
var editContext = new EditContext(ctx);
var fieldIdentifier = new FieldIdentifier(ctx, nameof(RadzenTextBox.Value));
ctx.RenderTree.TryAdd<CascadingValue<EditContext>>(parameters =>
{
parameters.Add(e => e.Value, editContext);
});
var component = ctx.RenderComponent<RadzenTextBox>(parameters =>
{
parameters.Add(p => p.FieldIdentifier, fieldIdentifier);
});
Assert.Equal(component.Instance.FieldIdentifier, fieldIdentifier);
}
[Fact]
public void TextBox_Renders_StyleParameter()
{
@@ -119,13 +141,26 @@ namespace Radzen.Blazor.Tests
var component = ctx.RenderComponent<RadzenTextBox>();
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, false));
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", false));
Assert.Contains(@$"autocomplete=""off""", component.Markup);
Assert.Contains(@$"aria-autocomplete=""none""", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
Assert.Contains(@$"autocomplete=""on""", component.Markup);
Assert.DoesNotContain(@$"aria-autocomplete", component.Markup);
component.SetParametersAndRender(parameters => parameters.AddUnmatched("autocomplete", "custom"));
Assert.Contains(@$"autocomplete=""custom""", component.Markup);
Assert.DoesNotContain(@$"aria-autocomplete", component.Markup);
component.Instance.DefaultAutoCompleteAttribute = "autocomplete-custom";
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", false));
Assert.Contains(@$"autocomplete=""autocomplete-custom""", component.Markup);
Assert.Contains(@$"aria-autocomplete=""none""", component.Markup);
}
[Fact]
@@ -135,22 +170,22 @@ namespace Radzen.Blazor.Tests
var component = ctx.RenderComponent<RadzenTextBox>();
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, false));
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", false));
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.On));
Assert.Contains(@$"autocomplete=""off""", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.Off));
Assert.Contains(@$"autocomplete=""off""", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.AdditionalName));
Assert.Contains(@$"autocomplete=""{AutoCompleteType.AdditionalName.GetAutoCompleteValue()}""", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.FamilyName));
Assert.Contains(@$"autocomplete=""{AutoCompleteType.FamilyName.GetAutoCompleteValue()}""", component.Markup);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,71 @@
using Bunit;
using Xunit;
namespace Radzen.Blazor.Tests
{
public class TimelineTests
{
[Fact]
public void Timeline_Renders_WithClassName()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenTimeline>();
Assert.Contains(@"rz-timeline", component.Markup);
}
[Fact]
public void Timeline_Renders_Orientation()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenTimeline>();
component.SetParametersAndRender(parameters => parameters.Add(p => p.Orientation, Orientation.Horizontal));
Assert.Contains("rz-timeline-row", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add(p => p.Orientation, Orientation.Vertical));
Assert.Contains("rz-timeline-column", component.Markup);
}
[Fact]
public void Timeline_Renders_LinePosition()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenTimeline>();
component.SetParametersAndRender(parameters => parameters.Add(p => p.LinePosition, LinePosition.Start));
Assert.Contains("rz-timeline-start", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add(p => p.LinePosition, LinePosition.End));
Assert.Contains("rz-timeline-end", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add(p => p.LinePosition, LinePosition.Center));
Assert.Contains("rz-timeline-center", component.Markup);
}
[Fact]
public void Timeline_Renders_AlignItems()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenTimeline>();
component.SetParametersAndRender(parameters => parameters.Add(p => p.AlignItems, AlignItems.Start));
Assert.Contains("rz-timeline-align-items-start", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add(p => p.AlignItems, AlignItems.Center));
Assert.Contains("rz-timeline-align-items-center", component.Markup);
}
[Fact]
public void Timeline_Renders_Reverse()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenTimeline>();
component.SetParametersAndRender(parameters => parameters.Add(p => p.Reverse, true));
Assert.Contains("rz-timeline-reverse", component.Markup);
}
}
}

View File

@@ -0,0 +1,27 @@
using Bunit;
using System.Collections.Generic;
using Xunit;
namespace Radzen.Blazor.Tests
{
public class TocTests
{
[Fact]
public void TocItem_Renders_With_Attributes()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenTocItem>(parameters =>
{
parameters.Add(p => p.Attributes, new Dictionary<string, object>
{
{ "data-enhance-nav", "false" },
{ "aria-label", "Table of Contents Item" }
});
});
Assert.Contains("data-enhance-nav=\"false\"", component.Markup);
Assert.Contains("aria-label=\"Table of Contents Item\"", component.Markup);
}
}
}

View File

@@ -0,0 +1,98 @@
using Bunit;
using Xunit;
namespace Radzen.Blazor.Tests
{
public class ToggleButtonTests
{
[Fact]
public void ToggleButton_Renders_WithClassName()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenToggleButton>();
Assert.Contains(@"rz-button", component.Markup);
}
[Fact]
public void ToggleButton_Renders_TextParameter()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenToggleButton>();
var text = "Toggle Me";
component.SetParametersAndRender(parameters => parameters.Add(p => p.Text, text));
Assert.Contains(text, component.Markup);
}
[Fact]
public void ToggleButton_Renders_IconParameter()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenToggleButton>();
var icon = "toggle_on";
component.SetParametersAndRender(parameters => parameters.Add(p => p.Icon, icon));
Assert.Contains(icon, component.Markup);
}
[Fact]
public void ToggleButton_Renders_Value()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenToggleButton>();
component.SetParametersAndRender(parameters => parameters.Add(p => p.Value, true));
Assert.Contains("rz-state-active", component.Markup);
}
[Fact]
public void ToggleButton_Renders_Disabled()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenToggleButton>();
component.SetParametersAndRender(parameters => parameters.Add(p => p.Disabled, true));
Assert.Contains("rz-state-disabled", component.Markup);
}
[Fact]
public void ToggleButton_Renders_ButtonStyle()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenToggleButton>();
component.SetParametersAndRender(parameters => parameters.Add(p => p.ButtonStyle, ButtonStyle.Primary));
Assert.Contains("rz-primary", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add(p => p.ButtonStyle, ButtonStyle.Success));
Assert.Contains("rz-success", component.Markup);
}
[Fact]
public void ToggleButton_Raises_ChangeEvent()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenToggleButton>();
var changed = false;
bool newValue = false;
component.SetParametersAndRender(parameters => parameters.Add(p => p.Change, args =>
{
changed = true;
newValue = args;
}));
component.Find("button").Click();
Assert.True(changed);
Assert.True(newValue);
}
}
}

View File

@@ -0,0 +1,211 @@
using Bunit;
using Xunit;
using System.Collections.Generic;
using System.Linq;
namespace Radzen.Blazor.Tests
{
public class TreeTests
{
class Category
{
public string Name { get; set; }
public List<Product> Products { get; set; } = new List<Product>();
}
class Product
{
public string Name { get; set; }
}
class Employee
{
public string FirstName { get; set; }
public string LastName { get; set; }
public List<Employee> Employees { get; set; } = new List<Employee>();
}
[Fact]
public void Tree_Renders_WithClassName()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenTree>();
Assert.Contains(@"rz-tree", component.Markup);
}
[Fact]
public void Tree_Renders_TreeContainer()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenTree>();
Assert.Contains("rz-tree-container", component.Markup);
}
[Fact]
public void Tree_Renders_TabIndex()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenTree>();
Assert.Contains("tabindex=\"0\"", component.Markup);
}
[Fact]
public void Tree_Renders_WithData_SingleLevel()
{
using var ctx = new TestContext();
var data = new List<Category>
{
new Category { Name = "Electronics" },
new Category { Name = "Clothing" }
};
var component = ctx.RenderComponent<RadzenTree>(parameters =>
{
parameters.Add(p => p.Data, data);
parameters.Add(p => p.ChildContent, builder =>
{
builder.OpenComponent<RadzenTreeLevel>(0);
builder.AddAttribute(1, "TextProperty", "Name");
builder.CloseComponent();
});
});
Assert.Contains("Electronics", component.Markup);
Assert.Contains("Clothing", component.Markup);
}
[Fact]
public void Tree_Renders_WithData_HierarchicalData()
{
using var ctx = new TestContext();
var data = new List<Category>
{
new Category
{
Name = "Electronics",
Products = new List<Product>
{
new Product { Name = "Laptop" },
new Product { Name = "Phone" }
}
}
};
var component = ctx.RenderComponent<RadzenTree>(parameters =>
{
parameters.Add(p => p.Data, data);
parameters.Add(p => p.ChildContent, builder =>
{
builder.OpenComponent<RadzenTreeLevel>(0);
builder.AddAttribute(1, "TextProperty", "Name");
builder.AddAttribute(2, "ChildrenProperty", "Products");
builder.CloseComponent();
builder.OpenComponent<RadzenTreeLevel>(3);
builder.AddAttribute(4, "TextProperty", "Name");
builder.AddAttribute(5, "HasChildren", (object product) => false);
builder.CloseComponent();
});
});
Assert.Contains("Electronics", component.Markup);
}
[Fact]
public void Tree_Renders_WithData_SelfReferencing()
{
using var ctx = new TestContext();
var data = new List<Employee>
{
new Employee
{
FirstName = "Nancy",
LastName = "Davolio",
Employees = new List<Employee>
{
new Employee { FirstName = "Andrew", LastName = "Fuller" }
}
}
};
var component = ctx.RenderComponent<RadzenTree>(parameters =>
{
parameters.Add(p => p.Data, data);
parameters.Add(p => p.ChildContent, builder =>
{
builder.OpenComponent<RadzenTreeLevel>(0);
builder.AddAttribute(1, "TextProperty", "LastName");
builder.AddAttribute(2, "ChildrenProperty", "Employees");
builder.AddAttribute(3, "HasChildren", (object e) => (e as Employee).Employees.Any());
builder.CloseComponent();
});
});
Assert.Contains("Davolio", component.Markup);
}
[Fact]
public void Tree_Renders_WithCheckBoxes()
{
using var ctx = new TestContext();
var data = new List<Category>
{
new Category { Name = "Electronics" }
};
var component = ctx.RenderComponent<RadzenTree>(parameters =>
{
parameters.Add(p => p.AllowCheckBoxes, true);
parameters.Add(p => p.Data, data);
parameters.Add(p => p.ChildContent, builder =>
{
builder.OpenComponent<RadzenTreeLevel>(0);
builder.AddAttribute(1, "TextProperty", "Name");
builder.CloseComponent();
});
});
Assert.Contains("rz-chkbox", component.Markup);
}
[Fact]
public void Tree_Renders_WithExpandableItems()
{
using var ctx = new TestContext();
var data = new List<Category>
{
new Category
{
Name = "Electronics",
Products = new List<Product>
{
new Product { Name = "Laptop" }
}
}
};
var component = ctx.RenderComponent<RadzenTree>(parameters =>
{
parameters.Add(p => p.Data, data);
parameters.Add(p => p.ChildContent, builder =>
{
builder.OpenComponent<RadzenTreeLevel>(0);
builder.AddAttribute(1, "TextProperty", "Name");
builder.AddAttribute(2, "ChildrenProperty", "Products");
builder.CloseComponent();
builder.OpenComponent<RadzenTreeLevel>(3);
builder.AddAttribute(4, "TextProperty", "Name");
builder.CloseComponent();
});
});
// Expandable items should have a toggle icon
Assert.Contains("rz-tree-toggler", component.Markup);
}
}
}

View File

@@ -0,0 +1,95 @@
using Bunit;
using Xunit;
namespace Radzen.Blazor.Tests
{
public class UploadTests
{
[Fact]
public void Upload_Renders_WithClassName()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenUpload>();
Assert.Contains(@"rz-fileupload", component.Markup);
}
[Fact]
public void Upload_Renders_Disabled()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenUpload>(parameters =>
{
parameters.Add(p => p.Disabled, true);
});
Assert.Contains("rz-state-disabled", component.Markup);
}
[Fact]
public void Upload_Renders_ChooseText()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenUpload>(parameters =>
{
parameters.Add(p => p.ChooseText, "Select Files");
});
Assert.Contains("Select Files", component.Markup);
}
[Fact]
public void Upload_Renders_DefaultChooseText()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenUpload>();
Assert.Contains("Choose", component.Markup);
}
[Fact]
public void Upload_Renders_Icon()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenUpload>(parameters =>
{
parameters.Add(p => p.Icon, "upload");
});
Assert.Contains("upload", component.Markup);
Assert.Contains("rzi", component.Markup);
}
[Fact]
public void Upload_Renders_Multiple_Attribute()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenUpload>(parameters =>
{
parameters.Add(p => p.Multiple, true);
});
Assert.Contains("multiple", component.Markup);
}
[Fact]
public void Upload_Renders_Accept_Attribute()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenUpload>(parameters =>
{
parameters.Add(p => p.Accept, "image/*");
});
Assert.Contains("accept=\"image/*\"", component.Markup);
}
}
}

View File

@@ -0,0 +1,214 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Net.Http;
using System.Net.Http.Headers;
using System.IO;
using System.Text.Json.Serialization;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System.Linq;
namespace Radzen;
/// <summary>
/// Service for interacting with AI chat models to get completions with conversation memory.
/// </summary>
public class AIChatService(IServiceProvider serviceProvider, IOptions<AIChatServiceOptions> options) : IAIChatService
{
private readonly Dictionary<string, ConversationSession> sessions = new();
private readonly object sessionsLock = new();
/// <summary>
/// Gets the configuration options for the chat streaming service.
/// </summary>
public AIChatServiceOptions Options => options.Value;
/// <inheritdoc />
public async IAsyncEnumerable<string> GetCompletionsAsync(string userInput, string sessionId = null, [System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken cancellationToken = default, string model = null, string systemPrompt = null, double? temperature = null, int? maxTokens = null, string endpoint = null, string proxy = null, string apiKey = null, string apiKeyHeader = null)
{
if (string.IsNullOrWhiteSpace(userInput))
{
throw new ArgumentException("User input cannot be null or empty.", nameof(userInput));
}
// Get or create session
var session = GetOrCreateSession(sessionId);
// Add user message to conversation history
session.AddMessage("user", userInput);
// Use runtime parameters or fall back to configured options
var url = proxy ?? Options.Proxy ?? endpoint ?? Options.Endpoint;
var effectiveApiKey = apiKey ?? Options.ApiKey;
var effectiveApiKeyHeader = apiKeyHeader ?? Options.ApiKeyHeader;
// Get formatted messages including conversation history
var messages = session.GetFormattedMessages(systemPrompt ?? Options.SystemPrompt);
var payload = new
{
model = model ?? Options.Model,
messages = messages,
temperature = temperature ?? Options.Temperature,
max_tokens = maxTokens ?? Options.MaxTokens,
stream = true
};
var request = new HttpRequestMessage(HttpMethod.Post, url)
{
Content = new StringContent(JsonSerializer.Serialize(payload, new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull }), Encoding.UTF8, "application/json")
};
if (!string.IsNullOrEmpty(effectiveApiKey))
{
if (string.Equals(effectiveApiKeyHeader, "Authorization", StringComparison.OrdinalIgnoreCase))
{
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", effectiveApiKey);
}
else
{
request.Headers.Add(effectiveApiKeyHeader, effectiveApiKey);
}
}
var httpClient = serviceProvider.GetRequiredService<HttpClient>();
var response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken);
if (!response.IsSuccessStatusCode)
{
throw new Exception($"Chat stream failed: {await response.Content.ReadAsStringAsync(cancellationToken)}");
}
using var stream = await response.Content.ReadAsStreamAsync(cancellationToken);
using var reader = new StreamReader(stream);
var assistantResponse = new StringBuilder();
string line;
while ((line = await reader.ReadLineAsync()) is not null && !cancellationToken.IsCancellationRequested)
{
if (string.IsNullOrWhiteSpace(line) || !line.StartsWith("data:"))
{
continue;
}
var json = line["data:".Length..].Trim();
if (json == "[DONE]")
{
break;
}
var content = ParseStreamingResponse(json);
if (!string.IsNullOrEmpty(content))
{
assistantResponse.Append(content);
yield return content;
}
}
// Add assistant response to conversation history
if (assistantResponse.Length > 0)
{
session.AddMessage("assistant", assistantResponse.ToString());
}
}
/// <inheritdoc />
public ConversationSession GetOrCreateSession(string sessionId = null)
{
lock (sessionsLock)
{
if (string.IsNullOrEmpty(sessionId))
{
sessionId = Guid.NewGuid().ToString();
}
if (!sessions.TryGetValue(sessionId, out var session))
{
session = new ConversationSession
{
Id = sessionId,
MaxMessages = Options.MaxMessages
};
sessions[sessionId] = session;
}
return session;
}
}
/// <inheritdoc />
public void ClearSession(string sessionId)
{
lock (sessionsLock)
{
if (sessions.TryGetValue(sessionId, out var session))
{
session.Clear();
}
}
}
/// <inheritdoc />
public IEnumerable<ConversationSession> GetActiveSessions()
{
lock (sessionsLock)
{
return sessions.Values.ToList();
}
}
/// <inheritdoc />
public void CleanupOldSessions(int maxAgeHours = 24)
{
lock (sessionsLock)
{
var cutoffTime = DateTime.Now.AddHours(-maxAgeHours);
var sessionsToRemove = sessions.Values
.Where(s => s.LastUpdated < cutoffTime)
.Select(s => s.Id)
.ToList();
foreach (var sessionId in sessionsToRemove)
{
sessions.Remove(sessionId);
}
}
}
private static string ParseStreamingResponse(string json)
{
try
{
var doc = JsonDocument.Parse(json);
var root = doc.RootElement;
if (!root.TryGetProperty("choices", out var choices) || choices.GetArrayLength() == 0)
{
return string.Empty;
}
var firstChoice = choices[0];
if (!firstChoice.TryGetProperty("delta", out var delta))
{
return string.Empty;
}
if (delta.TryGetProperty("content", out var contentElement))
{
return contentElement.GetString() ?? string.Empty;
}
return string.Empty;
}
catch
{
return string.Empty;
}
}
}

View File

@@ -0,0 +1,48 @@
using System;
using Microsoft.Extensions.DependencyInjection;
namespace Radzen;
/// <summary>
/// Extension methods for configuring AIChatService in the dependency injection container.
/// </summary>
public static class AIChatServiceExtensions
{
/// <summary>
/// Adds the AIChatService to the service collection with the specified configuration.
/// </summary>
/// <param name="services">The service collection.</param>
/// <param name="configureOptions">The action to configure the AIChatService options.</param>
/// <returns>The updated service collection.</returns>
public static IServiceCollection AddAIChatService(this IServiceCollection services, Action<AIChatServiceOptions> configureOptions)
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
}
if (configureOptions == null)
{
throw new ArgumentNullException(nameof(configureOptions));
}
services.Configure(configureOptions);
services.AddScoped<IAIChatService, AIChatService>();
return services;
}
/// <summary>
/// Adds the AIChatService to the service collection with default options.
/// </summary>
/// <param name="services">The service collection.</param>
/// <returns>The updated service collection.</returns>
public static IServiceCollection AddAIChatService(this IServiceCollection services)
{
services.AddOptions<AIChatServiceOptions>();
services.AddScoped<IAIChatService, AIChatService>();
return services;
}
}

View File

@@ -0,0 +1,58 @@
namespace Radzen;
/// <summary>
/// Configuration options for the <see cref="AIChatService"/>.
/// </summary>
public class AIChatServiceOptions
{
/// <summary>
/// Gets or sets the endpoint URL for the AI service.
/// </summary>
public string Endpoint { get; set; } = string.Empty;
/// <summary>
/// Gets or sets the proxy URL for the AI service, if any. If set, this will override the Endpoint.
/// </summary>
public string Proxy { get; set; } = null;
/// <summary>
/// Gets or sets the API key for authentication with the AI service.
/// </summary>
public string ApiKey { get; set; } = string.Empty;
/// <summary>
/// Gets or sets the header name for the API key (e.g., 'Authorization' or 'api-key').
/// </summary>
public string ApiKeyHeader { get; set; } = "Authorization";
/// <summary>
/// Gets or sets the model name to use for executing chat completions (e.g., 'gpt-3.5-turbo').
/// </summary>
public string Model { get; set; }
/// <summary>
/// Gets or sets the system prompt for the AI assistant.
/// </summary>
public string SystemPrompt { get; set; } = "You are a helpful AI code assistant.";
/// <summary>
/// Gets or sets the temperature for the AI model (0.0 to 2.0). Set to 0.0 for deterministic responses, higher values for more creative outputs.
/// </summary>
public double Temperature { get; set; } = 0.7;
/// <summary>
/// Gets or sets the maximum number of tokens to generate in the response.
/// </summary>
public int? MaxTokens { get; set; }
/// <summary>
/// Gets or sets the maximum number of messages to keep in conversation memory.
/// </summary>
public int MaxMessages { get; set; } = 50;
/// <summary>
/// Gets or sets the maximum age in hours for conversation sessions before cleanup.
/// </summary>
public int SessionMaxAgeHours { get; set; } = 24;
}

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