Compare commits

...

31 Commits

Author SHA1 Message Date
Vladimir Enchev
e8b2c7b470 Radzen.Blazor updated 2021-05-06 06:42:45 +03:00
Vladimir Enchev
899e5ed7ed version updated 2021-05-06 06:32:56 +03:00
Atanas Korchev
04cf4eaa76 Add ability to link an image in the HtmlEditor. 2021-05-03 16:04:48 +03:00
Vladimir Enchev
9ca336c47f Fixed DataGrid footer cells not scrolling horizontally 2021-04-29 16:11:41 +03:00
Vladimir Enchev
dac818db4d BusyDialog method overload with message string parameter added 2021-04-27 17:30:31 +03:00
Vladimir Enchev
21a8ea11a3 Radzen.Blazor updated 2021-04-26 11:01:59 +03:00
Vladimir Enchev
52af7c44f1 Version updated 2021-04-26 10:55:33 +03:00
Atanas Korchev
18b9bd8e4b AutoComplete not editable in a FilterTemplate. 2021-04-26 10:03:12 +03:00
Atanas Korchev
5cdf7573ee Setting the class attribute in the CellRender event does not work. 2021-04-23 12:02:22 +03:00
Vladimir Enchev
3c415591db DataGrid cannot collapse expanded item in DataGridExpandMode.Single 2021-04-22 08:45:37 +03:00
Vladimir Enchev
667fdc0163 Avoid try/catch block during validation. Components that do not have @bind-Value are valid by default. (#103)
Co-authored-by: Atanas Korchev <akorchev@gmail.com>
2021-04-21 16:44:40 +03:00
Vladimir Enchev
10569b1426 Radzen.Blazor updated 2021-04-21 09:21:05 +03:00
Vladimir Enchev
2f4ddeab9f Version updated 2021-04-21 09:15:28 +03:00
Vladimir Enchev
235ce4873f DropDownDataGrid View exposed 2021-04-20 09:50:16 +03:00
Atanas Korchev
b26e1e12d6 Update version 2021-04-19 20:10:30 +03:00
Atanas Korchev
ef1a2fe75e Submit the form when Action is set even if EditContext is unavailable. 2021-04-19 20:08:49 +03:00
Atanas Korchev
c7766c05d2 Setting a custom CSS class replaces the built-in one in gauge, chart, colorpicker, html editor and scheduler. 2021-04-19 17:09:55 +03:00
Atanas Korchev
85c8b636a8 Improve Scheduler monthly view event rendering to take advantage of remaining space. 2021-04-19 13:43:04 +03:00
Vladimir Enchev
43b80f24e6 Radzen.Blazor updated 2021-04-19 11:11:20 +03:00
Vladimir Enchev
c7e6fd6a1b Version updated 2021-04-19 11:03:44 +03:00
Vladimir Enchev
7ca4ad60c1 DataGrid should not reset current page on sorting
Fix #99
2021-04-19 11:03:23 +03:00
Vladimir Enchev
a81a31ac66 Validate form with action (#100)
* Submit a valid form if its Action property is set.

* Refactor RadzenLogin to rely on a wrapper RadzenTemplateForm for validation.

* Set Action of the first login form.

* OnRegister method fixed

Co-authored-by: Atanas Korchev <akorchev@gmail.com>
2021-04-19 10:34:35 +03:00
Vladimir Enchev
6b3eda7c4a Radzen.Blazor updated 2021-04-14 10:49:19 +03:00
Vladimir Enchev
68243ee844 Version updated 2021-04-14 10:39:26 +03:00
Vladimir Enchev
6196daeead Numeric focus appearance improved 2021-04-14 10:38:16 +03:00
Vladimir Enchev
81c420c2e3 DropDownDataGrid AllowFilteringByAllStringColumns should respect column Filterable property
Fix #98
2021-04-14 09:59:56 +03:00
Vladimir Enchev
c533da896c DropDownDataGrid selected item not respected if SelectedValue is set 2021-04-13 09:54:49 +03:00
Vladimir Enchev
29f5f33a12 DataGrid pager not reset to first page after sort
Fix #95
2021-04-13 09:48:20 +03:00
Vladimir Enchev
aa7734d72b DropDownDataGrid AllowFilteringByAllStringColumns will raise exception if some of the column values is null
Fix #96
2021-04-13 09:41:12 +03:00
Atanas Korchev
e5a2132dfd Selecting a tree item does not remove prior selection. 2021-04-12 10:30:41 +03:00
Vladimir Enchev
f766594ef3 Record number column added to DataGrid totals demo 2021-04-08 19:51:51 +03:00
28 changed files with 306 additions and 184 deletions

View File

@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
namespace Radzen.Blazor
{
@@ -8,5 +9,19 @@ namespace Radzen.Blazor
public DateTime End { get; set; }
public string Text { get; set; }
public object Data { get; set; }
public override bool Equals(object obj)
{
return obj is AppointmentData data &&
Start == data.Start &&
End == data.End &&
Text == data.Text &&
EqualityComparer<object>.Default.Equals(Data, data.Data);
}
public override int GetHashCode()
{
return HashCode.Combine(Start, End, Text, Data);
}
}
}

View File

@@ -138,14 +138,12 @@ namespace Radzen
{
if (topPager != null)
{
topPager.GoToPage(CurrentPage).Wait();
InvokeAsync(topPager.Reload);
topPager.SetCurrentPage(CurrentPage);
}
if (bottomPager != null)
{
bottomPager.GoToPage(CurrentPage).Wait();
InvokeAsync(bottomPager.Reload);
bottomPager.SetCurrentPage(CurrentPage);
}
}

View File

@@ -8,7 +8,7 @@
<IsPackable>true</IsPackable>
<PackageId>Radzen.Blazor</PackageId>
<Product>Radzen.Blazor</Product>
<Version>3.2.2</Version>
<Version>3.2.8</Version>
<Copyright>Radzen Ltd.</Copyright>
<Authors>Radzen Ltd.</Authors>
<Description>Native Blazor UI components by Radzen Ltd.</Description>

View File

@@ -3,7 +3,7 @@
@if (Visible)
{
<div @ref="Element" class=@GetCssClass() @attributes=@Attributes style=@Style id="@GetId()">
<div @ref="Element" style=@Style @attributes=@Attributes class=@GetCssClass() id="@GetId()">
@if (Width.HasValue && Height.HasValue)
{
<svg style="width: 100%; height: 100%">

View File

@@ -8,7 +8,7 @@
<CascadingValue Value="@this">
@ChildContent
</CascadingValue>
<div @ref="Element" class="@GetCssClass()" @attributes="@Attributes" style="@Style" id="@GetId()">
<div @ref="Element" @attributes="@Attributes" class="@GetCssClass()" style="@Style" id="@GetId()">
@if (Width.HasValue && Height.HasValue)
{
<CascadingValue Value="@this">

View File

@@ -5,7 +5,7 @@
@if (Visible)
{
<div class=@GetCssClass() @ref=@Element @onclick=@Toggle @attributes=@Attributes style=@Style id=@GetId()>
<div @ref=@Element style=@Style @onclick=@Toggle @attributes=@Attributes class=@GetCssClass() id=@GetId()>
@if(Icon != null)
{
<i class="rzi">@Icon</i>

View File

@@ -1,4 +1,6 @@
@using Radzen
@using System.Collections
@using System.Collections.Generic
@using System.Linq.Dynamic.Core
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.JSInterop
@@ -21,12 +23,6 @@
@Template(selectedItem)
</label>
}
else if (SelectedValue != null)
{
<label class="rz-dropdown-label rz-inputtext rz-corner-all" onclick="@OpenPopupScript()" style="width:100%;">
@PropertyAccess.GetItemOrValueFromProperty(SelectedValue, TextProperty)
</label>
}
else if (selectedItem != null)
{
<label class="rz-dropdown-label rz-inputtext " onclick="@OpenPopupScript()" style="width:100%;">
@@ -45,7 +41,7 @@
else
{
foreach (var item in selectedItems)
{
{
@Template(item)@(",")
}
}
@@ -56,6 +52,12 @@
}
</label>
}
else if (SelectedValue != null)
{
<label class="rz-dropdown-label rz-inputtext rz-corner-all" onclick="@OpenPopupScript()" style="width:100%;">
@PropertyAccess.GetItemOrValueFromProperty(SelectedValue, TextProperty)
</label>
}
else if (!string.IsNullOrEmpty(Placeholder))
{
<label class="rz-dropdown-label rz-inputtext rz-placeholder" onclick="@OpenPopupScript()" style="width:100%;">
@@ -78,19 +80,19 @@
@if (AllowFiltering)
{
<div class="rz-lookup-search">
<input id="@SearchID" @ref="@search" tabindex="-1" placeholder="@SearchText"
<input id="@SearchID" @ref="@search" tabindex="-1" placeholder="@SearchText"
@onchange="@((args) => OnFilter(args))" @onkeydown="@((args) => OnFilterKeyPress(args))" value="@searchText" style="@(ShowSearch ? "" : "margin-right:0px;")" />
@if (ShowSearch)
{
<button class="rz-button rz-button-md btn-primary rz-button-icon-only" type="button" title="">
<i class="rz-button-icon-left rzi">search</i>
</button>
<button class="rz-button rz-button-md btn-primary rz-button-icon-only" type="button" title="">
<i class="rz-button-icon-left rzi">search</i>
</button>
}
</div>
}
@if (Template != null)
{
<RadzenGrid Responsive="@Responsive" ColumnWidth="@ColumnWidth" @ref="grid" Data="@(LoadData.HasDelegate ? (Data != null ? Data.Cast<object>() : Enumerable.Empty<object>()) : pagedData)" Count="@(LoadData.HasDelegate ? Count : count)" LoadData="@OnLoadData"
<RadzenGrid Responsive="@Responsive" ColumnWidth="@ColumnWidth" @ref="grid" Data="@(LoadData.HasDelegate ? (Data != null ? Data.Cast<object>() : Enumerable.Empty<object>()) : pagedData)" Count="@(LoadData.HasDelegate ? Count : count)" LoadData="@OnLoadData"
TItem="object" PageSize="@PageSize" PageNumbersCount="@PageNumbersCount" AllowPaging="true" AllowSorting="@AllowSorting" RowSelect="@OnRowSelect">
<Columns>
<RadzenGridColumn TItem="object" Property="@TextProperty" Title="@TextProperty" Type="string">
@@ -103,7 +105,7 @@
}
else
{
<RadzenGrid Responsive="@Responsive" ColumnWidth="@ColumnWidth" EmptyText="@EmptyText" @ref="grid" Data="@(LoadData.HasDelegate ? (Data != null ? Data.Cast<object>() : Enumerable.Empty<object>()) : pagedData)" Count="@(LoadData.HasDelegate ? Count : count)" LoadData="@OnLoadData"
<RadzenGrid Responsive="@Responsive" ColumnWidth="@ColumnWidth" EmptyText="@EmptyText" @ref="grid" Data="@(LoadData.HasDelegate ? (Data != null ? Data.Cast<object>() : Enumerable.Empty<object>()) : pagedData)" Count="@(LoadData.HasDelegate ? Count : count)" LoadData="@OnLoadData"
TItem="object" PageSize="@PageSize" PageNumbersCount="@PageNumbersCount" AllowPaging="true" AllowSorting="@AllowSorting" RowSelect="@OnRowSelect">
<Columns>
@if (Columns != null)
@@ -112,8 +114,8 @@
}
else
{
<RadzenGridColumn TItem="object" Property="@TextProperty" Title="@TextProperty" Type="string">
</RadzenGridColumn>
<RadzenGridColumn TItem="object" Property="@TextProperty" Title="@TextProperty" Type="string">
</RadzenGridColumn>
}
</Columns>
</RadzenGrid>
@@ -197,7 +199,8 @@
private string GetPropertyFilterExpression(string property, string filterCaseSensitivityOperator)
{
return $"{property}{filterCaseSensitivityOperator}.{Enum.GetName(typeof(StringFilterOperator), FilterOperator)}(@0)";
var p = $@"({property} == null ? """" : {property})";
return $"{p}{filterCaseSensitivityOperator}.{Enum.GetName(typeof(StringFilterOperator), FilterOperator)}(@0)";
}
private bool IsColumnFilterPropertyTypeString(RadzenGridColumn<object> column)
@@ -224,7 +227,7 @@
if (AllowFilteringByAllStringColumns)
{
query = query.Where(string.Join(" || ", grid.ColumnsCollection.Where(c => IsColumnFilterPropertyTypeString(c))
query = query.Where(string.Join(" || ", grid.ColumnsCollection.Where(c => c.Filterable && IsColumnFilterPropertyTypeString(c))
.Select(c => GetPropertyFilterExpression(c.GetFilterProperty(), filterCaseSensitivityOperator))),
FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ? searchText.ToLower() : searchText);
}
@@ -240,6 +243,8 @@
query = query.OrderBy(args.OrderBy);
}
_internalView = query;
count = query.Count();
pagedData = QueryableExtension.ToList(query.Skip(args.Skip.HasValue ? args.Skip.Value : 0).Take(PageSize)).Cast<object>();
@@ -250,6 +255,15 @@
}
}
IEnumerable _internalView = Enumerable.Empty<object>();
public new IEnumerable View
{
get
{
return _internalView;
}
}
protected override IEnumerable<object> Items
{
get
@@ -335,7 +349,8 @@
{
try
{
if (key == "ArrowDown" && selectedIndex < items.Count - 1) {
if (key == "ArrowDown" && selectedIndex < items.Count - 1)
{
selectedIndex++;
}

View File

@@ -179,7 +179,7 @@
}
else
{
<label style="height:35px">
<label class="rz-cell-filter-label" style="height:35px">
@if (column.Type == "string" && column.Format == "date-time")
{
<i onclick="@($"Radzen.togglePopup(this.parentNode, '{PopupID}{column.GetFilterProperty()}')")"
@@ -189,7 +189,7 @@
<span class="rz-current-filter">@column.FilterValue</span>
<i @onclick="@((args) => ClearFilter(column))" class="rzi rz-cell-filter-clear">close</i>
}
<div id="@($"{PopupID}{column.GetFilterProperty()}")" class="rz-overlaypanel "
<div id="@($"{PopupID}{column.GetFilterProperty()}")" class="rz-overlaypanel"
style="display:none;width:550px;" tabindex="0">
<div class="rz-overlaypanel-content">
@@ -946,6 +946,12 @@
{
expandedItems.Remove(itemToCollapse);
await RowCollapse.InvokeAsync(itemToCollapse);
if(object.Equals(item,itemToCollapse))
{
return;
}
}
}
@@ -977,6 +983,7 @@
column.SetFilterValue(null);
column.SetFilterValue(null, false);
skip = 0;
CurrentPage = 0;
await InvokeAsync(Reload);
}
@@ -1202,6 +1209,7 @@
{
column.SetFilterValue(args.Value, isFirst);
skip = 0;
CurrentPage = 0;
InvokeAsync(Reload);
}
}
@@ -1240,7 +1248,6 @@
public void OrderBy(string property)
{
var p = IsOData() ? property.Replace('.', '/') : PropertyAccess.GetProperty(property);
skip = 0;
orderBy = orderBy == $"{p} desc" || orderBy == null || orderBy.IndexOf(p) == -1 ? $"{p} asc" : $"{p} desc";
InvokeAsync(Reload);
}
@@ -1248,7 +1255,6 @@
public void OrderByDescending(string property)
{
var p = IsOData() ? property.Replace('.', '/') : PropertyAccess.GetProperty(property);
skip = 0;
orderBy = $"{p} desc";
InvokeAsync(Reload);
}

View File

@@ -1,5 +1,5 @@
@typeparam TItem
<td style="@Style" class="@CssClass" @attributes="@Attributes" @onclick="@OnClick" @ondblclick="@OnDblClick" >
<td style="@Style" @attributes="@Attributes" class="@GetCssClass()" @onclick="@OnClick" @ondblclick="@OnDblClick" >
<CascadingValue Value=this>
@ChildContent
</CascadingValue>
@@ -38,4 +38,14 @@
await Grid.OnRowDblClick(Item);
}
}
string GetCssClass()
{
if (Attributes != null && Attributes.TryGetValue("class", out var @class) && !string.IsNullOrEmpty(Convert.ToString(@class)))
{
return $"{CssClass} {@class}".Trim();
}
return CssClass;
}
}

View File

@@ -6,7 +6,7 @@
@if(Visible)
{
<div @ref=Element class=@GetCssClass() @attributes=@Attributes style=@Style id=@GetId()>
<div @ref=Element style=@Style @attributes=@Attributes class=@GetCssClass() id=@GetId()>
<div class="rz-html-editor-toolbar">
<CascadingValue Value=@this>
@if (ChildContent != null)

View File

@@ -12,6 +12,7 @@
class LinkAttributes
{
public string InnerText { get; set; }
public string InnerHtml { get; set; }
public string Href { get; set; }
public string Target { get; set; }
}
@@ -53,10 +54,13 @@
<label>@UrlText</label>
<RadzenTextBox @bind-Value=@attributes.Href style="width: 100%" />
</div>
@if (string.IsNullOrEmpty(attributes.InnerHtml))
{
<div class="rz-html-editor-dialog-item">
<label>@LinkText</label>
<RadzenTextBox @bind-Value=@attributes.InnerText style="width: 100%" />
</div>
}
<div class="rz-html-editor-dialog-item">
<RadzenCheckBox @bind-Value=@blank />
<label>@OpenInNewWindowText</label>
@@ -78,7 +82,8 @@
{
html.Append(" target=\"_blank\"");
}
html.AppendFormat(">{0}</a>", attributes.InnerText);
html.AppendFormat(">{0}</a>", string.IsNullOrEmpty(attributes.InnerText) ? attributes.InnerHtml : attributes.InnerText);
await Editor.ExecuteCommandAsync("insertHTML", html.ToString());
}

View File

@@ -2,7 +2,7 @@
@if (Visible)
{
<i @ref="@Element" style="@Style" class="@GetCssClass()" @attributes="Attributes" id="@GetId()">@((MarkupString)Icon)</i>
<i @ref="@Element" style="@Style" @attributes="Attributes" class="@GetCssClass()" id="@GetId()">@((MarkupString)Icon)</i>
}
@code {
[Parameter]

View File

@@ -3,54 +3,36 @@
@if (Visible)
{
<div @ref="@Element" @attributes="Attributes" class="@GetCssClass()" style="@Style" id="@GetId()">
<div class="rz-form" novalidate="">
<div class="rz-form">
<div class="row form-group">
<label class="col-sm-3 col-form-label" for="username">@UserText</label>
<div class="col">
<input name="userName" class="rz-textbox" @bind="@Username" />
@if ((loginClicked || resetClicked) && string.IsNullOrEmpty(Username))
{
<div class="md-inputfield">
<div class="rz-message rz-messages-error ">
@UserRequired
</div>
</div>
}
<RadzenTextBox style="display: block" Name="Username" @bind-Value=@Username />
<RadzenRequiredValidator Component="Username" Text=@UserRequired style="position: absolute" />
</div>
</div>
<div class="row form-group">
<label class="col-sm-3 col-form-label" for="password">@PasswordText</label>
<div class="col">
<input name="password" class="rz-textbox" type="password" @bind="@Password" @oninput="@(args => Password = $"{args.Value}")" @onkeypress="@OnPwdKeyPress" />
@if (loginClicked && string.IsNullOrEmpty(Password))
{
<div class="md-inputfield">
<div class="rz-message rz-messages-error ">
@PasswordRequired
</div>
</div>
}
<RadzenPassword style="display: block" Name="Password" @bind-Value=@Password />
<RadzenRequiredValidator Component="Password" Text=@PasswordRequired style="position: absolute" />
</div>
</div>
<div class="row form-group">
<div class="offset-sm-3 col login-buttons">
<button class="rz-button rz-button-md btn-primary" type="@(!string.IsNullOrEmpty(Username) && !string.IsNullOrEmpty(Password) ? "submit" : "button")" @onclick="@OnLogin">
<span class="rz-button-text" style="">@LoginText</span>
</button>
<RadzenButton ButtonStyle="ButtonStyle.Primary" ButtonType="ButtonType.Submit" Text=@LoginText Click=@OnLogin />
@if (AllowResetPassword)
{
<a @onclick="@OnReset">@ResetPasswordText</a>
<a @onclick=@OnReset>@ResetPasswordText</a>
}
</div>
</div>
</div>
@if (AllowRegister)
{
<div class="register" style="">
<div class="register">
@RegisterMessageText
<button class="rz-button rz-button-md btn-secondary" type="button" @onclick="@OnRegister">
<span class="rz-button-text">@RegisterText</span>
</button>
<RadzenButton ButtonType="ButtonType.Button" ButtonStyle="ButtonStyle.Primary" Text=@RegisterText Click=@OnRegister />
</div>
}
</div>
@@ -134,37 +116,24 @@
[Parameter]
public string PasswordRequired { get; set; } = "Password is required";
bool loginClicked = false;
protected async System.Threading.Tasks.Task OnLogin(EventArgs args)
protected async Task OnLogin()
{
loginClicked = true;
if (!string.IsNullOrEmpty(Username) && !string.IsNullOrEmpty(Password))
{
await Login.InvokeAsync(new Radzen.LoginArgs() { Username = Username, Password = Password });
await Login.InvokeAsync(new Radzen.LoginArgs { Username = Username, Password = Password });
}
}
async Task OnPwdKeyPress(KeyboardEventArgs args)
protected async Task OnReset(EventArgs args)
{
var key = args.Code != null ? args.Code : args.Key;
if (key == "Enter")
{
await OnLogin(args);
}
}
bool resetClicked = false;
protected async System.Threading.Tasks.Task OnReset(EventArgs args)
{
resetClicked = true;
if (!string.IsNullOrEmpty(Username))
{
await ResetPassword.InvokeAsync(Username);
}
}
protected async System.Threading.Tasks.Task OnRegister(EventArgs args)
protected async Task OnRegister()
{
await Register.InvokeAsync(args);
await Register.InvokeAsync(EventArgs.Empty);
}
}

View File

@@ -139,6 +139,14 @@
}
}
internal async void SetCurrentPage(int page)
{
if (CurrentPage != page)
{
skip = page * PageSize;
}
}
public async Task FirstPage(bool forceReload = false)
{
if (CurrentPage != 0 || forceReload)

View File

@@ -3,7 +3,7 @@
@inherits GaugeBase
@if (Visible)
{
<div @ref="Element" class=@GetCssClass() @attributes=@Attributes style=@Style id="@GetId()">
<div @ref="Element" style=@Style @attributes=@Attributes class=@GetCssClass() id=@GetId()>
@if (Width.HasValue && Height.HasValue)
{
<svg style="width: 100%; height: 100%">

View File

@@ -11,7 +11,7 @@
<CascadingValue Value="@this">
@ChildContent
</CascadingValue>
<div @ref=Element class=@GetCssClass() style=@Style @attributes=@Attributes id="@GetId()">
<div @ref=Element style=@Style @attributes=@Attributes class=@GetCssClass() id=@GetId()>
<div class="rz-scheduler-nav">
<div class="rz-scheduler-nav-prev-next">
<button class="rz-button rz-prev" @onclick=@OnPrev><RadzenIcon Icon="chevron_left" /></button>

View File

@@ -6,6 +6,7 @@ using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
using Microsoft.AspNetCore.Components.Forms;
using Radzen;
using Microsoft.JSInterop;
namespace Radzen.Blazor
{
@@ -67,26 +68,28 @@ namespace Radzen.Blazor
{
if (EditContext != null)
{
bool valid = false;
try
{
valid = EditContext.Validate();
}
catch
{
}
bool valid = EditContext.Validate();
if (valid)
{
await Submit.InvokeAsync(Data);
if (Action != null)
{
await JSRuntime.InvokeVoidAsync($"Radzen.submit", Element);
}
}
else
{
await InvalidSubmit.InvokeAsync(new FormInvalidSubmitEventArgs() { Errors = EditContext.GetValidationMessages() });
}
}
else
{
if (Action != null)
{
await JSRuntime.InvokeVoidAsync($"Radzen.submit", Element);
}
}
}
@@ -137,18 +140,16 @@ namespace Radzen.Blazor
builder.AddAttribute(2, "method", Method);
builder.AddAttribute(3, "action", Action);
}
else
{
builder.AddAttribute(4, "onsubmit", handleSubmitDelegate);
}
builder.AddAttribute(4, "onsubmit", handleSubmitDelegate);
builder.AddMultipleAttributes(5, Attributes);
builder.AddAttribute(6, "class", GetCssClass());
builder.AddElementReferenceCapture(7, form => Element = form);
builder.OpenComponent<CascadingValue<IRadzenForm>>(7);
builder.AddAttribute(8, "IsFixed", true);
builder.AddAttribute(9, "Value", this);
builder.AddAttribute(10, "ChildContent", new RenderFragment(contentBuilder =>
builder.OpenComponent<CascadingValue<IRadzenForm>>(8);
builder.AddAttribute(9, "IsFixed", true);
builder.AddAttribute(10, "Value", this);
builder.AddAttribute(11, "ChildContent", new RenderFragment(contentBuilder =>
{
contentBuilder.OpenComponent<CascadingValue<EditContext>>(0);
contentBuilder.AddAttribute(1, "IsFixed", true);
@@ -159,6 +160,7 @@ namespace Radzen.Blazor
builder.CloseComponent(); // CascadingValue<IRadzenForm>
builder.CloseElement(); // form
if (Data != null)

View File

@@ -6,16 +6,16 @@
@if (Visible)
{
<div @ref="@Element" @attributes="Attributes" class="@GetCssClass()" style="@Style" id="@GetId()">
<ul class="rz-tree-container">
<ul class="rz-tree-container">
<CascadingValue Value=this>
@ChildContent
</CascadingValue>
@if (Data != null && Levels.Any())
{
<CascadingValue Value=this>
@RenderChildren(Data, 0)
</CascadingValue>
}
{
<CascadingValue Value=this>
@RenderChildren(Data, 0)
</CascadingValue>
}
</ul>
</div>
}
@@ -43,13 +43,14 @@
public IEnumerable Data { get; set; }
[Parameter]
public object Value { get; set;}
public object Value { get; set; }
[Parameter]
public EventCallback<object> ValueChanged { get; set; }
void RenderTreeItem(RenderTreeBuilder builder, object data, RenderFragment<RadzenTreeItem> template, Func<object, string> text,
Func<object, bool> hasChildren, Func<object, bool> expanded, Func<object, bool> selected)
void RenderTreeItem(RenderTreeBuilder builder, object data, RenderFragment<RadzenTreeItem> template, Func<object,
string> text,
Func<object, bool> hasChildren, Func<object, bool> expanded, Func<object, bool> selected)
{
builder.OpenComponent<RadzenTreeItem>(0);
builder.AddAttribute(1, nameof(RadzenTreeItem.Text), text(data));
@@ -162,12 +163,19 @@
return PropertyAccess.Getter<T>(data, property);
}
protected override void OnParametersSet()
public override async Task SetParametersAsync(ParameterView parameters)
{
if (Value == null)
if (parameters.DidParameterChange(nameof(Value), Value))
{
SelectedItem = null;
var value = parameters.GetValueOrDefault<object>(nameof(Value));
if (value == null)
{
SelectedItem = null;
}
}
await base.SetParametersAsync(parameters);
}
internal void AddLevel(RadzenTreeLevel level)

View File

@@ -14,6 +14,7 @@
</div>
@{
var days = 0;
var points = new Dictionary<AppointmentData, double>();
}
<div class="rz-view-content">
@for (var date = StartDate; date < EndDate; date = date.AddDays(7))
@@ -23,9 +24,9 @@
@for (var start = date; start < date.AddDays(7); start = start.AddDays(1))
{
var end = start.AddDays(1);
var appointments = AppointmentsInSlot(start, end);
var excessCount = appointments.Count() - MaxAppointmentsInSlot;
var existingTops = ExistingTops(points, appointments.Take(MaxAppointmentsInSlot));
@foreach(var item in appointments.Take(MaxAppointmentsInSlot))
{
@@ -34,7 +35,12 @@
var left = slotIndex * slotWidth;
var length = Math.Max(1, Math.Ceiling(item.End.Subtract(date).TotalDays) - slotIndex);
var width = item.End <= date.AddDays(7) ? (length) * slotWidth : (7 - slotIndex) * slotWidth;
var top = 1.5 + 1.5 * Array.IndexOf(appointments, item);
if (!points.TryGetValue(item, out var top))
{
top = DetermineTop(existingTops);
points.Add(item, top);
existingTops.Add(top);
}
var height = 1.5;
var data = item;
@@ -103,6 +109,33 @@
await Scheduler.SelectSlot(date, date.AddDays(1));
}
double DetermineTop(HashSet<double> existingTops)
{
var top = 1.5;
while (existingTops.Contains(top))
{
top += 1.5;
}
return top;
}
HashSet<double> ExistingTops(IDictionary<AppointmentData, double> tops, IEnumerable<AppointmentData> appointments)
{
var existingTops = new HashSet<double>();
foreach (var appointment in appointments)
{
if (tops.TryGetValue(appointment, out var existingTop))
{
existingTops.Add(existingTop);
}
}
return existingTops;
}
async Task OnAppointmentClick(AppointmentData data)
{
await Scheduler.SelectAppointment(data);

View File

@@ -86,16 +86,19 @@ namespace Radzen.Blazor
throw new InvalidOperationException($"Cannot find component with Name {Component}");
}
IsValid = Validate(component);
messages.Clear(component.FieldIdentifier);
if (!IsValid)
if (component.FieldIdentifier.FieldName != null)
{
messages.Add(component.FieldIdentifier, Text);
}
IsValid = Validate(component);
EditContext?.NotifyValidationStateChanged();
messages.Clear(component.FieldIdentifier);
if (!IsValid)
{
messages.Add(component.FieldIdentifier, Text);
}
EditContext?.NotifyValidationStateChanged();
}
FieldIdentifier = component.FieldIdentifier;
}

View File

@@ -426,61 +426,65 @@ $grid-button-line-height: $grid-button-height !default;
font-size: $grid-filter-font-size;
font-weight: normal;
label {
display: flex;
flex: auto;
align-items: center;
.rz-cell-filter-label {
display: flex;
flex: auto;
align-items: center;
> .rzi {
width: $grid-filter-icon-width;
height: $grid-filter-icon-height;
font-size: $grid-filter-font-size;
margin: $grid-filter-icon-margin;
color: $grid-filter-color;
> .rzi {
width: $grid-filter-icon-width;
height: $grid-filter-icon-height;
font-size: $grid-filter-font-size;
margin: $grid-filter-icon-margin;
color: $grid-filter-color;
&.rz-cell-filter-clear {
margin-left: auto;
&.rz-cell-filter-clear {
margin-left: auto;
}
}
.rz-spinner {
border: none;
padding: 0;
height: auto;
background-color: transparent;
box-shadow: none;
line-height: 1;
flex: auto;
input {
line-height: 1;
&:focus {
outline: none;
color: $grid-filter-focus-color;
}
}
button {
display: none;
}
}
}
.rz-chkbox-box {
.rz-spinner {
border: none;
padding: 0;
height: auto;
background-color: transparent;
box-shadow: none;
line-height: 1;
flex: auto;
&.rz-state-active {
background-color: $input-background-color;
}
}
input {
> input {
width: 0;
flex: auto;
border: none;
box-shadow: none;
padding: 0;
background-color: transparent;
color: $grid-filter-color;
line-height: 1;
}
button {
display: none;
}
}
.rz-chkbox-box {
&.rz-state-active {
background-color: $input-background-color;
}
}
input {
width: 0;
flex: auto;
border: none;
box-shadow: none;
padding: 0;
background-color: transparent;
color: $grid-filter-color;
line-height: 1;
&:focus {
outline: none;
color: $grid-filter-focus-color;
&:focus {
outline: none;
color: $grid-filter-focus-color;
}
}
}
}

View File

@@ -1,5 +1,5 @@
$numeric-line-height: 1.5rem !default;
$numeric-input-padding: 1px 12px 1px 1px;
$numeric-input-padding: 1px 12px 1px 0.5rem;
$numeric-button-width: 0.875rem !default;
$numeric-button-height: $numeric-button-width !default;
$numeric-button-border-radius: 2px !default;
@@ -14,20 +14,19 @@ $numeric-button-color: $white !default;
@extend %input;
padding: 0px;
input[type='number'],
input[type='text'] {
-moz-appearance: textfield;
width: 100%;
height: 100%;
border: none;
background-color: transparent;
line-height: $numeric-line-height;
text-align: inherit;
padding: $numeric-input-padding;
&:focus {
outline: none;
}
&::-webkit-inner-spin-button,
&::-webkit-outer-spin-button {
-webkit-appearance: none;

View File

@@ -750,7 +750,9 @@ window.Radzen = {
e.target.clientHeight < e.target.scrollHeight ? (e.target.offsetWidth - e.target.clientWidth) + 'px' : '0px';
if (e.target.nextElementSibling) {
e.target.nextElementSibling.style.paddingRight = scrollLeft;
e.target.nextElementSibling.style.marginLeft = scrollLeft;
e.target.nextElementSibling.firstElementChild.style.paddingRight =
e.target.clientHeight < e.target.scrollHeight ? (e.target.offsetWidth - e.target.clientWidth) + 'px' : '0px';
}
for (var i = 0; i < document.body.children.length; i++) {
@@ -1051,11 +1053,15 @@ window.Radzen = {
selectionAttributes: function (selector, attributes) {
var selection = getSelection();
var target = selection.focusNode;
var innerHTML;
if (target) {
if (target.nodeType == 3) {
target = target.parentElement;
} else {
target = target.childNodes[selection.focusOffset];
if (target) {
innerHTML = target.outerHTML;
}
}
if (target && !target.matches(selector)) {
target = target.closest(selector);
@@ -1066,7 +1072,7 @@ window.Radzen = {
result[name] = target[name];
}
return result;
}, { innerText: selection.toString() });
}, { innerText: selection.toString(), innerHTML: innerHTML });
},
destroyEditor: function (ref) {
if (ref) {
@@ -1093,6 +1099,9 @@ window.Radzen = {
document.addEventListener('touchend', ref.mouseUpHandler, { passive: true });
return Radzen.clientRect(ref);
},
submit: function (form) {
form.submit();
},
clientRect: function (arg) {
var el = arg instanceof Element || arg instanceof HTMLDocument
? arg

View File

@@ -3,7 +3,7 @@
@using RadzenBlazorDemos.Data
@using RadzenBlazorDemos.Models.Northwind
@using Microsoft.EntityFrameworkCore
@using System.Linq
@inject NorthwindContext dbContext
<h1>DataGrid Footer Totals</h1>
@@ -18,8 +18,13 @@
else
{
<RadzenGrid @ref="ordersGrid" AllowFiltering="true" AllowPaging="true" PageSize="3" AllowSorting="true"
Data="@dbContext.Orders.Include("Customer").Include("Employee")" TItem="Order">
Data="@orders" TItem="Order">
<Columns>
<RadzenGridColumn Width="50px" TItem="Order" Title="Nr." Filterable="false" Sortable="false" TextAlign="TextAlign.Center">
<Template>
@(orders.IndexOf(context) + 1)
</Template>
</RadzenGridColumn>
<RadzenGridColumn Width="200px" TItem="Order" Property="OrderID" Title="Order ID">
<FooterTemplate>
Displayed orders: <b>@ordersGrid.View.Count()</b> of <b>@orders.Count()</b>
@@ -56,7 +61,7 @@ else
@code {
RadzenGrid<Order> ordersGrid;
IEnumerable<Order> orders;
IList<Order> orders;
protected override void OnInitialized()
{

View File

@@ -66,9 +66,10 @@
};
timer.Start();
await BusyDialog();
await BusyDialog("Busy...");
}
// Busy dialog from markup
async Task BusyDialog() => await DialogService.OpenAsync("", ds =>
@<div>
<div class="row">
@@ -77,4 +78,25 @@
</div>
</div>
</div>, new DialogOptions() { ShowTitle = false, Style = "min-height:auto;min-width:auto;width:auto" });
// Busy dialog from string
async Task BusyDialog(string message) => await DialogService.OpenAsync("", ds =>
{
RenderFragment content = b =>
{
var i = 0;
b.OpenElement(i++, "div");
b.AddAttribute(i++, "class", "row");
b.OpenElement(i++, "div");
b.AddAttribute(i++, "class", "col-md-12");
b.AddContent(i++, message);
b.CloseElement();
b.CloseElement();
};
return content;
}, new DialogOptions() { ShowTitle = false, Style = "min-height:auto;min-width:auto;width:auto" });
}

View File

@@ -45,14 +45,14 @@
</Template>
</RadzenDropDownDataGrid>
<h3 style="margin-top: 2rem">DropDownDataGrid with multiple selection and multiple columns</h3>
<RadzenDropDownDataGrid AllowFiltering="true" FilterCaseSensitivity="FilterCaseSensitivity.CaseInsensitive" AllowClear="true" @bind-Value=@multipleValues
<RadzenDropDownDataGrid @ref="grid" AllowFiltering="true" FilterCaseSensitivity="FilterCaseSensitivity.CaseInsensitive" AllowClear="true" @bind-Value=@multipleValues
Multiple="true" Placeholder="Select..." Data=@customers TextProperty="CompanyName" ValueProperty="CustomerID"
Change=@(args => OnChange(args, "DropDownDataGrid with multiple selection")) Style="width:400px">
<Columns>
<RadzenDropDownDataGridColumn Width="40px" Sortable="false">
<HeaderTemplate>
<RadzenCheckBox TriState="false" TValue="bool" Value="@(customers.Any(c => multipleValues != null && multipleValues.Contains(c.CustomerID)))"
Change="@(args => multipleValues = args ? customers.Select(c => c.CustomerID) : multipleValues = Enumerable.Empty<string>())" />
Change="@(args => multipleValues = args ? grid.View.Cast<Customer>().Select(c => c.CustomerID) : multipleValues = Enumerable.Empty<string>())" />
</HeaderTemplate>
<Template Context="data">
<RadzenCheckBox TriState="false" Value="@(multipleValues != null && multipleValues.Contains(((Customer)data).CustomerID))" />
@@ -72,6 +72,7 @@
</RadzenExample>
@code {
RadzenDropDownDataGrid<IEnumerable<string>> grid;
IEnumerable<Customer> customers;
IEnumerable<string> multipleValues;

View File

@@ -9,30 +9,39 @@
<div class="col-xl-6">
<h3>Simple login</h3>
<RadzenCard>
<RadzenLogin AllowRegister="false" AllowResetPassword="false" Login=@(args => OnLogin(args, "Simple login")) Style="margin-bottom: 20px;" />
<RadzenTemplateForm Data=@("SimpleLogin") Action="http://www.google.com">
<RadzenLogin AllowRegister="false" AllowResetPassword="false" Login=@(args => OnLogin(args, "Simple login")) Style="margin-bottom: 20px;" />
</RadzenTemplateForm>
</RadzenCard>
<h3 style="margin-top: 1rem">Login with register</h3>
<RadzenCard>
<RadzenTemplateForm Data=@("LoginWithRegister")>
<RadzenLogin AllowResetPassword="false"
Login=@(args => OnLogin(args, "Login with register"))
Register=@(args => OnRegister("Login with register")) Style="margin-bottom: 20px;" />
</RadzenTemplateForm>
</RadzenCard>
<h3 style="margin-top: 1rem">Login with register and password reset</h3>
<RadzenCard>
<RadzenTemplateForm Data=@("LoginWithRegisterAndReset")>
<RadzenLogin Login=@(args => OnLogin(args, "Login with register and password reset"))
ResetPassword=@(args => OnResetPassword(args, "Login with register and password reset"))
Register=@(args => OnRegister("Login with register and password reset")) Style="margin-bottom: 20px;" />
</RadzenTemplateForm>
</RadzenCard>
<h3 style="margin-top: 1rem">Login with default values</h3>
<RadzenCard>
<RadzenTemplateForm Data=@("LoginWithDefaultValues")>
<RadzenLogin AllowRegister="true" AllowResetPassword="true" Username=@userName Password=@password
Login=@(args => OnLogin(args, "Login with default values"))
ResetPassword=@(args => OnResetPassword(args, "Login with default values"))
Register=@(args => OnRegister("Login with default values"))
Style="margin-bottom: 20px;" />
</RadzenTemplateForm>
</RadzenCard>
<h3 style="margin-top: 1rem">Localization</h3>
<RadzenCard>
<RadzenTemplateForm Data=@("Localization")>
<RadzenLogin AllowRegister="true" AllowResetPassword="true"
LoginText="Einloggen" UserText="Benutzername" PasswordText="Passwort"
UserRequired="Benutzername erforderlich"
@@ -44,6 +53,7 @@
ResetPassword=@(args => OnResetPassword(args, "Localized login"))
Register=@(args => OnRegister("Localized login"))
Style="margin-bottom: 20px;" />
</RadzenTemplateForm>
</RadzenCard>
</div>
<div class="col-md-6">

View File

@@ -5,7 +5,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Radzen.Blazor" Version="3.2.2" />
<PackageReference Include="Radzen.Blazor" Version="3.2.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.0" />
<PackageReference Include="DocumentFormat.OpenXml" Version="2.11.3" />