mirror of
https://github.com/radzenhq/radzen-blazor.git
synced 2026-02-04 05:35:44 +00:00
Compare commits
142 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a244741640 | ||
|
|
e3f5360a7f | ||
|
|
c280bae14f | ||
|
|
e99671ba81 | ||
|
|
73338462e5 | ||
|
|
1912e69375 | ||
|
|
60a3789e9c | ||
|
|
a89bc5a5ce | ||
|
|
08f3126f46 | ||
|
|
53e746146b | ||
|
|
1e7cc0d655 | ||
|
|
b37a81b297 | ||
|
|
6aec8118f2 | ||
|
|
756732803f | ||
|
|
a6b8abb9ce | ||
|
|
38feb54237 | ||
|
|
ee828de086 | ||
|
|
bc82638fea | ||
|
|
edb6f58f66 | ||
|
|
23b9a6e7bf | ||
|
|
0b3c6058e2 | ||
|
|
cb6572980e | ||
|
|
78e5bbb9dc | ||
|
|
12b52b3e79 | ||
|
|
e226749388 | ||
|
|
001cd0cdcd | ||
|
|
c3806348a0 | ||
|
|
c6a8d80d45 | ||
|
|
2babacd15a | ||
|
|
456ab29a34 | ||
|
|
1de201841a | ||
|
|
a5586fd4ea | ||
|
|
a14ac78957 | ||
|
|
1193ede1ca | ||
|
|
8ad75a1773 | ||
|
|
9ea1b44e64 | ||
|
|
b92ef7922d | ||
|
|
3d6eff639f | ||
|
|
011e761d7f | ||
|
|
a2fdb687a1 | ||
|
|
ff846e0cc1 | ||
|
|
df0ad0d9f1 | ||
|
|
716d1a6cba | ||
|
|
3e7468177d | ||
|
|
d4113e6715 | ||
|
|
7f7ce06d0e | ||
|
|
7cfea596fd | ||
|
|
7eae5d0f6e | ||
|
|
a390658ad9 | ||
|
|
ecc403cbbc | ||
|
|
e870ca856c | ||
|
|
e7b8fec063 | ||
|
|
7767878c4c | ||
|
|
63de20fe36 | ||
|
|
6114a9a8ed | ||
|
|
d5514ca0cd | ||
|
|
8cf0565211 | ||
|
|
32246b1d69 | ||
|
|
418dbf09ec | ||
|
|
a198d09b71 | ||
|
|
f3bb0e7b90 | ||
|
|
b3917e19a2 | ||
|
|
e7d8b7454f | ||
|
|
4d4660eed9 | ||
|
|
b80e47672d | ||
|
|
3b370841cc | ||
|
|
7ec2a9a0a5 | ||
|
|
e340a376ef | ||
|
|
a2709afc5c | ||
|
|
9c7ed95f23 | ||
|
|
524f1f99cb | ||
|
|
2ac6d7f2bb | ||
|
|
6b3fd9efae | ||
|
|
d99daa6538 | ||
|
|
13e0bba379 | ||
|
|
ed7c5bc537 | ||
|
|
03b7968b99 | ||
|
|
274d64246b | ||
|
|
4450053fd3 | ||
|
|
8c321f18e1 | ||
|
|
e015807edc | ||
|
|
4ebcd2f214 | ||
|
|
67cd8b7a61 | ||
|
|
0a802ca73b | ||
|
|
097f37bfbc | ||
|
|
524e42980a | ||
|
|
34eebc9406 | ||
|
|
65f20c232c | ||
|
|
d742fdae86 | ||
|
|
397e2baf6c | ||
|
|
4b1d951083 | ||
|
|
ab65a5a975 | ||
|
|
9947cbf47b | ||
|
|
f781ba0c6a | ||
|
|
e3c605a7a9 | ||
|
|
849e6761b8 | ||
|
|
407ef36b70 | ||
|
|
fef5ceb36d | ||
|
|
2e22f556d8 | ||
|
|
95b833402f | ||
|
|
c0e7418e7c | ||
|
|
4d72ef1efe | ||
|
|
a00bce399f | ||
|
|
2b8658b233 | ||
|
|
fc2784450b | ||
|
|
896d9bd3ae | ||
|
|
9199096f69 | ||
|
|
bdb2694734 | ||
|
|
98ab3cd3d0 | ||
|
|
22f7d3f9f4 | ||
|
|
7f27dafe32 | ||
|
|
37a1e6d4b5 | ||
|
|
91d5473bf2 | ||
|
|
b883cccb30 | ||
|
|
2ca7b3ba5f | ||
|
|
faada7ae7b | ||
|
|
3910fb778f | ||
|
|
4577d063cc | ||
|
|
1f5c70166e | ||
|
|
f920f9f08d | ||
|
|
e6272e88e6 | ||
|
|
4be24abf7f | ||
|
|
85cc05a144 | ||
|
|
7f726c4e2a | ||
|
|
5c86ffd2ac | ||
|
|
257444b640 | ||
|
|
c61d453de4 | ||
|
|
4b88b18e78 | ||
|
|
1125894e7a | ||
|
|
e8894360fa | ||
|
|
168c071ac3 | ||
|
|
d6dd67951e | ||
|
|
c7e4470a60 | ||
|
|
cb6789504a | ||
|
|
314664c4e2 | ||
|
|
58794f806c | ||
|
|
6a470a6448 | ||
|
|
27bf1713a0 | ||
|
|
c1e428dd3e | ||
|
|
661e5b50f8 | ||
|
|
749c2cf600 | ||
|
|
153e9e01bc |
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2018-2024 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
|
||||
|
||||
@@ -174,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()
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using AngleSharp.Dom;
|
||||
using Bunit;
|
||||
@@ -14,18 +15,20 @@ namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public string Text { get; set; }
|
||||
public int Id { get; set; }
|
||||
public bool Disabled { get; set; } = false;
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
@@ -100,7 +103,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));
|
||||
});
|
||||
|
||||
@@ -123,7 +127,8 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
List<DataItem> boundCollection = [new() { Text = "Item 2" }];
|
||||
|
||||
var component = DropDown<string>(ctx, parameters => {
|
||||
var component = DropDown<string>(ctx, parameters =>
|
||||
{
|
||||
parameters.Add(p => p.ItemComparer, new DataItemComparer());
|
||||
parameters.Add(p => p.Multiple, true);
|
||||
parameters.Add(p => p.Value, boundCollection);
|
||||
@@ -150,7 +155,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);
|
||||
});
|
||||
@@ -275,6 +281,50 @@ namespace Radzen.Blazor.Tests
|
||||
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<DataItem>>(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"));
|
||||
}
|
||||
|
||||
class DataItemComparer : IEqualityComparer<DataItem>, IEqualityComparer<object>
|
||||
{
|
||||
@@ -292,7 +342,7 @@ namespace Radzen.Blazor.Tests
|
||||
return obj.Text.GetHashCode();
|
||||
}
|
||||
|
||||
public bool Equals(object x, object y)
|
||||
public new bool Equals(object x, object y)
|
||||
{
|
||||
return Equals((DataItem)x, (DataItem)y);
|
||||
}
|
||||
|
||||
@@ -28,6 +28,10 @@ namespace Radzen.Blazor.Tests
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool Disabled { get; set; }
|
||||
public bool Visible { get; set; }
|
||||
public IFormFieldContext FormFieldContext => null;
|
||||
|
||||
public object Value { get; set; }
|
||||
}
|
||||
|
||||
@@ -169,4 +173,4 @@ namespace Radzen.Blazor.Tests
|
||||
Assert.False(component.Instance.Validate(DateTime.Now));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -463,10 +463,11 @@ namespace Radzen.Blazor.Tests
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var value = new Dollars(11m);
|
||||
Dollars? ConvertFunc(string s) => decimal.TryParse(s, out var val) ? new Dollars(val) : null;
|
||||
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?>.Value), value),
|
||||
ComponentParameter.CreateParameter(nameof(RadzenNumeric<Dollars>.Culture), System.Globalization.CultureInfo.InvariantCulture)
|
||||
);
|
||||
|
||||
component.Render();
|
||||
@@ -494,7 +495,101 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
component.Render();
|
||||
|
||||
Assert.Contains($" value=\"{valueToTest.ToString(format)}\"", component.Markup);
|
||||
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]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using System.Linq;
|
||||
using System.Linq.Dynamic.Core;
|
||||
using Radzen.Blazor.Rendering;
|
||||
using System.Threading.Tasks;
|
||||
using System.Net.Mime;
|
||||
@@ -410,7 +409,7 @@ namespace Radzen.Blazor
|
||||
|
||||
if (IsDate(CategoryProperty) || IsNumeric(CategoryProperty))
|
||||
{
|
||||
Items = Items.AsQueryable().OrderBy(DynamicLinqCustomTypeProvider.ParsingConfig, CategoryProperty).ToList();
|
||||
Items = Items.AsQueryable().OrderBy(CategoryProperty).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,11 +7,11 @@ using Radzen.Blazor.Rendering;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Linq.Dynamic.Core;
|
||||
using System.Linq.Dynamic.Core.Parser;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Metadata;
|
||||
using System.Text;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Text.Json;
|
||||
@@ -2287,6 +2287,18 @@ namespace Radzen
|
||||
/// </summary>
|
||||
/// <value>The property.</value>
|
||||
public string Property { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the property type.
|
||||
/// </summary>
|
||||
/// <value>The property type.</value>
|
||||
public Type Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the filtered property.
|
||||
/// </summary>
|
||||
/// <value>The property.</value>
|
||||
public string FilterProperty { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the value to filter by.
|
||||
/// </summary>
|
||||
@@ -2325,6 +2337,18 @@ namespace Radzen
|
||||
/// <value>The property.</value>
|
||||
public string Property { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the property type.
|
||||
/// </summary>
|
||||
/// <value>The property type.</value>
|
||||
public Type Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the filtered property.
|
||||
/// </summary>
|
||||
/// <value>The property.</value>
|
||||
public string FilterProperty { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value to filter by.
|
||||
/// </summary>
|
||||
@@ -2428,6 +2452,43 @@ namespace Radzen
|
||||
public int Level { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The result of a call to a <see cref="QueryableExtension"/>.GroupByMany() overload.
|
||||
/// </summary>
|
||||
public class GroupResult
|
||||
{
|
||||
/// <summary>
|
||||
/// The key value of the group.
|
||||
/// </summary>
|
||||
public dynamic Key { get; internal set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// The number of resulting elements in the group.
|
||||
/// </summary>
|
||||
public int Count { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// The resulting elements in the group.
|
||||
/// </summary>
|
||||
public IEnumerable Items { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// The resulting subgroups in the group.
|
||||
/// </summary>
|
||||
public IEnumerable<GroupResult> Subgroups { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="System.String" /> showing the key of the group and the number of items in the group.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="System.String" /> that represents this instance.
|
||||
/// </returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, "{0} ({1})", ((object)Key).ToString(), Count);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Supplies information about a <see cref="PagedDataBoundComponent{TItem}.LoadData" /> event that is being raised.
|
||||
/// </summary>
|
||||
@@ -2902,9 +2963,14 @@ namespace Radzen
|
||||
/// </summary>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <param name="culture">The culture.</param>
|
||||
/// <returns>System.Object</returns>
|
||||
public static object ChangeType(object value, Type type)
|
||||
public static object ChangeType(object value, Type type, CultureInfo culture = null)
|
||||
{
|
||||
if (culture == null)
|
||||
{
|
||||
culture = CultureInfo.CurrentCulture;
|
||||
}
|
||||
if (value == null && Nullable.GetUnderlyingType(type) != null)
|
||||
{
|
||||
return value;
|
||||
@@ -2932,7 +2998,7 @@ namespace Radzen
|
||||
|
||||
}
|
||||
|
||||
return value is IConvertible ? Convert.ChangeType(value, Nullable.GetUnderlyingType(type) ?? type) : value;
|
||||
return value is IConvertible ? Convert.ChangeType(value, Nullable.GetUnderlyingType(type) ?? type, culture) : value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2953,7 +3019,9 @@ namespace Radzen
|
||||
{
|
||||
if (propertyName.Contains("["))
|
||||
{
|
||||
return DynamicExpressionParser.ParseLambda<TItem, TValue>(null, false, propertyName).Compile();
|
||||
var arg = Expression.Parameter(typeof(TItem));
|
||||
|
||||
return Expression.Lambda<Func<TItem, TValue>>(QueryableExtension.GetNestedPropertyExpression(arg, propertyName, type), arg).Compile();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3105,11 +3173,6 @@ namespace Radzen
|
||||
}
|
||||
var propertyName = $"{(type != null ? "@" : "")}{property}";
|
||||
|
||||
if (propertyName.IndexOf(".") != -1)
|
||||
{
|
||||
return $"np({propertyName})";
|
||||
}
|
||||
|
||||
return propertyName;
|
||||
}
|
||||
|
||||
@@ -3405,6 +3468,21 @@ namespace Radzen
|
||||
/// Sets the focus.
|
||||
/// </summary>
|
||||
ValueTask FocusAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Sets the Disabled state of the component
|
||||
/// </summary>
|
||||
bool Disabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets the Visible state of the component
|
||||
/// </summary>
|
||||
bool Visible { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets the FormFieldContext of the component
|
||||
/// </summary>
|
||||
IFormFieldContext FormFieldContext { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -3789,4 +3867,4 @@ namespace Radzen
|
||||
/// </summary>
|
||||
Right
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,12 +3,9 @@ using Microsoft.AspNetCore.Components.Forms;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using Radzen.Blazor;
|
||||
using Radzen.Blazor.Rendering;
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Dynamic.Core;
|
||||
using System.Linq.Expressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -262,23 +259,7 @@ namespace Radzen
|
||||
{
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
{
|
||||
var ignoreCase = FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive;
|
||||
|
||||
var query = new List<string>();
|
||||
|
||||
if (!string.IsNullOrEmpty(TextProperty))
|
||||
{
|
||||
query.Add(TextProperty);
|
||||
}
|
||||
|
||||
if (ignoreCase)
|
||||
{
|
||||
query.Add("ToLower()");
|
||||
}
|
||||
|
||||
query.Add($"{Enum.GetName(typeof(StringFilterOperator), FilterOperator)}(@0)");
|
||||
|
||||
_view = Query.Where(DynamicLinqCustomTypeProvider.ParsingConfig, string.Join(".", query), ignoreCase ? searchText.ToLower() : searchText);
|
||||
_view = Query.Where(TextProperty, searchText, FilterOperator, FilterCaseSensitivity);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -180,6 +180,27 @@ namespace Radzen
|
||||
return _sideDialogTask.Task;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens a side dialog with the specified arguments
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of Blazor component which will be displayed in the side dialog.</typeparam>
|
||||
/// <param name="title">The text displayed in the title bar of the side dialog.</param>
|
||||
/// <param name="parameters">The dialog parameters. Passed as property values of <typeparamref name="T"/></param>
|
||||
/// <param name="options">The side dialog options.</param>
|
||||
public void OpenSide<T>(string title, Dictionary<string, object> parameters = null, SideDialogOptions options = null)
|
||||
where T : ComponentBase
|
||||
{
|
||||
CloseSide();
|
||||
|
||||
if (options == null)
|
||||
{
|
||||
options = new SideDialogOptions();
|
||||
}
|
||||
|
||||
options.Title = title;
|
||||
OnSideOpen?.Invoke(typeof(T), parameters ?? new Dictionary<string, object>(), options);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Closes the side dialog
|
||||
/// </summary>
|
||||
@@ -189,8 +210,9 @@ namespace Radzen
|
||||
if (_sideDialogTask?.Task.IsCompleted == false)
|
||||
{
|
||||
_sideDialogTask.TrySetResult(result);
|
||||
OnSideClose?.Invoke(result);
|
||||
}
|
||||
|
||||
OnSideClose?.Invoke(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -6,7 +6,6 @@ using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Dynamic.Core;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Radzen
|
||||
@@ -341,15 +340,17 @@ namespace Radzen
|
||||
|
||||
internal bool IsAllSelected()
|
||||
{
|
||||
List<object> notDisabledItemsInList = View.Cast<object>().ToList()
|
||||
.Where(i => disabledPropertyGetter == null || disabledPropertyGetter(i) as bool? != true)
|
||||
.ToList();
|
||||
|
||||
if (LoadData.HasDelegate && !string.IsNullOrEmpty(ValueProperty))
|
||||
{
|
||||
return View != null && View.Cast<object>().ToList()
|
||||
.Where(i => disabledPropertyGetter != null ? disabledPropertyGetter(i) as bool? != true : true)
|
||||
return View != null && notDisabledItemsInList.Count > 0 && notDisabledItemsInList
|
||||
.All(i => IsItemSelectedByValue(GetItemOrValueFromProperty(i, ValueProperty)));
|
||||
}
|
||||
|
||||
return View != null && selectedItems.Count == View.Cast<object>().ToList()
|
||||
.Where(i => disabledPropertyGetter != null ? disabledPropertyGetter(i) as bool? != true : true).Count();
|
||||
return View != null && notDisabledItemsInList.Count > 0 && selectedItems.Count == notDisabledItemsInList.Count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -434,9 +435,13 @@ namespace Radzen
|
||||
|
||||
var type = query.ElementType;
|
||||
|
||||
if (type == typeof(object) && typeof(EnumerableQuery).IsAssignableFrom(query.GetType()) && query.Any())
|
||||
if (type == typeof(object) && typeof(EnumerableQuery).IsAssignableFrom(query.GetType()) && query.Cast<object>().Any())
|
||||
{
|
||||
type = query.FirstOrDefault().GetType();
|
||||
var firstElement = query.Cast<object>().FirstOrDefault(i => i != null);
|
||||
if (firstElement != null)
|
||||
{
|
||||
type = firstElement.GetType();
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(ValueProperty))
|
||||
@@ -454,7 +459,10 @@ namespace Radzen
|
||||
disabledPropertyGetter = GetGetter(DisabledProperty, type);
|
||||
}
|
||||
|
||||
selectedItems = new HashSet<object>(ItemComparer);
|
||||
if (selectedItems.Count == 0)
|
||||
{
|
||||
selectedItems = new HashSet<object>(ItemComparer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -737,8 +745,7 @@ namespace Radzen
|
||||
var filteredItems = (!string.IsNullOrEmpty(TextProperty) ?
|
||||
Query.Where(TextProperty, args.Key, StringFilterOperator.StartsWith, FilterCaseSensitivity.CaseInsensitive) :
|
||||
Query)
|
||||
.Cast<object>()
|
||||
.ToList();
|
||||
.Cast(Query.ElementType).Cast<dynamic>().ToList();
|
||||
|
||||
|
||||
if (previousKey != args.Key)
|
||||
@@ -1136,9 +1143,13 @@ namespace Radzen
|
||||
var query = Data.AsQueryable();
|
||||
var elementType = query.ElementType;
|
||||
|
||||
if (elementType == typeof(object) && typeof(EnumerableQuery).IsAssignableFrom(query.GetType()) && query.Any())
|
||||
if (elementType == typeof(object) && typeof(EnumerableQuery).IsAssignableFrom(query.GetType()) && query.Cast<object>().Any())
|
||||
{
|
||||
elementType = query.FirstOrDefault().GetType();
|
||||
var firstElement = query.Cast<object>().FirstOrDefault(i => i != null);
|
||||
if (firstElement != null)
|
||||
{
|
||||
elementType = firstElement.GetType();
|
||||
}
|
||||
}
|
||||
|
||||
if (elementType != null)
|
||||
@@ -1218,7 +1229,7 @@ namespace Radzen
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedItems = selectedItems.AsQueryable().Where(DynamicLinqCustomTypeProvider.ParsingConfig, $@"!object.Equals(it.{ValueProperty},@0)", value).ToHashSet(ItemComparer);
|
||||
selectedItems = selectedItems.AsQueryable().Where(i => !object.Equals(GetItemOrValueFromProperty(i, ValueProperty), value)).ToHashSet(ItemComparer);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1249,7 +1260,16 @@ namespace Radzen
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectedItem = view.AsQueryable().Where(DynamicLinqCustomTypeProvider.ParsingConfig, $@"{ValueProperty} == @0", value).FirstOrDefault();
|
||||
SelectedItem = view.AsQueryable().Where(new FilterDescriptor[]
|
||||
{
|
||||
new FilterDescriptor()
|
||||
{
|
||||
Property = ValueProperty,
|
||||
FilterValue = value
|
||||
}
|
||||
},
|
||||
LogicalFilterOperator.And,
|
||||
FilterCaseSensitivity.Default).FirstOrDefault();
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1266,7 +1286,7 @@ namespace Radzen
|
||||
{
|
||||
if (!string.IsNullOrEmpty(ValueProperty))
|
||||
{
|
||||
foreach (object v in values.ToDynamicList())
|
||||
foreach (object v in values.Cast<dynamic>().ToList())
|
||||
{
|
||||
dynamic item;
|
||||
|
||||
@@ -1276,10 +1296,19 @@ namespace Radzen
|
||||
}
|
||||
else
|
||||
{
|
||||
item = view.AsQueryable().Where(DynamicLinqCustomTypeProvider.ParsingConfig, $@"{ValueProperty} == @0", v).FirstOrDefault();
|
||||
item = view.AsQueryable().Where(new FilterDescriptor[]
|
||||
{
|
||||
new FilterDescriptor()
|
||||
{
|
||||
Property = ValueProperty,
|
||||
FilterValue = v
|
||||
}
|
||||
},
|
||||
LogicalFilterOperator.And,
|
||||
FilterCaseSensitivity.Default).FirstOrDefault();
|
||||
}
|
||||
|
||||
if (!object.Equals(item, null) && !selectedItems.AsQueryable().Where(DynamicLinqCustomTypeProvider.ParsingConfig, $@"object.Equals(it.{ValueProperty},@0)", v).Any())
|
||||
if (!object.Equals(item, null) && !selectedItems.AsQueryable().Where(i => object.Equals(GetItemOrValueFromProperty(i, ValueProperty), v)).Any())
|
||||
{
|
||||
selectedItems.Add(item);
|
||||
}
|
||||
|
||||
753
Radzen.Blazor/DynamicExtensions.cs
Normal file
753
Radzen.Blazor/DynamicExtensions.cs
Normal file
@@ -0,0 +1,753 @@
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Radzen;
|
||||
using Radzen.Blazor;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Common;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Reflection.Metadata;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.Loader;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace System.Linq.Dynamic.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Class DynamicExtensions used to replace System.Linq.Dynamic.Core library.
|
||||
/// </summary>
|
||||
public static class DynamicExtensions
|
||||
{
|
||||
static string rtPath = Path.GetDirectoryName(typeof(object).Assembly.Location);
|
||||
|
||||
static CSharpCompilation Compilation = CSharpCompilation.Create(Guid.NewGuid().ToString())
|
||||
.WithOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
|
||||
.WithOptimizationLevel(OptimizationLevel.Debug))
|
||||
.AddReferences(MetadataReference.CreateFromFile(Path.Combine(rtPath, "System.Runtime.dll")))
|
||||
.AddReferences(MetadataReference.CreateFromFile(Path.Combine(rtPath, "System.Collections.dll")))
|
||||
.AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location))
|
||||
.AddReferences(MetadataReference.CreateFromFile(typeof(Expression).Assembly.Location))
|
||||
.AddReferences(MetadataReference.CreateFromFile(typeof(Queryable).Assembly.Location))
|
||||
.AddReferences(MetadataReference.CreateFromFile(typeof(Enumerable).Assembly.Location));
|
||||
private static Assembly Compile(CSharpCompilation compilation, string code, AssemblyLoadContext context)
|
||||
{
|
||||
var errors = compilation.GetDiagnostics().Where(d => d.Severity == DiagnosticSeverity.Error);
|
||||
|
||||
if (errors.Any())
|
||||
{
|
||||
var message = string.Join(Environment.NewLine, errors.Select(e => e.GetMessage()));
|
||||
|
||||
throw new InvalidOperationException($"Compilation of {code} failed: {message}");
|
||||
}
|
||||
|
||||
using var projectStream = new MemoryStream();
|
||||
|
||||
var result = compilation.Emit(projectStream);
|
||||
|
||||
if (!result.Success)
|
||||
{
|
||||
errors = result.Diagnostics.Where(d => d.Severity == DiagnosticSeverity.Error);
|
||||
|
||||
var message = string.Join(Environment.NewLine, errors.Select(e => e.GetMessage()));
|
||||
|
||||
throw new InvalidOperationException(message);
|
||||
}
|
||||
|
||||
projectStream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
return context.LoadFromStream(projectStream);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Filters using the specified filter descriptors.
|
||||
/// </summary>
|
||||
public static IQueryable<T> Where<T>(
|
||||
this IQueryable<T> source,
|
||||
string selector,
|
||||
object[] parameters = null, object[] otherParameters = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (parameters != null)
|
||||
{
|
||||
for (var i = 0; i < parameters.Length; i++)
|
||||
{
|
||||
var value = object.Equals(parameters[i], string.Empty) ? @"""""" :
|
||||
parameters[i] == null ? @"null" :
|
||||
parameters[i] is string ? @$"""{parameters[i].ToString().Replace("\"", "\\\"")}""" :
|
||||
parameters[i] is bool ? $"{parameters[i]}".ToLower() : parameters[i];
|
||||
|
||||
selector = selector.Replace($"@{i}", $"{value}");
|
||||
}
|
||||
}
|
||||
|
||||
var code = $@"
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
namespace Dynamic;
|
||||
public static class Linq
|
||||
{{
|
||||
public static Expression<Func<{typeof(T).FullName.Replace("+", ".")}, bool>> where = {(selector == "true" ? "i => true" : selector).Replace("DateTime", "DateTime.Parse").Replace("DateTimeOffset", "DateTimeOffset.Parse").Replace("DateOnly", "DateOnly.Parse").Replace("Guid", "Guid.Parse").Replace(" = "," == ")};
|
||||
}}";
|
||||
|
||||
var assembly = Compile(Compilation
|
||||
.AddReferences(MetadataReference.CreateFromFile(typeof(T).Assembly.Location))
|
||||
.AddSyntaxTrees(CSharpSyntaxTree.ParseText(code, new CSharpParseOptions(LanguageVersion.Latest))),
|
||||
code, new AssemblyLoadContext("RadzenALC", true));
|
||||
|
||||
Expression<Func<T, bool>> whereMethod = (Expression<Func<T, bool>>)assembly
|
||||
.GetType("Dynamic.Linq").GetFields().FirstOrDefault().GetValue(null);
|
||||
|
||||
return source.Where(whereMethod);
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new InvalidOperationException($"Invalid Where selector");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sorts the elements of a sequence in ascending or descending order according to a key.
|
||||
/// </summary>
|
||||
public static IQueryable<T> OrderBy<T>(
|
||||
this IQueryable<T> source,
|
||||
string selector,
|
||||
object[] parameters = null)
|
||||
{
|
||||
return Radzen.QueryableExtension.OrderBy(source, selector);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Projects each element of a sequence into a collection of property values.
|
||||
/// </summary>
|
||||
public static IQueryable Select<T>(
|
||||
this IQueryable<T> source,
|
||||
string selector,
|
||||
object[] parameters = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var parameter = Expression.Parameter(typeof(T), "it");
|
||||
|
||||
var className = $"Class{Guid.NewGuid()}".Replace("-", "");
|
||||
|
||||
var properties = selector.Replace("new (", "").Replace(")", "").Trim().Split(",", StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
var declaredProperties = string.Join(Environment.NewLine, properties
|
||||
.Select(s =>
|
||||
{
|
||||
var original = s.Split(" as ").FirstOrDefault().Trim();
|
||||
var property = QueryableExtension.GetNestedPropertyExpression(parameter, original);
|
||||
var name = s.Contains(" as ") ? s.Split(" as ").LastOrDefault().Trim() : s.Trim();
|
||||
return $@"public {property.Type.DisplayName(fullName: false)} {name} {{ get; set; }}";
|
||||
}));
|
||||
|
||||
selector = string.Join(", ", properties
|
||||
.Select(s => (s.Contains(" as ") ? s.Split(" as ").LastOrDefault().Trim() : s.Trim()) + " = " + $"it.{s.Split(" as ").FirstOrDefault().Replace(".", "?.").Trim()}"));
|
||||
|
||||
var code = $@"
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
namespace Dynamic;
|
||||
public class {className}
|
||||
{{
|
||||
{declaredProperties}
|
||||
}}
|
||||
public static class Linq
|
||||
{{
|
||||
public static IQueryable Select(IQueryable source)
|
||||
{{
|
||||
var list = System.Linq.Enumerable.ToList(System.Linq.Queryable.Cast<{typeof(T).FullName}>(source));
|
||||
return System.Linq.Queryable.AsQueryable(list.Select(it => new {className}() {{ {selector} }}));
|
||||
}}
|
||||
}}";
|
||||
|
||||
var assembly = Compile(Compilation
|
||||
.AddReferences(MetadataReference.CreateFromFile(typeof(T).Assembly.Location))
|
||||
.AddSyntaxTrees(CSharpSyntaxTree.ParseText(code, new CSharpParseOptions(LanguageVersion.Latest))),
|
||||
code, new AssemblyLoadContext("RadzenALC", true));
|
||||
|
||||
return (IQueryable)assembly.GetType("Dynamic.Linq").GetMethods().FirstOrDefault().Invoke(null, new object[] { source });
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new InvalidOperationException($"Invalid selector");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class SharedTypeExtensions
|
||||
{
|
||||
private static readonly Dictionary<Type, string> BuiltInTypeNames = new()
|
||||
{
|
||||
{ typeof(bool), "bool" },
|
||||
{ typeof(byte), "byte" },
|
||||
{ typeof(char), "char" },
|
||||
{ typeof(decimal), "decimal" },
|
||||
{ typeof(double), "double" },
|
||||
{ typeof(float), "float" },
|
||||
{ typeof(int), "int" },
|
||||
{ typeof(long), "long" },
|
||||
{ typeof(object), "object" },
|
||||
{ typeof(sbyte), "sbyte" },
|
||||
{ typeof(short), "short" },
|
||||
{ typeof(string), "string" },
|
||||
{ typeof(uint), "uint" },
|
||||
{ typeof(ulong), "ulong" },
|
||||
{ typeof(ushort), "ushort" },
|
||||
{ typeof(void), "void" }
|
||||
};
|
||||
|
||||
public static Type UnwrapNullableType(this Type type)
|
||||
=> Nullable.GetUnderlyingType(type) ?? type;
|
||||
|
||||
public static bool IsNullableValueType(this Type type)
|
||||
=> type.IsConstructedGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>);
|
||||
|
||||
public static bool IsNullableType(this Type type)
|
||||
=> !type.IsValueType || type.IsNullableValueType();
|
||||
|
||||
public static bool IsValidEntityType(this Type type)
|
||||
=> type.IsClass
|
||||
&& !type.IsArray;
|
||||
|
||||
public static bool IsPropertyBagType(this Type type)
|
||||
{
|
||||
if (type.IsGenericTypeDefinition)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var types = GetGenericTypeImplementations(type, typeof(IDictionary<,>));
|
||||
return types.Any(
|
||||
t => t.GetGenericArguments()[0] == typeof(string)
|
||||
&& t.GetGenericArguments()[1] == typeof(object));
|
||||
}
|
||||
|
||||
public static Type MakeNullable(this Type type, bool nullable = true)
|
||||
=> type.IsNullableType() == nullable
|
||||
? type
|
||||
: nullable
|
||||
? typeof(Nullable<>).MakeGenericType(type)
|
||||
: type.UnwrapNullableType();
|
||||
|
||||
public static bool IsNumeric(this Type type)
|
||||
{
|
||||
type = type.UnwrapNullableType();
|
||||
|
||||
return type.IsInteger()
|
||||
|| type == typeof(decimal)
|
||||
|| type == typeof(float)
|
||||
|| type == typeof(double);
|
||||
}
|
||||
|
||||
public static bool IsInteger(this Type type)
|
||||
{
|
||||
type = type.UnwrapNullableType();
|
||||
|
||||
return type == typeof(int)
|
||||
|| type == typeof(long)
|
||||
|| type == typeof(short)
|
||||
|| type == typeof(byte)
|
||||
|| type == typeof(uint)
|
||||
|| type == typeof(ulong)
|
||||
|| type == typeof(ushort)
|
||||
|| type == typeof(sbyte)
|
||||
|| type == typeof(char);
|
||||
}
|
||||
|
||||
public static bool IsSignedInteger(this Type type)
|
||||
=> type == typeof(int)
|
||||
|| type == typeof(long)
|
||||
|| type == typeof(short)
|
||||
|| type == typeof(sbyte);
|
||||
|
||||
public static bool IsAnonymousType(this Type type)
|
||||
=> type.Name.StartsWith("<>", StringComparison.Ordinal)
|
||||
&& type.GetCustomAttributes(typeof(CompilerGeneratedAttribute), inherit: false).Length > 0
|
||||
&& type.Name.Contains("AnonymousType");
|
||||
|
||||
public static PropertyInfo GetAnyProperty(this Type type, string name)
|
||||
{
|
||||
var props = type.GetRuntimeProperties().Where(p => p.Name == name).ToList();
|
||||
if (props.Count > 1)
|
||||
{
|
||||
throw new AmbiguousMatchException();
|
||||
}
|
||||
|
||||
return props.SingleOrDefault();
|
||||
}
|
||||
|
||||
public static bool IsInstantiable(this Type type)
|
||||
=> !type.IsAbstract
|
||||
&& !type.IsInterface
|
||||
&& (!type.IsGenericType || !type.IsGenericTypeDefinition);
|
||||
|
||||
public static Type UnwrapEnumType(this Type type)
|
||||
{
|
||||
var isNullable = type.IsNullableType();
|
||||
var underlyingNonNullableType = isNullable ? type.UnwrapNullableType() : type;
|
||||
if (!underlyingNonNullableType.IsEnum)
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
var underlyingEnumType = Enum.GetUnderlyingType(underlyingNonNullableType);
|
||||
return isNullable ? MakeNullable(underlyingEnumType) : underlyingEnumType;
|
||||
}
|
||||
|
||||
public static Type GetSequenceType(this Type type)
|
||||
{
|
||||
var sequenceType = TryGetSequenceType(type);
|
||||
if (sequenceType == null)
|
||||
{
|
||||
throw new ArgumentException($"The type {type.Name} does not represent a sequence");
|
||||
}
|
||||
|
||||
return sequenceType;
|
||||
}
|
||||
|
||||
public static Type TryGetSequenceType(this Type type)
|
||||
=> type.TryGetElementType(typeof(IEnumerable<>))
|
||||
?? type.TryGetElementType(typeof(IAsyncEnumerable<>));
|
||||
|
||||
public static Type TryGetElementType(this Type type, Type interfaceOrBaseType)
|
||||
{
|
||||
if (type.IsGenericTypeDefinition)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var types = GetGenericTypeImplementations(type, interfaceOrBaseType);
|
||||
|
||||
Type singleImplementation = null;
|
||||
foreach (var implementation in types)
|
||||
{
|
||||
if (singleImplementation == null)
|
||||
{
|
||||
singleImplementation = implementation;
|
||||
}
|
||||
else
|
||||
{
|
||||
singleImplementation = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return singleImplementation?.GenericTypeArguments.FirstOrDefault();
|
||||
}
|
||||
|
||||
public static bool IsCompatibleWith(this Type propertyType, Type fieldType)
|
||||
{
|
||||
if (propertyType.IsAssignableFrom(fieldType)
|
||||
|| fieldType.IsAssignableFrom(propertyType))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var propertyElementType = propertyType.TryGetSequenceType();
|
||||
var fieldElementType = fieldType.TryGetSequenceType();
|
||||
|
||||
return propertyElementType != null
|
||||
&& fieldElementType != null
|
||||
&& IsCompatibleWith(propertyElementType, fieldElementType);
|
||||
}
|
||||
|
||||
public static IEnumerable<Type> GetGenericTypeImplementations(this Type type, Type interfaceOrBaseType)
|
||||
{
|
||||
var typeInfo = type.GetTypeInfo();
|
||||
if (!typeInfo.IsGenericTypeDefinition)
|
||||
{
|
||||
var baseTypes = interfaceOrBaseType.GetTypeInfo().IsInterface
|
||||
? typeInfo.ImplementedInterfaces
|
||||
: type.GetBaseTypes();
|
||||
foreach (var baseType in baseTypes)
|
||||
{
|
||||
if (baseType.IsGenericType
|
||||
&& baseType.GetGenericTypeDefinition() == interfaceOrBaseType)
|
||||
{
|
||||
yield return baseType;
|
||||
}
|
||||
}
|
||||
|
||||
if (type.IsGenericType
|
||||
&& type.GetGenericTypeDefinition() == interfaceOrBaseType)
|
||||
{
|
||||
yield return type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<Type> GetBaseTypes(this Type type)
|
||||
{
|
||||
var currentType = type.BaseType;
|
||||
|
||||
while (currentType != null)
|
||||
{
|
||||
yield return currentType;
|
||||
|
||||
currentType = currentType.BaseType;
|
||||
}
|
||||
}
|
||||
|
||||
public static List<Type> GetBaseTypesAndInterfacesInclusive(this Type type)
|
||||
{
|
||||
var baseTypes = new List<Type>();
|
||||
var typesToProcess = new Queue<Type>();
|
||||
typesToProcess.Enqueue(type);
|
||||
|
||||
while (typesToProcess.Count > 0)
|
||||
{
|
||||
type = typesToProcess.Dequeue();
|
||||
baseTypes.Add(type);
|
||||
|
||||
if (type.IsNullableValueType())
|
||||
{
|
||||
typesToProcess.Enqueue(Nullable.GetUnderlyingType(type)!);
|
||||
}
|
||||
|
||||
if (type.IsConstructedGenericType)
|
||||
{
|
||||
typesToProcess.Enqueue(type.GetGenericTypeDefinition());
|
||||
}
|
||||
|
||||
if (!type.IsGenericTypeDefinition
|
||||
&& !type.IsInterface)
|
||||
{
|
||||
if (type.BaseType != null)
|
||||
{
|
||||
typesToProcess.Enqueue(type.BaseType);
|
||||
}
|
||||
|
||||
foreach (var @interface in GetDeclaredInterfaces(type))
|
||||
{
|
||||
typesToProcess.Enqueue(@interface);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return baseTypes;
|
||||
}
|
||||
|
||||
public static IEnumerable<Type> GetTypesInHierarchy(this Type type)
|
||||
{
|
||||
var currentType = type;
|
||||
|
||||
while (currentType != null)
|
||||
{
|
||||
yield return currentType;
|
||||
|
||||
currentType = currentType.BaseType;
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<Type> GetDeclaredInterfaces(this Type type)
|
||||
{
|
||||
var interfaces = type.GetInterfaces();
|
||||
if (type.BaseType == typeof(object)
|
||||
|| type.BaseType == null)
|
||||
{
|
||||
return interfaces;
|
||||
}
|
||||
|
||||
return interfaces.Except(type.BaseType.GetInterfaces());
|
||||
}
|
||||
|
||||
public static ConstructorInfo GetDeclaredConstructor(this Type type, Type[] types)
|
||||
{
|
||||
types ??= Array.Empty<Type>();
|
||||
|
||||
return type.GetTypeInfo().DeclaredConstructors
|
||||
.SingleOrDefault(
|
||||
c => !c.IsStatic
|
||||
&& c.GetParameters().Select(p => p.ParameterType).SequenceEqual(types))!;
|
||||
}
|
||||
|
||||
public static IEnumerable<PropertyInfo> GetPropertiesInHierarchy(this Type type, string name)
|
||||
{
|
||||
var currentType = type;
|
||||
do
|
||||
{
|
||||
var typeInfo = currentType.GetTypeInfo();
|
||||
foreach (var propertyInfo in typeInfo.DeclaredProperties)
|
||||
{
|
||||
if (propertyInfo.Name.Equals(name, StringComparison.Ordinal)
|
||||
&& !(propertyInfo.GetMethod ?? propertyInfo.SetMethod)!.IsStatic)
|
||||
{
|
||||
yield return propertyInfo;
|
||||
}
|
||||
}
|
||||
|
||||
currentType = typeInfo.BaseType;
|
||||
}
|
||||
while (currentType != null);
|
||||
}
|
||||
|
||||
// Looking up the members through the whole hierarchy allows to find inherited private members.
|
||||
public static IEnumerable<MemberInfo> GetMembersInHierarchy(this Type type)
|
||||
{
|
||||
var currentType = type;
|
||||
|
||||
do
|
||||
{
|
||||
// Do the whole hierarchy for properties first since looking for fields is slower.
|
||||
foreach (var propertyInfo in currentType.GetRuntimeProperties().Where(pi => !(pi.GetMethod ?? pi.SetMethod)!.IsStatic))
|
||||
{
|
||||
yield return propertyInfo;
|
||||
}
|
||||
|
||||
foreach (var fieldInfo in currentType.GetRuntimeFields().Where(f => !f.IsStatic))
|
||||
{
|
||||
yield return fieldInfo;
|
||||
}
|
||||
|
||||
currentType = currentType.BaseType;
|
||||
}
|
||||
while (currentType != null);
|
||||
}
|
||||
|
||||
public static IEnumerable<MemberInfo> GetMembersInHierarchy(this Type type, string name)
|
||||
=> type.GetMembersInHierarchy().Where(m => m.Name == name);
|
||||
|
||||
private static readonly Dictionary<Type, object> CommonTypeDictionary = new()
|
||||
{
|
||||
#pragma warning disable IDE0034 // Simplify 'default' expression - default causes default(object)
|
||||
{ typeof(int), default(int) },
|
||||
{ typeof(Guid), default(Guid) },
|
||||
{ typeof(DateOnly), default(DateOnly) },
|
||||
{ typeof(DateTime), default(DateTime) },
|
||||
{ typeof(DateTimeOffset), default(DateTimeOffset) },
|
||||
{ typeof(TimeOnly), default(TimeOnly) },
|
||||
{ typeof(long), default(long) },
|
||||
{ typeof(bool), default(bool) },
|
||||
{ typeof(double), default(double) },
|
||||
{ typeof(short), default(short) },
|
||||
{ typeof(float), default(float) },
|
||||
{ typeof(byte), default(byte) },
|
||||
{ typeof(char), default(char) },
|
||||
{ typeof(uint), default(uint) },
|
||||
{ typeof(ushort), default(ushort) },
|
||||
{ typeof(ulong), default(ulong) },
|
||||
{ typeof(sbyte), default(sbyte) }
|
||||
#pragma warning restore IDE0034 // Simplify 'default' expression
|
||||
};
|
||||
|
||||
public static object GetDefaultValue(this Type type)
|
||||
{
|
||||
if (!type.IsValueType)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// A bit of perf code to avoid calling Activator.CreateInstance for common types and
|
||||
// to avoid boxing on every call. This is about 50% faster than just calling CreateInstance
|
||||
// for all value types.
|
||||
return CommonTypeDictionary.TryGetValue(type, out var value)
|
||||
? value
|
||||
: Activator.CreateInstance(type);
|
||||
}
|
||||
|
||||
public static IEnumerable<Reflection.TypeInfo> GetConstructibleTypes(this Assembly assembly)
|
||||
=> assembly.GetLoadableDefinedTypes().Where(
|
||||
t => !t.IsAbstract
|
||||
&& !t.IsGenericTypeDefinition);
|
||||
|
||||
public static IEnumerable<Reflection.TypeInfo> GetLoadableDefinedTypes(this Assembly assembly)
|
||||
{
|
||||
try
|
||||
{
|
||||
return assembly.DefinedTypes;
|
||||
}
|
||||
catch (ReflectionTypeLoadException ex)
|
||||
{
|
||||
return ex.Types.Where(t => t != null).Select(IntrospectionExtensions.GetTypeInfo!);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
|
||||
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
|
||||
/// any release. You should only use it directly in your code with extreme caution and knowing that
|
||||
/// doing so can result in application failures when updating to a new Entity Framework Core release.
|
||||
/// </summary>
|
||||
public static string DisplayName(this Type type, bool fullName = true, bool compilable = false)
|
||||
{
|
||||
var stringBuilder = new StringBuilder();
|
||||
ProcessType(stringBuilder, type, fullName, compilable);
|
||||
return stringBuilder.ToString();
|
||||
}
|
||||
|
||||
private static void ProcessType(StringBuilder builder, Type type, bool fullName, bool compilable)
|
||||
{
|
||||
if (type.IsGenericType)
|
||||
{
|
||||
var genericArguments = type.GetGenericArguments();
|
||||
ProcessGenericType(builder, type, genericArguments, genericArguments.Length, fullName, compilable);
|
||||
}
|
||||
else if (type.IsArray)
|
||||
{
|
||||
ProcessArrayType(builder, type, fullName, compilable);
|
||||
}
|
||||
else if (BuiltInTypeNames.TryGetValue(type, out var builtInName))
|
||||
{
|
||||
builder.Append(builtInName);
|
||||
}
|
||||
else if (!type.IsGenericParameter)
|
||||
{
|
||||
if (compilable)
|
||||
{
|
||||
if (type.IsNested)
|
||||
{
|
||||
ProcessType(builder, type.DeclaringType!, fullName, compilable);
|
||||
builder.Append('.');
|
||||
}
|
||||
else if (fullName)
|
||||
{
|
||||
builder.Append(type.Namespace).Append('.');
|
||||
}
|
||||
|
||||
builder.Append(type.Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.Append(fullName ? type.FullName : type.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void ProcessArrayType(StringBuilder builder, Type type, bool fullName, bool compilable)
|
||||
{
|
||||
var innerType = type;
|
||||
while (innerType.IsArray)
|
||||
{
|
||||
innerType = innerType.GetElementType()!;
|
||||
}
|
||||
|
||||
ProcessType(builder, innerType, fullName, compilable);
|
||||
|
||||
while (type.IsArray)
|
||||
{
|
||||
builder.Append('[');
|
||||
builder.Append(',', type.GetArrayRank() - 1);
|
||||
builder.Append(']');
|
||||
type = type.GetElementType()!;
|
||||
}
|
||||
}
|
||||
|
||||
private static void ProcessGenericType(
|
||||
StringBuilder builder,
|
||||
Type type,
|
||||
Type[] genericArguments,
|
||||
int length,
|
||||
bool fullName,
|
||||
bool compilable)
|
||||
{
|
||||
if (type.IsConstructedGenericType
|
||||
&& type.GetGenericTypeDefinition() == typeof(Nullable<>))
|
||||
{
|
||||
ProcessType(builder, type.UnwrapNullableType(), fullName, compilable);
|
||||
builder.Append('?');
|
||||
return;
|
||||
}
|
||||
|
||||
var offset = type.IsNested ? type.DeclaringType!.GetGenericArguments().Length : 0;
|
||||
|
||||
if (compilable)
|
||||
{
|
||||
if (type.IsNested)
|
||||
{
|
||||
ProcessType(builder, type.DeclaringType!, fullName, compilable);
|
||||
builder.Append('.');
|
||||
}
|
||||
else if (fullName)
|
||||
{
|
||||
builder.Append(type.Namespace);
|
||||
builder.Append('.');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fullName)
|
||||
{
|
||||
if (type.IsNested)
|
||||
{
|
||||
ProcessGenericType(builder, type.DeclaringType!, genericArguments, offset, fullName, compilable);
|
||||
builder.Append('+');
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.Append(type.Namespace);
|
||||
builder.Append('.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var genericPartIndex = type.Name.IndexOf('`');
|
||||
if (genericPartIndex <= 0)
|
||||
{
|
||||
builder.Append(type.Name);
|
||||
return;
|
||||
}
|
||||
|
||||
builder.Append(type.Name, 0, genericPartIndex);
|
||||
builder.Append('<');
|
||||
|
||||
for (var i = offset; i < length; i++)
|
||||
{
|
||||
ProcessType(builder, genericArguments[i], fullName, compilable);
|
||||
if (i + 1 == length)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
builder.Append(',');
|
||||
if (!genericArguments[i + 1].IsGenericParameter)
|
||||
{
|
||||
builder.Append(' ');
|
||||
}
|
||||
}
|
||||
|
||||
builder.Append('>');
|
||||
}
|
||||
|
||||
public static IEnumerable<string> GetNamespaces(this Type type)
|
||||
{
|
||||
if (BuiltInTypeNames.ContainsKey(type))
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
yield return type.Namespace!;
|
||||
|
||||
if (type.IsGenericType)
|
||||
{
|
||||
foreach (var typeArgument in type.GenericTypeArguments)
|
||||
{
|
||||
foreach (var ns in typeArgument.GetNamespaces())
|
||||
{
|
||||
yield return ns;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static ConstantExpression GetDefaultValueConstant(this Type type)
|
||||
=> (ConstantExpression)GenerateDefaultValueConstantMethod
|
||||
.MakeGenericMethod(type).Invoke(null, Array.Empty<object>())!;
|
||||
|
||||
private static readonly MethodInfo GenerateDefaultValueConstantMethod =
|
||||
typeof(SharedTypeExtensions).GetTypeInfo().GetDeclaredMethod(nameof(GenerateDefaultValueConstant))!;
|
||||
|
||||
private static ConstantExpression GenerateDefaultValueConstant<TDefault>()
|
||||
=> Expression.Constant(default(TDefault), typeof(TDefault));
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Dynamic.Core;
|
||||
using System.Linq.Dynamic.Core.CustomTypeProviders;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
class DynamicLinqCustomTypeProvider : IDynamicLinkCustomTypeProvider
|
||||
{
|
||||
static readonly HashSet<Type> empty = [];
|
||||
public HashSet<Type> GetCustomTypes() => empty;
|
||||
public Dictionary<Type, List<MethodInfo>> GetExtensionMethods() => throw new NotSupportedException();
|
||||
public Type ResolveType(string typeName) => throw new NotSupportedException();
|
||||
public Type ResolveTypeBySimpleName(string simpleTypeName) => throw new NotSupportedException();
|
||||
public static ParsingConfig ParsingConfig = new() { CustomTypeProvider = new DynamicLinqCustomTypeProvider() };
|
||||
}
|
||||
}
|
||||
@@ -77,6 +77,12 @@ namespace Radzen.Blazor
|
||||
/// <param name="appointments">The appointments for this range.</param>
|
||||
Task SelectMonth(DateTime monthStart, IEnumerable<AppointmentData> appointments);
|
||||
/// <summary>
|
||||
/// Selects the specified day.
|
||||
/// </summary>
|
||||
/// <param name="day">The selected day.</param>
|
||||
/// <param name="appointments">The appointments for this range.</param>
|
||||
Task SelectDay(DateTime day, IEnumerable<AppointmentData> appointments);
|
||||
/// <summary>
|
||||
/// Selects the specified more link.
|
||||
/// </summary>
|
||||
/// <param name="start">The start.</param>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2018-2024 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
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace Radzen.Blazor
|
||||
|
||||
protected virtual double CalculateTickCount(int distance)
|
||||
{
|
||||
return Math.Ceiling(Math.Abs(Output.End - Output.Start) / distance);
|
||||
return Math.Max(1, Math.Ceiling(Math.Abs(Output.End - Output.Start) / distance));
|
||||
}
|
||||
|
||||
public override (double Start, double End, double Step) Ticks(int distance)
|
||||
|
||||
@@ -3,5 +3,4 @@
|
||||
<assembly fullname="System.Core">
|
||||
<type fullname="System.Linq.Queryable" preserve="all" />
|
||||
</assembly>
|
||||
<assembly fullname="System.Linq.Dynamic.Core" />
|
||||
</linker>
|
||||
@@ -8,7 +8,7 @@ using System.Text;
|
||||
namespace Radzen
|
||||
{
|
||||
/// <summary>
|
||||
/// Class NotificationService. Contains various methods with options to open notifications.
|
||||
/// Class NotificationService. Contains various methods with options to open notifications.
|
||||
/// Should be added as scoped service in the application services and RadzenNotification should be added in application main layout.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
@@ -50,6 +50,20 @@ namespace Radzen
|
||||
/// <param name="detail">The detail.</param>
|
||||
/// <param name="duration">The duration.</param>
|
||||
/// <param name="click">The click event.</param>
|
||||
public void Notify(NotificationSeverity severity, string summary,
|
||||
string detail, TimeSpan duration, Action<NotificationMessage> click = null)
|
||||
{
|
||||
Notify(severity, summary, detail, duration.TotalMilliseconds, click);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Notifies the specified severity.
|
||||
/// </summary>
|
||||
/// <param name="severity">The severity.</param>
|
||||
/// <param name="summary">The summary.</param>
|
||||
/// <param name="detail">The detail.</param>
|
||||
/// <param name="duration">The duration, default of 3 seconds.</param>
|
||||
/// <param name="click">The click event.</param>
|
||||
/// <param name="closeOnClick">If true, then the notification will be closed when clicked on.</param>
|
||||
/// <param name="payload">Used to store a custom payload that can be retreived later in the click event handler.</param>
|
||||
/// <param name="close">Action to be executed on close.</param>
|
||||
@@ -108,7 +122,7 @@ namespace Radzen
|
||||
/// Gets or sets the click event.
|
||||
/// </summary>
|
||||
/// <value>This event handler is called when the notification is clicked on.</value>
|
||||
public Action<NotificationMessage> Click { get; set; }
|
||||
public Action<NotificationMessage> Click { get; set; }
|
||||
/// <summary>
|
||||
/// Get or set the event for when the notification is closed
|
||||
/// </summary>
|
||||
@@ -146,12 +160,12 @@ namespace Radzen
|
||||
public bool Equals(NotificationMessage other)
|
||||
{
|
||||
if(other == null) return false;
|
||||
|
||||
|
||||
if(object.ReferenceEquals(this, other)) return true;
|
||||
|
||||
return this.Severity == other.Severity
|
||||
&& this.Summary == other.Summary
|
||||
&& this.Detail == other.Detail
|
||||
return this.Severity == other.Severity
|
||||
&& this.Summary == other.Summary
|
||||
&& this.Detail == other.Detail
|
||||
&& this.Duration == other.Duration
|
||||
&& this.Style == other.Style
|
||||
&& this.Click == other.Click
|
||||
|
||||
@@ -2,7 +2,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using System.Linq.Dynamic.Core;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Radzen.Blazor;
|
||||
@@ -354,18 +353,18 @@ namespace Radzen
|
||||
/// Called when [parameters set asynchronous].
|
||||
/// </summary>
|
||||
/// <returns>Task.</returns>
|
||||
protected override Task OnParametersSetAsync()
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
if (Visible && !LoadData.HasDelegate)
|
||||
{
|
||||
InvokeAsync(Reload);
|
||||
await InvokeAsync(Reload);
|
||||
}
|
||||
else
|
||||
{
|
||||
CalculatePager();
|
||||
}
|
||||
|
||||
return base.OnParametersSetAsync();
|
||||
await base.OnParametersSetAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -10,7 +10,7 @@
|
||||
<IsPackable>true</IsPackable>
|
||||
<PackageId>Radzen.Blazor</PackageId>
|
||||
<Product>Radzen.Blazor</Product>
|
||||
<Version>5.7.2</Version>
|
||||
<Version>6.0.3</Version>
|
||||
<Copyright>Radzen Ltd.</Copyright>
|
||||
<Authors>Radzen Ltd.</Authors>
|
||||
<Description>Radzen Blazor is a set of 90+ free native Blazor UI controls packed with DataGrid, Scheduler, Charts and robust theming including Material design and Fluent UI.</Description>
|
||||
@@ -24,7 +24,8 @@
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DartSassBuilder" Version="1.0.0" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.8.0" />
|
||||
<PackageReference Include="DartSassBuilder" Version="1.1.0" PrivateAssets="All" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components" Condition="'$(TargetFramework)' == 'net6.0'" Version="6.0.25" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Condition="'$(TargetFramework)' == 'net6.0'" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components" Condition="'$(TargetFramework)' == 'net7.0'" Version="7.0.14" />
|
||||
@@ -33,7 +34,6 @@
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Condition="'$(TargetFramework)' == 'net8.0'" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components" Condition="'$(TargetFramework)' == 'net9.0'" Version="9.*-*" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Condition="'$(TargetFramework)' == 'net9.0'" Version="9.*-*" />
|
||||
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.3.7" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -180,7 +180,7 @@ namespace Radzen.Blazor
|
||||
await Expand.InvokeAsync(itemIndex);
|
||||
}
|
||||
|
||||
item.SetSelected(value ?? !selected);
|
||||
await item.SetSelected(value ?? !selected);
|
||||
|
||||
if (!Multiple)
|
||||
{
|
||||
@@ -198,7 +198,7 @@ namespace Radzen.Blazor
|
||||
{
|
||||
if (i.GetSelected())
|
||||
{
|
||||
i.SetSelected(false);
|
||||
await i.SetSelected(false);
|
||||
await Collapse.InvokeAsync(items.IndexOf(i));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,24 @@ namespace Radzen.Blazor
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if selected; otherwise, <c>false</c>.</value>
|
||||
[Parameter]
|
||||
public bool Selected { get; set; }
|
||||
public bool Selected
|
||||
{
|
||||
get
|
||||
{
|
||||
return selected != null ? selected.Value : false;
|
||||
}
|
||||
set
|
||||
{
|
||||
selected = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value changed.
|
||||
/// </summary>
|
||||
/// <value>The value changed.</value>
|
||||
[Parameter]
|
||||
public EventCallback<bool> SelectedChanged { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this <see cref="RadzenAccordionItem"/> is disabled.
|
||||
@@ -139,9 +156,11 @@ namespace Radzen.Blazor
|
||||
return selected ?? Selected;
|
||||
}
|
||||
|
||||
internal void SetSelected(bool? value)
|
||||
internal async Task SetSelected(bool? value)
|
||||
{
|
||||
selected = value;
|
||||
|
||||
await SelectedChanged.InvokeAsync(Selected);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -151,12 +170,19 @@ namespace Radzen.Blazor
|
||||
/// <returns>A Task representing the asynchronous operation.</returns>
|
||||
public override async Task SetParametersAsync(ParameterView parameters)
|
||||
{
|
||||
bool shouldRefresh = false;
|
||||
if (parameters.DidParameterChange(nameof(Selected), Selected))
|
||||
{
|
||||
Accordion?.SelectItem(this, parameters.GetValueOrDefault<bool>(nameof(Selected)));
|
||||
selected = parameters.GetValueOrDefault<bool>(nameof(Selected));
|
||||
shouldRefresh = true;
|
||||
}
|
||||
|
||||
await base.SetParametersAsync(parameters);
|
||||
|
||||
if (shouldRefresh)
|
||||
{
|
||||
Accordion.Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
}
|
||||
<div id="@PopupID" class="rz-autocomplete-panel" style="@PopupStyle">
|
||||
<ul @ref="@list" class="rz-autocomplete-items rz-autocomplete-list" role="listbox">
|
||||
@if (!string.IsNullOrEmpty(searchText) || !string.IsNullOrEmpty(customSearchText))
|
||||
@if (OpenOnFocus || (!string.IsNullOrEmpty(searchText) || !string.IsNullOrEmpty(customSearchText)))
|
||||
{
|
||||
@foreach (var item in LoadData.HasDelegate ? Data != null ? Data : Enumerable.Empty<object>() : (View != null ? View : Enumerable.Empty<object>()))
|
||||
{
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using Radzen;
|
||||
using Radzen.Blazor.Rendering;
|
||||
using System.Collections;
|
||||
using System.Linq.Dynamic.Core;
|
||||
using Microsoft.AspNetCore.Components.Forms;
|
||||
using Microsoft.JSInterop;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
@@ -23,6 +22,35 @@ namespace Radzen.Blazor
|
||||
/// </example>
|
||||
public partial class RadzenAutoComplete : DataBoundFormComponent<string>
|
||||
{
|
||||
object selectedItem = null;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the selected item.
|
||||
/// </summary>
|
||||
/// <value>The selected item.</value>
|
||||
[Parameter]
|
||||
public object SelectedItem
|
||||
{
|
||||
get
|
||||
{
|
||||
return selectedItem;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (selectedItem != value)
|
||||
{
|
||||
selectedItem = object.Equals(value, "null") ? null : value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the selected item changed.
|
||||
/// </summary>
|
||||
/// <value>The selected item changed.</value>
|
||||
[Parameter]
|
||||
public EventCallback<object> SelectedItemChanged { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies additional custom attributes that will be rendered by the input.
|
||||
/// </summary>
|
||||
@@ -153,8 +181,8 @@ namespace Radzen.Blazor
|
||||
var value = await JSRuntime.InvokeAsync<string>("Radzen.getInputValue", search);
|
||||
|
||||
value = $"{value}";
|
||||
|
||||
if (value.Length < MinLength)
|
||||
|
||||
if (value.Length < MinLength && !OpenOnFocus)
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.closePopup", PopupID);
|
||||
return;
|
||||
@@ -195,7 +223,7 @@ namespace Radzen.Blazor
|
||||
{
|
||||
get
|
||||
{
|
||||
return Data != null && !string.IsNullOrEmpty(searchText) ? Data.AsQueryable() : null;
|
||||
return Data != null && (OpenOnFocus || !string.IsNullOrEmpty(searchText)) ? Data.AsQueryable() : null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,12 +237,7 @@ namespace Radzen.Blazor
|
||||
{
|
||||
if (Query != null)
|
||||
{
|
||||
string filterCaseSensitivityOperator = FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ? ".ToLower()" : "";
|
||||
|
||||
string textProperty = string.IsNullOrEmpty(TextProperty) ? string.Empty : $".{TextProperty}";
|
||||
|
||||
return Query.Where(DynamicLinqCustomTypeProvider.ParsingConfig, $"o=>o{textProperty}{filterCaseSensitivityOperator}.{Enum.GetName(typeof(StringFilterOperator), FilterOperator)}(@0)",
|
||||
FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ? searchText.ToLower() : searchText);
|
||||
return Query.Where(TextProperty, searchText, FilterOperator, FilterCaseSensitivity);
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -232,6 +255,8 @@ namespace Radzen.Blazor
|
||||
await ValueChanged.InvokeAsync($"{Value}");
|
||||
if (FieldIdentifier.FieldName != null) { EditContext?.NotifyFieldChanged(FieldIdentifier); }
|
||||
await Change.InvokeAsync(Value);
|
||||
|
||||
await SelectedItemChanged.InvokeAsync(null);
|
||||
}
|
||||
|
||||
async System.Threading.Tasks.Task SelectItem(object item)
|
||||
@@ -249,6 +274,8 @@ namespace Radzen.Blazor
|
||||
if (FieldIdentifier.FieldName != null) { EditContext?.NotifyFieldChanged(FieldIdentifier); }
|
||||
await Change.InvokeAsync(Value);
|
||||
|
||||
await SelectedItemChanged.InvokeAsync(item);
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
@@ -307,8 +334,22 @@ namespace Radzen.Blazor
|
||||
shouldClose = !visible;
|
||||
}
|
||||
|
||||
if (parameters.DidParameterChange(nameof(SelectedItem), SelectedItem))
|
||||
{
|
||||
var item = parameters.GetValueOrDefault<object>(nameof(SelectedItem));
|
||||
if (item != null)
|
||||
{
|
||||
await SelectItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
await base.SetParametersAsync(parameters);
|
||||
|
||||
if (parameters.DidParameterChange(nameof(Value), Value))
|
||||
{
|
||||
Value = parameters.GetValueOrDefault<object>(nameof(Value));
|
||||
}
|
||||
|
||||
if (shouldClose && !firstRender)
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.destroyPopup", PopupID);
|
||||
|
||||
@@ -276,6 +276,13 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public string IsNotEmptyText { get; set; } = "Is not empty";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the custom filter operator text.
|
||||
/// </summary>
|
||||
/// <value>The custom filter operator text.</value>
|
||||
[Parameter]
|
||||
public string CustomText { get; set; } = "Custom";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the columns can be filtered.
|
||||
/// </summary>
|
||||
|
||||
@@ -119,6 +119,8 @@ else
|
||||
}
|
||||
|
||||
Filter.Property = property.Property;
|
||||
Filter.FilterProperty = property.FilterProperty;
|
||||
Filter.Type = property.FilterPropertyType;
|
||||
|
||||
if (Filter.FilterOperator == null)
|
||||
{
|
||||
|
||||
@@ -3,10 +3,7 @@ using Microsoft.JSInterop;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Common;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Linq.Dynamic.Core;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
@@ -347,6 +344,8 @@ namespace Radzen.Blazor
|
||||
{
|
||||
switch (filterOperator)
|
||||
{
|
||||
case FilterOperator.Custom:
|
||||
return DataFilter?.CustomText;
|
||||
case FilterOperator.Contains:
|
||||
return DataFilter?.ContainsText;
|
||||
case FilterOperator.DoesNotContain:
|
||||
|
||||
@@ -168,202 +168,9 @@
|
||||
{
|
||||
var filterMode = column.FilterMode ?? FilterMode;
|
||||
<th colspan="@column.GetColSpan()" class="@($"rz-unselectable-text {getFrozenColumnClass(column, visibleColumns)} {column.HeaderCssClass}")" scope="col" style="@column.GetStyle(true, true)">
|
||||
@if (AllowFiltering && column.Filterable && column.Columns == null && (!string.IsNullOrEmpty(column.GetFilterProperty()) || column.FilterTemplate != null))
|
||||
@if (allColumns.All(c => c.Parent == null) && AllowFiltering && column.Filterable && column.Columns == null && (!string.IsNullOrEmpty(column.GetFilterProperty()) || column.FilterTemplate != null))
|
||||
{
|
||||
<div class="rz-cell-filter">
|
||||
<div class="rz-cell-filter-content">
|
||||
@if (column.FilterTemplate != null)
|
||||
{
|
||||
@column.FilterTemplate(column)
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="rz-cell-filter-label" style="height:35px; width:100%;" onclick="event.preventDefault()">
|
||||
@if (PropertyAccess.IsDate(column.FilterPropertyType))
|
||||
{
|
||||
if (filterMode == FilterMode.Simple)
|
||||
{
|
||||
<button aria-label="@FilterToggleAriaLabel" class="rz-button rz-button-md rz-button-icon-only rz-variant-flat rz-base rz-shade-default @(column.HasActiveFilter() ? "rz-grid-filter-active" : "")" onclick="@($"Radzen.togglePopup(this.parentNode, '{PopupID}{column.GetFilterProperty()}')")">
|
||||
<i class="notranslate rzi">date_range</i>
|
||||
</button>
|
||||
var filterValue = column.GetFilterValue();
|
||||
var filterOperator = column.GetFilterOperator();
|
||||
@if (filterValue != null && filters.Any(d => d.Property == column.GetFilterProperty()))
|
||||
{
|
||||
<span class="rz-current-filter">@string.Format("{0:" + getFilterDateFormat(column) + "}", filterValue)</span>
|
||||
<i @onclick="@((args) => ClearFilter(column))" class="notranslate rzi rz-cell-filter-clear">close</i>
|
||||
}
|
||||
else if ((filterOperator == FilterOperator.IsNull || filterOperator == FilterOperator.IsNotNull) && filters.Any(d => d.Property == column.GetFilterProperty()))
|
||||
{
|
||||
<span class="rz-current-filter">@column.GetFilterOperatorText(filterOperator)</span>
|
||||
<i @onclick="@((args) => ClearFilter(column))" class="notranslate rzi rz-cell-filter-clear">close</i>
|
||||
}
|
||||
<div id="@($"{PopupID}{column.GetFilterProperty()}")" class="rz-overlaypanel rz-grid-date-filter"
|
||||
style="display:none;" tabindex="0">
|
||||
<div class="rz-overlaypanel-content">
|
||||
|
||||
<div class="rz-date-filter">
|
||||
|
||||
<div class="rz-listbox rz-inputtext ">
|
||||
<div class="rz-listbox-list-wrapper">
|
||||
<ul class="rz-listbox-list">
|
||||
@if (column.GetFilterOperators().Contains(FilterOperator.Equals))
|
||||
{
|
||||
<li class="@(DateFilterOperatorStyle(column, FilterOperator.Equals))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.Equals))" style="display: block;">
|
||||
<span>@EqualsText</span>
|
||||
</li>
|
||||
}
|
||||
@if (column.GetFilterOperators().Contains(FilterOperator.NotEquals))
|
||||
{
|
||||
<li class="@(DateFilterOperatorStyle(column, FilterOperator.NotEquals))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.NotEquals))" style="display: block;">
|
||||
<span>@NotEqualsText</span>
|
||||
</li>
|
||||
}
|
||||
@if (column.GetFilterOperators().Contains(FilterOperator.LessThan))
|
||||
{
|
||||
<li class="@(DateFilterOperatorStyle(column, FilterOperator.LessThan))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.LessThan))" style="display: block;">
|
||||
<span>@LessThanText</span>
|
||||
</li>
|
||||
}
|
||||
@if (column.GetFilterOperators().Contains(FilterOperator.LessThanOrEquals))
|
||||
{
|
||||
<li class="@(DateFilterOperatorStyle(column, FilterOperator.LessThanOrEquals))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.LessThanOrEquals))" style="display: block;">
|
||||
<span>@LessThanOrEqualsText</span>
|
||||
</li>
|
||||
}
|
||||
@if (column.GetFilterOperators().Contains(FilterOperator.GreaterThan))
|
||||
{
|
||||
<li class="@(DateFilterOperatorStyle(column, FilterOperator.GreaterThan))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.GreaterThan))" style="display: block;">
|
||||
<span>@GreaterThanText</span>
|
||||
</li>
|
||||
}
|
||||
@if (column.GetFilterOperators().Contains(FilterOperator.GreaterThanOrEquals))
|
||||
{
|
||||
<li class="@(DateFilterOperatorStyle(column, FilterOperator.GreaterThanOrEquals))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.GreaterThanOrEquals))" style="display: block;">
|
||||
<span>@GreaterThanOrEqualsText</span>
|
||||
</li>
|
||||
}
|
||||
@if (column.GetFilterOperators().Contains(FilterOperator.IsEmpty))
|
||||
{
|
||||
<li class="@(DateFilterOperatorStyle(column, FilterOperator.IsEmpty))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.IsEmpty))" style="display: block;">
|
||||
<span>@IsEmptyText</span>
|
||||
</li>
|
||||
}
|
||||
@if (column.GetFilterOperators().Contains(FilterOperator.IsNotEmpty))
|
||||
{
|
||||
<li class="@(DateFilterOperatorStyle(column, FilterOperator.IsNotEmpty))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.IsNotEmpty))" style="display: block;">
|
||||
<span>@IsNotEmptyText</span>
|
||||
</li>
|
||||
}
|
||||
@if (column.GetFilterOperators().Contains(FilterOperator.IsNull))
|
||||
{
|
||||
<li class="@(DateFilterOperatorStyle(column, FilterOperator.IsNull))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.IsNull))" style="display: block;">
|
||||
<span>@IsNullText</span>
|
||||
</li>
|
||||
}
|
||||
@if (column.GetFilterOperators().Contains(FilterOperator.IsNotNull))
|
||||
{
|
||||
<li class="@(DateFilterOperatorStyle(column, FilterOperator.IsNotNull))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.IsNotNull))" style="display: block;">
|
||||
<span>@IsNotNullText</span>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<RadzenDatePicker TValue="@object" AllowInput=@(AllowFilterDateInput) InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", column.Title + FilterValueAriaLabel + column.GetFilterValue() }})"
|
||||
ShowTime="@column.ShowTimeForDateTimeFilter()" ShowTimeOkButton="false" Inline="true" DateFormat="@getFilterDateFormat(column)"
|
||||
Value="@column.GetFilterValue()" Change="@(args => { column.SetFilterValue(PropertyAccess.IsDateOnly(column.FilterPropertyType) ? PropertyAccess.DateOnlyFromDateTime(args.Value) : args.Value); SaveSettings(); })" />
|
||||
|
||||
</div>
|
||||
<div class="rz-grid-filter-buttons">
|
||||
<RadzenButton ButtonStyle="ButtonStyle.Base" class="rz-clear-filter" Click="@((args) => ClearFilter(column, true))" Text=@ClearFilterText title="@ClearFilterText" />
|
||||
<RadzenButton ButtonStyle="ButtonStyle.Primary" class="rz-apply-filter" Click="@((args) => ApplyFilter(column, true))" Text=@ApplyFilterText title="@ApplyFilterText" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<RadzenDataGridFilterMenu Grid="@this" Column="@column" />
|
||||
@if (column.FilterValueTemplate != null)
|
||||
{
|
||||
@column.FilterValueTemplate(column)
|
||||
}
|
||||
else
|
||||
{
|
||||
<RadzenDatePicker Disabled=@(!column.CanSetFilterValue()) TValue="@object" Style="width:100%" AllowInput=@(AllowFilterDateInput) AllowClear="true" InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", column.Title + FilterValueAriaLabel + column.GetFilterValue() }})"
|
||||
ShowTime="false" ShowTimeOkButton="false" DateFormat="@getFilterDateFormat(column)"
|
||||
Value="@column.GetFilterValue()" Change="@(args => { if(!args.HasValue) { InvokeAsync(() => ClearFilter(column, true)); } else {column.SetFilterValue(PropertyAccess.IsDateOnly(column.FilterPropertyType) ? PropertyAccess.DateOnlyFromDateTime(args.Value) : args.Value); InvokeAsync(() => ApplyFilter(column, true));} })" />
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (PropertyAccess.IsNullableEnum(column.FilterPropertyType) || PropertyAccess.IsEnum(column.FilterPropertyType))
|
||||
{
|
||||
@if (column.FilterValueTemplate != null)
|
||||
{
|
||||
@column.FilterValueTemplate(column)
|
||||
}
|
||||
else
|
||||
{
|
||||
<RadzenDropDown Style="width:100%" AllowClear="true" AllowFiltering="false" TValue="@object"
|
||||
Value=@column.GetFilterValue() Multiple="false" Placeholder="@EnumFilterSelectText" TextProperty="Text" ValueProperty="Value"
|
||||
Data=@((PropertyAccess.IsNullableEnum(column.FilterPropertyType) ? new object[]{ new { Value = Convert.ChangeType(-1, Enum.GetUnderlyingType(Nullable.GetUnderlyingType(column.FilterPropertyType) ?? column.FilterPropertyType)), Text = EnumNullFilterText}} : Enumerable.Empty<object>()).Concat(EnumExtensions.EnumAsKeyValuePair(Nullable.GetUnderlyingType(column.FilterPropertyType) ?? column.FilterPropertyType)))
|
||||
Change="@(args => {column.SetFilterValue(args);column.SetFilterOperator(object.Equals(args, -1) ? FilterOperator.IsNull : FilterOperator.Equals);InvokeAsync(() => ApplyFilter(column, true));})" />
|
||||
}
|
||||
}
|
||||
else if (PropertyAccess.IsNumeric(column.FilterPropertyType))
|
||||
{
|
||||
if (filterMode == FilterMode.SimpleWithMenu)
|
||||
{
|
||||
<RadzenDataGridFilterMenu Grid="@this" Column="@column" />
|
||||
}
|
||||
@if (column.FilterValueTemplate != null)
|
||||
{
|
||||
@column.FilterValueTemplate(column)
|
||||
}
|
||||
else
|
||||
{
|
||||
@(DrawNumericFilter(column))
|
||||
}
|
||||
}
|
||||
else if (column.FilterPropertyType == typeof(bool) || column.FilterPropertyType == typeof(bool?))
|
||||
{
|
||||
@if (column.FilterValueTemplate != null)
|
||||
{
|
||||
@column.FilterValueTemplate(column)
|
||||
}
|
||||
else
|
||||
{
|
||||
<div style="@(column.TextAlign == TextAlign.Center ? "width:100%;text-align:center" : column.TextAlign == TextAlign.Right ? "width:100%;text-align:right" : "")">
|
||||
<RadzenCheckBox TriState="true" TValue="@object" Value="@column.GetFilterValue()" Change="@((args) => OnFilter(new ChangeEventArgs() { Value = args }, column))" />
|
||||
</div>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (filterMode == FilterMode.SimpleWithMenu)
|
||||
{
|
||||
<RadzenDataGridFilterMenu Grid="@this" Column="@column" />
|
||||
}
|
||||
@if (column.FilterValueTemplate != null)
|
||||
{
|
||||
@column.FilterValueTemplate(column)
|
||||
}
|
||||
else
|
||||
{
|
||||
<input autocomplete="off" aria-label=@(column.Title + FilterValueAriaLabel + column.GetFilterValue()) disabled=@(!column.CanSetFilterValue()) id="@(getFilterInputId(column))" @onchange="@((args) => OnFilter(args, column))" @onkeydown="@((args) => OnFilterKeyPress(args, column))" value="@column.GetFilterValue()" type="text" placeholder="@column.GetFilterPlaceholder()" class="rz-textbox" style="width: 100%;" />
|
||||
@if (column.GetFilterValue() != null && filters.Any(d => d.Property == column.GetFilterProperty()))
|
||||
{
|
||||
<i @onclick="@((args) => ClearFilter(column))" class="notranslate rzi rz-cell-filter-clear" style="position:absolute;inset-inline-end:10px;">close</i>
|
||||
}
|
||||
}
|
||||
}
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
@RenderSimpleFilter(column, filterMode)
|
||||
}
|
||||
</th>
|
||||
}
|
||||
@@ -489,6 +296,212 @@
|
||||
}
|
||||
</CascadingValue>
|
||||
@code {
|
||||
internal RenderFragment RenderSimpleFilter(RadzenDataGridColumn<TItem> column, FilterMode filterMode)
|
||||
{
|
||||
return __builder =>
|
||||
{
|
||||
<text>
|
||||
@if (AllowFiltering && column.Filterable && column.Columns == null && (!string.IsNullOrEmpty(column.GetFilterProperty()) || column.FilterTemplate != null))
|
||||
{
|
||||
<div class="rz-cell-filter">
|
||||
<div class="rz-cell-filter-content">
|
||||
@if (column.FilterTemplate != null)
|
||||
{
|
||||
@column.FilterTemplate(column)
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="rz-cell-filter-label" style="height:35px; width:100%;" onclick="event.preventDefault()">
|
||||
@if (PropertyAccess.IsDate(column.FilterPropertyType))
|
||||
{
|
||||
if (filterMode == FilterMode.Simple)
|
||||
{
|
||||
<button aria-label="@FilterToggleAriaLabel" class="rz-button rz-button-md rz-button-icon-only rz-variant-flat rz-base rz-shade-default @(column.HasActiveFilter() ? "rz-grid-filter-active" : "")" onclick="@($"Radzen.togglePopup(this.parentNode, '{PopupID}{column.GetFilterProperty()}')")">
|
||||
<i class="notranslate rzi">date_range</i>
|
||||
</button>
|
||||
var filterValue = column.GetFilterValue();
|
||||
var filterOperator = column.GetFilterOperator();
|
||||
@if (filterValue != null && filters.Any(d => d.Property == column.GetFilterProperty()))
|
||||
{
|
||||
<span class="rz-current-filter">@string.Format("{0:" + getFilterDateFormat(column) + "}", filterValue)</span>
|
||||
<i @onclick="@((args) => ClearFilter(column))" class="notranslate rzi rz-cell-filter-clear">close</i>
|
||||
}
|
||||
else if ((filterOperator == FilterOperator.IsNull || filterOperator == FilterOperator.IsNotNull) && filters.Any(d => d.Property == column.GetFilterProperty()))
|
||||
{
|
||||
<span class="rz-current-filter">@column.GetFilterOperatorText(filterOperator)</span>
|
||||
<i @onclick="@((args) => ClearFilter(column))" class="notranslate rzi rz-cell-filter-clear">close</i>
|
||||
}
|
||||
<div id="@($"{PopupID}{column.GetFilterProperty()}")" class="rz-overlaypanel rz-grid-date-filter"
|
||||
style="display:none;" tabindex="0">
|
||||
<div class="rz-overlaypanel-content">
|
||||
|
||||
<div class="rz-date-filter">
|
||||
|
||||
<div class="rz-listbox rz-inputtext ">
|
||||
<div class="rz-listbox-list-wrapper">
|
||||
<ul class="rz-listbox-list">
|
||||
@if (column.GetFilterOperators().Contains(FilterOperator.Equals))
|
||||
{
|
||||
<li class="@(DateFilterOperatorStyle(column, FilterOperator.Equals))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.Equals))" style="display: block;">
|
||||
<span>@EqualsText</span>
|
||||
</li>
|
||||
}
|
||||
@if (column.GetFilterOperators().Contains(FilterOperator.NotEquals))
|
||||
{
|
||||
<li class="@(DateFilterOperatorStyle(column, FilterOperator.NotEquals))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.NotEquals))" style="display: block;">
|
||||
<span>@NotEqualsText</span>
|
||||
</li>
|
||||
}
|
||||
@if (column.GetFilterOperators().Contains(FilterOperator.LessThan))
|
||||
{
|
||||
<li class="@(DateFilterOperatorStyle(column, FilterOperator.LessThan))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.LessThan))" style="display: block;">
|
||||
<span>@LessThanText</span>
|
||||
</li>
|
||||
}
|
||||
@if (column.GetFilterOperators().Contains(FilterOperator.LessThanOrEquals))
|
||||
{
|
||||
<li class="@(DateFilterOperatorStyle(column, FilterOperator.LessThanOrEquals))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.LessThanOrEquals))" style="display: block;">
|
||||
<span>@LessThanOrEqualsText</span>
|
||||
</li>
|
||||
}
|
||||
@if (column.GetFilterOperators().Contains(FilterOperator.GreaterThan))
|
||||
{
|
||||
<li class="@(DateFilterOperatorStyle(column, FilterOperator.GreaterThan))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.GreaterThan))" style="display: block;">
|
||||
<span>@GreaterThanText</span>
|
||||
</li>
|
||||
}
|
||||
@if (column.GetFilterOperators().Contains(FilterOperator.GreaterThanOrEquals))
|
||||
{
|
||||
<li class="@(DateFilterOperatorStyle(column, FilterOperator.GreaterThanOrEquals))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.GreaterThanOrEquals))" style="display: block;">
|
||||
<span>@GreaterThanOrEqualsText</span>
|
||||
</li>
|
||||
}
|
||||
@if (column.GetFilterOperators().Contains(FilterOperator.IsEmpty))
|
||||
{
|
||||
<li class="@(DateFilterOperatorStyle(column, FilterOperator.IsEmpty))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.IsEmpty))" style="display: block;">
|
||||
<span>@IsEmptyText</span>
|
||||
</li>
|
||||
}
|
||||
@if (column.GetFilterOperators().Contains(FilterOperator.IsNotEmpty))
|
||||
{
|
||||
<li class="@(DateFilterOperatorStyle(column, FilterOperator.IsNotEmpty))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.IsNotEmpty))" style="display: block;">
|
||||
<span>@IsNotEmptyText</span>
|
||||
</li>
|
||||
}
|
||||
@if (column.GetFilterOperators().Contains(FilterOperator.IsNull))
|
||||
{
|
||||
<li class="@(DateFilterOperatorStyle(column, FilterOperator.IsNull))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.IsNull))" style="display: block;">
|
||||
<span>@IsNullText</span>
|
||||
</li>
|
||||
}
|
||||
@if (column.GetFilterOperators().Contains(FilterOperator.IsNotNull))
|
||||
{
|
||||
<li class="@(DateFilterOperatorStyle(column, FilterOperator.IsNotNull))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.IsNotNull))" style="display: block;">
|
||||
<span>@IsNotNullText</span>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<RadzenDatePicker TValue="@object" AllowInput=@(AllowFilterDateInput) InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", column.Title + FilterValueAriaLabel + column.GetFilterValue() }})"
|
||||
ShowTime="@column.ShowTimeForDateTimeFilter()" ShowTimeOkButton="false" Inline="true" DateFormat="@getFilterDateFormat(column)"
|
||||
Value="@column.GetFilterValue()" Change="@(args => { column.SetFilterValue(PropertyAccess.IsDateOnly(column.FilterPropertyType) ? PropertyAccess.DateOnlyFromDateTime(args.Value) : args.Value); SaveSettings(); })" />
|
||||
|
||||
</div>
|
||||
<div class="rz-grid-filter-buttons">
|
||||
<RadzenButton ButtonStyle="ButtonStyle.Base" class="rz-clear-filter" Click="@((args) => ClearFilter(column, true))" Text=@ClearFilterText title="@ClearFilterText" />
|
||||
<RadzenButton ButtonStyle="ButtonStyle.Primary" class="rz-apply-filter" Click="@((args) => ApplyFilter(column, true))" Text=@ApplyFilterText title="@ApplyFilterText" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<RadzenDataGridFilterMenu Grid="@this" Column="@column" />
|
||||
@if (column.FilterValueTemplate != null)
|
||||
{
|
||||
@column.FilterValueTemplate(column)
|
||||
}
|
||||
else
|
||||
{
|
||||
<RadzenDatePicker Disabled=@(!column.CanSetFilterValue()) TValue="@object" Style="width:100%" AllowInput=@(AllowFilterDateInput) AllowClear="true" InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", column.Title + FilterValueAriaLabel + column.GetFilterValue() }})"
|
||||
ShowTime="false" ShowTimeOkButton="false" DateFormat="@getFilterDateFormat(column)"
|
||||
Value="@column.GetFilterValue()" Change="@(args => { if(!args.HasValue) { InvokeAsync(() => ClearFilter(column, true)); } else {column.SetFilterValue(PropertyAccess.IsDateOnly(column.FilterPropertyType) ? PropertyAccess.DateOnlyFromDateTime(args.Value) : args.Value); InvokeAsync(() => ApplyFilter(column, true));} })" />
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (PropertyAccess.IsNullableEnum(column.FilterPropertyType) || PropertyAccess.IsEnum(column.FilterPropertyType))
|
||||
{
|
||||
@if (column.FilterValueTemplate != null)
|
||||
{
|
||||
@column.FilterValueTemplate(column)
|
||||
}
|
||||
else
|
||||
{
|
||||
<RadzenDropDown Style="width:100%" AllowClear="true" AllowFiltering="false" TValue="@object"
|
||||
Value=@column.GetFilterValue() Multiple="false" Placeholder="@EnumFilterSelectText" TextProperty="Text" ValueProperty="Value"
|
||||
Data=@((PropertyAccess.IsNullableEnum(column.FilterPropertyType) ? new object[]{ new { Value = Convert.ChangeType(-1, Enum.GetUnderlyingType(Nullable.GetUnderlyingType(column.FilterPropertyType) ?? column.FilterPropertyType)), Text = EnumNullFilterText}} : Enumerable.Empty<object>()).Concat(EnumExtensions.EnumAsKeyValuePair(Nullable.GetUnderlyingType(column.FilterPropertyType) ?? column.FilterPropertyType)))
|
||||
Change="@(args => {column.SetFilterValue(args);column.SetFilterOperator(object.Equals(args, -1) ? FilterOperator.IsNull : FilterOperator.Equals);InvokeAsync(() => ApplyFilter(column, true));})" />
|
||||
}
|
||||
}
|
||||
else if (PropertyAccess.IsNumeric(column.FilterPropertyType))
|
||||
{
|
||||
if (filterMode == FilterMode.SimpleWithMenu)
|
||||
{
|
||||
<RadzenDataGridFilterMenu Grid="@this" Column="@column" />
|
||||
}
|
||||
@if (column.FilterValueTemplate != null)
|
||||
{
|
||||
@column.FilterValueTemplate(column)
|
||||
}
|
||||
else
|
||||
{
|
||||
@(DrawNumericFilter(column))
|
||||
}
|
||||
}
|
||||
else if (column.FilterPropertyType == typeof(bool) || column.FilterPropertyType == typeof(bool?))
|
||||
{
|
||||
@if (column.FilterValueTemplate != null)
|
||||
{
|
||||
@column.FilterValueTemplate(column)
|
||||
}
|
||||
else
|
||||
{
|
||||
<div style="@(column.TextAlign == TextAlign.Center ? "width:100%;text-align:center" : column.TextAlign == TextAlign.Right ? "width:100%;text-align:right" : "")">
|
||||
<RadzenCheckBox TriState="true" TValue="@object" Value="@column.GetFilterValue()" Change="@((args) => OnFilter(new ChangeEventArgs() { Value = args }, column))" />
|
||||
</div>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (filterMode == FilterMode.SimpleWithMenu)
|
||||
{
|
||||
<RadzenDataGridFilterMenu Grid="@this" Column="@column" />
|
||||
}
|
||||
@if (column.FilterValueTemplate != null)
|
||||
{
|
||||
@column.FilterValueTemplate(column)
|
||||
}
|
||||
else
|
||||
{
|
||||
<input autocomplete="off" aria-label=@(column.Title + FilterValueAriaLabel + column.GetFilterValue()) disabled=@(!column.CanSetFilterValue()) id="@(getFilterInputId(column))" @onchange="@((args) => OnFilter(args, column))" @onkeydown="@((args) => OnFilterKeyPress(args, column))" value="@column.GetFilterValue()" type="text" placeholder="@column.GetFilterPlaceholder()" class="rz-textbox" style="width: 100%;" />
|
||||
@if (column.GetFilterValue() != null && filters.Any(d => d.Property == column.GetFilterProperty()))
|
||||
{
|
||||
<i @onclick="@((args) => ClearFilter(column))" class="notranslate rzi rz-cell-filter-clear" style="position:absolute;inset-inline-end:10px;">close</i>
|
||||
}
|
||||
}
|
||||
}
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</text>
|
||||
};
|
||||
}
|
||||
|
||||
internal void SetAttribute(Dictionary<string, object> attributes, string attributeName, object attributeValue)
|
||||
{
|
||||
var separator = attributeName == "class" ? " " : ";";
|
||||
|
||||
@@ -7,9 +7,7 @@ using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
using System.Data.Common;
|
||||
using System.Linq;
|
||||
using System.Linq.Dynamic.Core;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -157,8 +155,8 @@ namespace Radzen.Blazor
|
||||
|
||||
if (Groups.Any())
|
||||
{
|
||||
query = view.AsQueryable().OrderBy(DynamicLinqCustomTypeProvider.ParsingConfig, Groups.Any() ? string.Join(',', Groups.Select(g => $"{(typeof(TItem) == typeof(object) ? g.Property : "np(" + g.Property + ")")}")) : "it");
|
||||
_groupedPagedView = await Task.FromResult(query.GroupByMany(DynamicLinqCustomTypeProvider.ParsingConfig, Groups.Any() ? Groups.Select(g => $"{(typeof(TItem) == typeof(object) ? g.Property : "np(" + g.Property + ")")}").ToArray() : new string[] { "it" }).ToList());
|
||||
query = view.AsQueryable().OrderBy(Groups.Any() ? string.Join(',', Groups.Select(g => g.Property)) : null);
|
||||
_groupedPagedView = await Task.FromResult(query.GroupByMany(Groups.Any() ? Groups.Select(g => g.Property).ToArray() : new string[] { "it" }).ToList());
|
||||
|
||||
totalItemsCount = await Task.FromResult(_groupedPagedView.Count());
|
||||
}
|
||||
@@ -365,9 +363,9 @@ namespace Radzen.Blazor
|
||||
if (_groupedPagedView == null)
|
||||
{
|
||||
var orderBy = GetOrderBy();
|
||||
var query = Groups.Count(g => g.SortOrder == null) == Groups.Count || !string.IsNullOrEmpty(orderBy) ? View : View.OrderBy(DynamicLinqCustomTypeProvider.ParsingConfig, string.Join(',', Groups.Select(g => $"{(typeof(TItem) == typeof(object) ? g.Property : "np(" + g.Property + ")")} {(g.SortOrder == null ? "" : g.SortOrder == SortOrder.Ascending ? " asc" : " desc")}")));
|
||||
var query = Groups.Count(g => g.SortOrder == null) == Groups.Count || !string.IsNullOrEmpty(orderBy) ? View : View.OrderBy(string.Join(',', Groups.Select(g => $"{g.Property} {(g.SortOrder == null ? "" : g.SortOrder == SortOrder.Ascending ? " asc" : " desc")}")));
|
||||
var v = (AllowPaging && !LoadData.HasDelegate ? query.Skip(skip).Take(PageSize) : query).ToList().AsQueryable();
|
||||
_groupedPagedView = v.GroupByMany(DynamicLinqCustomTypeProvider.ParsingConfig, Groups.Select(g => $"{(typeof(TItem) == typeof(object) ? g.Property : "np(" + g.Property + ")")}").ToArray()).ToList();
|
||||
_groupedPagedView = v.GroupByMany(Groups.Select(g => g.Property).ToArray()).ToList();
|
||||
}
|
||||
return _groupedPagedView;
|
||||
}
|
||||
@@ -1302,6 +1300,13 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public string IsNotEmptyText { get; set; } = "Is not empty";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the custom filter operator text.
|
||||
/// </summary>
|
||||
/// <value>The custom filter operator text.</value>
|
||||
[Parameter]
|
||||
public string CustomText { get; set; } = "Custom";
|
||||
|
||||
internal class NumericFilterEventCallback
|
||||
{
|
||||
public static EventCallback<T> Create<T>(object receiver, Action<T> action)
|
||||
@@ -1680,7 +1685,16 @@ namespace Radzen.Blazor
|
||||
|
||||
internal string GetOrderBy()
|
||||
{
|
||||
return string.Join(",", sorts.Select(d => allColumns.ToList().Where(c => c.GetSortProperty() == d.Property).FirstOrDefault()).Where(c => c != null).Select(c => c.GetSortOrderAsString(IsOData())));
|
||||
return string.Join(",", sorts.Select(d => GetSortOrderAsString(d, IsOData())));
|
||||
}
|
||||
|
||||
internal string GetSortOrderAsString(SortDescriptor d, bool isOData)
|
||||
{
|
||||
var property = d.Property;
|
||||
if (string.IsNullOrEmpty(property))
|
||||
return "";
|
||||
var p = isOData ? property.Replace('.', '/') : PropertyAccess.GetProperty(property);
|
||||
return $"{p} {(d.SortOrder == Radzen.SortOrder.Ascending ? "asc" : "desc")}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1713,12 +1727,12 @@ namespace Radzen.Blazor
|
||||
var firstItem = view.FirstOrDefault();
|
||||
if (firstItem != null)
|
||||
{
|
||||
view = view.Cast(firstItem.GetType()).AsQueryable().OrderBy(orderBy).Cast<TItem>();
|
||||
view = QueryableExtension.Cast(view, firstItem.GetType()).AsQueryable().OrderBy(orderBy).Cast<TItem>();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
view = view.OrderBy(orderBy);
|
||||
view = view.OrderBy<TItem>(orderBy);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1744,7 +1758,7 @@ namespace Radzen.Blazor
|
||||
var cd = childData[item].Data.AsQueryable();
|
||||
if (!string.IsNullOrEmpty(orderBy))
|
||||
{
|
||||
cd = cd.OrderBy(orderBy);
|
||||
cd = cd.OrderBy<TItem>(orderBy);
|
||||
}
|
||||
|
||||
viewList.InsertRange(viewList.IndexOf(item) + 1, cd);
|
||||
@@ -1799,7 +1813,8 @@ namespace Radzen.Blazor
|
||||
var firstItem = view.FirstOrDefault();
|
||||
if (firstItem != null)
|
||||
{
|
||||
view = view.Cast(firstItem.GetType()).AsQueryable().OrderBy(orderBy).Cast<TItem>();
|
||||
view = QueryableExtension.Cast(view, firstItem.GetType());
|
||||
view = view.OrderBy(orderBy).Cast<TItem>();
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -2193,18 +2208,18 @@ namespace Radzen.Blazor
|
||||
/// Called when parameters set asynchronous.
|
||||
/// </summary>
|
||||
/// <returns>Task.</returns>
|
||||
protected override Task OnParametersSetAsync()
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
if (Visible && !LoadData.HasDelegate && _view == null)
|
||||
{
|
||||
InvokeAsync(Reload);
|
||||
await InvokeAsync(Reload);
|
||||
}
|
||||
else
|
||||
{
|
||||
CalculatePager();
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
internal Dictionary<RadzenDataGridGroupRow<TItem>, bool> collapsedGroupItems = new Dictionary<RadzenDataGridGroupRow<TItem>, bool>();
|
||||
@@ -2407,6 +2422,17 @@ namespace Radzen.Blazor
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Force load of the DataGrid Settings.
|
||||
/// </summary>
|
||||
public async Task ReloadSettings()
|
||||
{
|
||||
if (settings != null)
|
||||
{
|
||||
await LoadSettingsInternal(settings);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
@@ -2951,23 +2977,40 @@ namespace Radzen.Blazor
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
public async System.Threading.Tasks.Task InsertRow(TItem item)
|
||||
{
|
||||
await InsertRowAtIndex(item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inserts new row after specific row item.
|
||||
/// </summary>
|
||||
/// <param name="itemToInsert">The item.</param>
|
||||
/// <param name="rowItem">Row item to insert after</param>
|
||||
public async System.Threading.Tasks.Task InsertAfterRow(TItem itemToInsert, TItem rowItem)
|
||||
{
|
||||
var list = this.PagedView.ToList();
|
||||
var index = list.IndexOf(rowItem);
|
||||
await InsertRowAtIndex(itemToInsert, index + 1);
|
||||
}
|
||||
|
||||
private async System.Threading.Tasks.Task InsertRowAtIndex(TItem item, int insertIndex = 0)
|
||||
{
|
||||
itemsToInsert.Add(item);
|
||||
if(!IsVirtualizationAllowed())
|
||||
if (!IsVirtualizationAllowed())
|
||||
{
|
||||
var list = this.PagedView.ToList();
|
||||
list.Insert(0, item);
|
||||
list.Insert(insertIndex, item);
|
||||
this._view = list.AsQueryable();
|
||||
this.Count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(virtualize != null)
|
||||
if (virtualize != null)
|
||||
{
|
||||
await virtualize.RefreshDataAsync();
|
||||
}
|
||||
|
||||
if(groupVirtualize != null)
|
||||
if (groupVirtualize != null)
|
||||
{
|
||||
await groupVirtualize.RefreshDataAsync();
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Linq.Dynamic.Core;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
@@ -738,15 +737,6 @@ namespace Radzen.Blazor
|
||||
}
|
||||
}
|
||||
|
||||
internal string GetSortOrderAsString(bool isOData)
|
||||
{
|
||||
var property = GetSortProperty();
|
||||
if (string.IsNullOrEmpty(property))
|
||||
return "";
|
||||
var p = isOData ? property.Replace('.', '/') : PropertyAccess.GetProperty(property);
|
||||
return $"{p} {(GetSortOrder() == Radzen.SortOrder.Ascending ? "asc" : "desc")}";
|
||||
}
|
||||
|
||||
internal void SetSortOrder(SortOrder? order)
|
||||
{
|
||||
var descriptor = Grid.sorts.Where(d => d.Property == GetSortProperty()).FirstOrDefault();
|
||||
@@ -1327,6 +1317,8 @@ namespace Radzen.Blazor
|
||||
{
|
||||
switch (filterOperator)
|
||||
{
|
||||
case FilterOperator.Custom:
|
||||
return Grid?.CustomText;
|
||||
case FilterOperator.Contains:
|
||||
return Grid?.ContainsText;
|
||||
case FilterOperator.DoesNotContain:
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@typeparam TItem
|
||||
@using System.Linq.Dynamic.Core
|
||||
@for (var i = 0; i < Grid.deepestChildColumnLevel + 1; i++)
|
||||
{
|
||||
<tr>
|
||||
@@ -32,9 +31,9 @@
|
||||
[Parameter]
|
||||
public IList<RadzenDataGridColumn<TItem>> Columns { get; set; }
|
||||
|
||||
GroupResult _groupResult;
|
||||
GroupResult _groupResult;
|
||||
[Parameter]
|
||||
public GroupResult GroupResult
|
||||
public GroupResult GroupResult
|
||||
{
|
||||
get
|
||||
{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@typeparam TItem
|
||||
@using System.Linq.Dynamic.Core
|
||||
@using System.Globalization
|
||||
@{
|
||||
var rowArgs = Grid?.GroupRowAttributes(this);
|
||||
@@ -86,7 +85,7 @@
|
||||
|
||||
GroupResult _groupResult;
|
||||
[Parameter]
|
||||
public GroupResult GroupResult
|
||||
public GroupResult GroupResult
|
||||
{
|
||||
get
|
||||
{
|
||||
|
||||
@@ -2,148 +2,147 @@
|
||||
@using Microsoft.JSInterop
|
||||
@using Radzen.Blazor.Rendering
|
||||
@using System.Globalization
|
||||
@using System.Linq.Dynamic.Core
|
||||
@using System.Collections
|
||||
@using Radzen
|
||||
|
||||
@if (RowIndex == Column.GetLevel())
|
||||
{
|
||||
<th rowspan="@(Column.GetRowSpan())" colspan="@(Column.GetColSpan())" @attributes="@Attributes" class="@CssClass" scope="col" style="@GetStyle()" @onmouseup=@(args => Grid.EndColumnReorder(args, ColumnIndex))>
|
||||
<div @onclick='@((args) => Grid.OnSort(args, Column))' @onkeydown="OnSortKeyPressed">
|
||||
@if ((Grid.AllowColumnReorder && Column.Reorderable || Grid.AllowGrouping && Column.Groupable))
|
||||
{
|
||||
<span id="@(Grid.getColumnUniqueId(ColumnIndex) + "-drag")" class="rz-column-drag"
|
||||
@onclick:preventDefault="true" @onclick:stopPropagation="true"
|
||||
@onmousedown:preventDefault="true"
|
||||
@onmousedown=@(args => Grid.StartColumnReorder(args, ColumnIndex, Column.UniqueID ?? Column.Property))></span>
|
||||
}
|
||||
<span class="rz-column-title" title="@(Grid.ShowColumnTitleAsTooltip ? @Column.GetTitle() : Column.HeaderTooltip)">
|
||||
@if (Column.HeaderTemplate != null)
|
||||
<th rowspan="@(Column.GetRowSpan())" colspan="@(Column.GetColSpan())" @attributes="@Attributes" class="@CssClass" scope="col" style="@GetStyle()" @onmouseup=@(args => Grid.EndColumnReorder(args, ColumnIndex))>
|
||||
<div @onclick='@((args) => Grid.OnSort(args, Column))' @onkeydown="OnSortKeyPressed">
|
||||
@if ((Grid.AllowColumnReorder && Column.Reorderable || Grid.AllowGrouping && Column.Groupable))
|
||||
{
|
||||
<span class="rz-column-title-content" @onkeydown:stopPropagation>@Column.HeaderTemplate</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="rz-column-title-content">@Column.GetTitle()</span>
|
||||
<span id="@(Grid.getColumnUniqueId(ColumnIndex) + "-drag")" class="rz-column-drag"
|
||||
@onclick:preventDefault="true" @onclick:stopPropagation="true"
|
||||
@onmousedown:preventDefault="true"
|
||||
@onmousedown=@(args => Grid.StartColumnReorder(args, ColumnIndex, Column.UniqueID ?? Column.Property))></span>
|
||||
}
|
||||
<span class="rz-column-title" title="@(Grid.ShowColumnTitleAsTooltip ? @Column.GetTitle() : Column.HeaderTooltip)">
|
||||
@if (Column.HeaderTemplate != null)
|
||||
{
|
||||
<span class="rz-column-title-content" @onkeydown:stopPropagation>@Column.HeaderTemplate</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="rz-column-title-content">@Column.GetTitle()</span>
|
||||
}
|
||||
|
||||
@if (Grid.AllowSorting && Column.Sortable)
|
||||
{
|
||||
@if (Column.GetSortOrder() == SortOrder.Ascending)
|
||||
{
|
||||
<span class="notranslate rz-sortable-column-icon rzi-grid-sort rzi-sort rzi-sort-asc"></span>
|
||||
@if(Grid.ShowMultiColumnSortingIndex)
|
||||
{
|
||||
<RadzenBadge BadgeStyle="BadgeStyle.Info" Shade="Shade.Lighter" IsPill=true Text="@Column.getSortIndexAsString()" />
|
||||
}
|
||||
}
|
||||
else if (Column.GetSortOrder() == SortOrder.Descending)
|
||||
{
|
||||
<span class="notranslate rz-sortable-column-icon rzi-grid-sort rzi-sort rzi-sort-desc"></span>
|
||||
@if(Grid.ShowMultiColumnSortingIndex)
|
||||
@if (Grid.AllowSorting && Column.Sortable)
|
||||
{
|
||||
@if (Column.GetSortOrder() == SortOrder.Ascending)
|
||||
{
|
||||
<span class="notranslate rz-sortable-column-icon rzi-grid-sort rzi-sort rzi-sort-asc"></span>
|
||||
@if(Grid.ShowMultiColumnSortingIndex)
|
||||
{
|
||||
<RadzenBadge BadgeStyle="BadgeStyle.Info" Shade="Shade.Lighter" IsPill=true Text="@Column.getSortIndexAsString()" />
|
||||
}
|
||||
}
|
||||
else if (Column.GetSortOrder() == SortOrder.Descending)
|
||||
{
|
||||
<span class="notranslate rz-sortable-column-icon rzi-grid-sort rzi-sort rzi-sort-desc"></span>
|
||||
@if(Grid.ShowMultiColumnSortingIndex)
|
||||
{
|
||||
<RadzenBadge BadgeStyle="BadgeStyle.Info" Shade="Shade.Lighter" IsPill=true Text="@Column.getSortIndexAsString()" />
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="notranslate rz-sortable-column-icon rzi-grid-sort rzi-sort"></span>
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
</span>
|
||||
@if (Grid.AllowColumnResize && Column.Resizable && Column.Parent == null)
|
||||
{
|
||||
<span class="notranslate rz-sortable-column-icon rzi-grid-sort rzi-sort"></span>
|
||||
<div id="@(Grid.getColumnUniqueId(ColumnIndex) + "-resizer")" style="cursor:col-resize;float:right;"
|
||||
@onclick:preventDefault="true" @onclick:stopPropagation="true" class="rz-column-resizer"
|
||||
@onmousedown:preventDefault="true"
|
||||
@onmousedown=@StartColumnResize @onmouseup=@StopColumnResize> </div>
|
||||
}
|
||||
}
|
||||
</span>
|
||||
@if (Grid.AllowColumnResize && Column.Resizable && Column.Parent == null)
|
||||
{
|
||||
<div id="@(Grid.getColumnUniqueId(ColumnIndex) + "-resizer")" style="cursor:col-resize;float:right;"
|
||||
@onclick:preventDefault="true" @onclick:stopPropagation="true" class="rz-column-resizer"
|
||||
@onmousedown:preventDefault="true"
|
||||
@onmousedown=@StartColumnResize @onmouseup=@StopColumnResize> </div>
|
||||
}
|
||||
@{var filterMode = Column.FilterMode ?? Grid.FilterMode;}
|
||||
@if (Grid.AllowFiltering && Column.Filterable && (filterMode == FilterMode.Advanced || filterMode == FilterMode.CheckBoxList))
|
||||
{
|
||||
@{var filterMode = Column.FilterMode ?? Grid.FilterMode;}
|
||||
@if (Grid.AllowFiltering && Column.Filterable && (filterMode == FilterMode.Advanced || filterMode == FilterMode.CheckBoxList))
|
||||
{
|
||||
<i @ref=@filterButton @onclick:stopPropagation="true" @onmousedown=@ToggleFilter
|
||||
class="@getFilterIconCss(Column)" onclick=@getFilterOpen() @onclick:preventDefault="true">
|
||||
@Grid.FilterIcon
|
||||
class="@getFilterIconCss(Column)" onclick=@getFilterOpen() @onclick:preventDefault="true">
|
||||
@Grid.FilterIcon
|
||||
</i>
|
||||
|
||||
<Popup Lazy=@(Grid.FilterPopupRenderMode == PopupRenderMode.OnDemand) @ref=popup id="@($"{getColumnPopupID()}")" class="rz-overlaypanel"
|
||||
style="display:none;min-width:250px;" @onkeydown="OnFilterPopupKeyPressed">
|
||||
<div class="rz-overlaypanel-content">
|
||||
@if (Column.FilterTemplate != null)
|
||||
{
|
||||
@Column.FilterTemplate(Column)
|
||||
}
|
||||
else
|
||||
{
|
||||
<form id="@($"{getColumnPopupID()}-form")" @onsubmit="@(args => ApplyFilter())" class="rz-grid-filter">
|
||||
style="display:none;min-width:250px;" @onkeydown="OnFilterPopupKeyPressed">
|
||||
<div class="rz-overlaypanel-content">
|
||||
@if (Column.FilterTemplate != null)
|
||||
{
|
||||
@Column.FilterTemplate(Column)
|
||||
}
|
||||
else
|
||||
{
|
||||
<form id="@($"{getColumnPopupID()}-form")" @onsubmit="@(args => ApplyFilter())" class="rz-grid-filter">
|
||||
@if (filterMode == FilterMode.Advanced)
|
||||
{
|
||||
<span class="rz-grid-filter-label">@Grid.FilterText</span>
|
||||
<RadzenDropDown InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Grid.FilterOperatorAriaLabel + Column.GetFilterOperatorText(Column.GetSecondFilterOperator()) }})"
|
||||
<span class="rz-grid-filter-label">@Grid.FilterText</span>
|
||||
<RadzenDropDown InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Grid.FilterOperatorAriaLabel + Column.GetFilterOperatorText(Column.GetSecondFilterOperator()) }})"
|
||||
@onclick:preventDefault="true" Data="@(Column.GetFilterOperators().Select(t => new { Value = Column.GetFilterOperatorText(t), Key = t }))" TextProperty="Value" ValueProperty="Key" TValue="FilterOperator" Value="@Column.GetFilterOperator()" Change="@(args => Column.SetFilterOperator((FilterOperator)args))" />
|
||||
@if (Column.FilterValueTemplate != null)
|
||||
{
|
||||
@Column.FilterValueTemplate(Column)
|
||||
}
|
||||
else if (PropertyAccess.IsNullableEnum(Column.FilterPropertyType) || PropertyAccess.IsEnum(Column.FilterPropertyType))
|
||||
{
|
||||
<RadzenDropDown Disabled="@(!Column.CanSetFilterValue())" AllowClear="false" AllowFiltering="false" TValue="@object"
|
||||
Value=@Column.GetFilterValue() Multiple="false" Placeholder="@Grid.EnumFilterSelectText" TextProperty="Text" ValueProperty="Value" Data=@EnumExtensions.EnumAsKeyValuePair(Nullable.GetUnderlyingType(Column.FilterPropertyType) ?? Column.FilterPropertyType, Grid.EnumFilterTranslationFunc)
|
||||
Change="@(args => Column.SetFilterValue(args))"
|
||||
InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Column.Title + Grid.FilterValueAriaLabel + Column.GetFilterValue() }})" />
|
||||
}
|
||||
else if (PropertyAccess.IsNumeric(Column.FilterPropertyType))
|
||||
{
|
||||
@(Grid.DrawNumericFilter(Column, false))
|
||||
}
|
||||
else if (PropertyAccess.IsDate(Column.FilterPropertyType))
|
||||
{
|
||||
<RadzenDatePicker Disabled="@(!Column.CanSetFilterValue())" TValue="@object" ShowTime="@Column.ShowTimeForDateTimeFilter()" ShowTimeOkButton="true" DateFormat="@Grid.getFilterDateFormat(Column)"
|
||||
Value="@Column.GetFilterValue()" Change="@(args => Column.SetFilterValue(PropertyAccess.IsDateOnly(Column.FilterPropertyType) ? PropertyAccess.DateOnlyFromDateTime(args.Value) : args.Value))" AllowInput=@(Grid.AllowFilterDateInput)
|
||||
InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Column.Title + Grid.FilterValueAriaLabel + Column.GetFilterValue() }})" />
|
||||
@if (Column.FilterValueTemplate != null)
|
||||
{
|
||||
@Column.FilterValueTemplate(Column)
|
||||
}
|
||||
else if (PropertyAccess.IsNullableEnum(Column.FilterPropertyType) || PropertyAccess.IsEnum(Column.FilterPropertyType))
|
||||
{
|
||||
<RadzenDropDown Disabled="@(!Column.CanSetFilterValue())" AllowClear="false" AllowFiltering="false" TValue="@object"
|
||||
Value=@Column.GetFilterValue() Multiple="false" Placeholder="@Grid.EnumFilterSelectText" TextProperty="Text" ValueProperty="Value" Data=@EnumExtensions.EnumAsKeyValuePair(Nullable.GetUnderlyingType(Column.FilterPropertyType) ?? Column.FilterPropertyType, Grid.EnumFilterTranslationFunc)
|
||||
Change="@(args => Column.SetFilterValue(args))"
|
||||
InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Column.Title + Grid.FilterValueAriaLabel + Column.GetFilterValue() }})" />
|
||||
}
|
||||
else if (PropertyAccess.IsNumeric(Column.FilterPropertyType))
|
||||
{
|
||||
@(Grid.DrawNumericFilter(Column, false))
|
||||
}
|
||||
else if (PropertyAccess.IsDate(Column.FilterPropertyType))
|
||||
{
|
||||
<RadzenDatePicker Disabled="@(!Column.CanSetFilterValue())" TValue="@object" ShowTime="@Column.ShowTimeForDateTimeFilter()" ShowTimeOkButton="true" DateFormat="@Grid.getFilterDateFormat(Column)"
|
||||
Value="@Column.GetFilterValue()" Change="@(args => Column.SetFilterValue(PropertyAccess.IsDateOnly(Column.FilterPropertyType) ? PropertyAccess.DateOnlyFromDateTime(args.Value) : args.Value))" AllowInput=@(Grid.AllowFilterDateInput)
|
||||
InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Column.Title + Grid.FilterValueAriaLabel + Column.GetFilterValue() }})" />
|
||||
|
||||
}
|
||||
else if (Column.FilterPropertyType == typeof(bool) || Column.FilterPropertyType == typeof(bool?))
|
||||
{
|
||||
<RadzenCheckBox Disabled="@(!Column.CanSetFilterValue())" InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Column.Title + Grid.FilterValueAriaLabel + Column.GetFilterValue() }})" TriState="true" TValue="@object" Value="@Column.GetFilterValue()" Change="@(args => { Column.SetFilterValue(null); Column.SetFilterValue(args); Grid.SaveSettings(); })" />
|
||||
}
|
||||
else
|
||||
{
|
||||
<RadzenTextBox Disabled="@(!Column.CanSetFilterValue())" id="@($"{getColumnPopupID()}-sf")" aria-label=@(Column.Title + Grid.FilterValueAriaLabel + Column.GetFilterValue()) Value="@($"{Column.GetFilterValue()}")" Change="@(args => Column.SetFilterValue(args))" />
|
||||
}
|
||||
}
|
||||
else if (Column.FilterPropertyType == typeof(bool) || Column.FilterPropertyType == typeof(bool?))
|
||||
{
|
||||
<RadzenCheckBox Disabled="@(!Column.CanSetFilterValue())" InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Column.Title + Grid.FilterValueAriaLabel + Column.GetFilterValue() }})" TriState="true" TValue="@object" Value="@Column.GetFilterValue()" Change="@(args => { Column.SetFilterValue(null); Column.SetFilterValue(args); Grid.SaveSettings(); })" />
|
||||
}
|
||||
else
|
||||
{
|
||||
<RadzenTextBox Disabled="@(!Column.CanSetFilterValue())" id="@($"{getColumnPopupID()}-sf")" aria-label=@(Column.Title + Grid.FilterValueAriaLabel + Column.GetFilterValue()) Value="@($"{Column.GetFilterValue()}")" Change="@(args => Column.SetFilterValue(args))" />
|
||||
}
|
||||
|
||||
<RadzenDropDown @onclick:preventDefault="true" TextProperty="Text" ValueProperty="Value" Style="width: 90px" InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Column.Title + Grid.LogicalOperatorAriaLabel + (Column.LogicalFilterOperator == LogicalFilterOperator.And ? Grid.AndOperatorText : Grid.OrOperatorText) }})"
|
||||
Data="@(Enum.GetValues(typeof(LogicalFilterOperator)).Cast<LogicalFilterOperator>().Select(t => new { Text = t == LogicalFilterOperator.And ? Grid.AndOperatorText : Grid.OrOperatorText, Value = t }))" TValue="LogicalFilterOperator" Value="@Column.LogicalFilterOperator" Change="@(args => Column.SetLogicalFilterOperator((LogicalFilterOperator)args))" />
|
||||
<RadzenDropDown @onclick:preventDefault="true" TextProperty="Text" ValueProperty="Value" Style="width: 90px" InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Column.Title + Grid.LogicalOperatorAriaLabel + (Column.LogicalFilterOperator == LogicalFilterOperator.And ? Grid.AndOperatorText : Grid.OrOperatorText) }})"
|
||||
Data="@(Enum.GetValues(typeof(LogicalFilterOperator)).Cast<LogicalFilterOperator>().Select(t => new { Text = t == LogicalFilterOperator.And ? Grid.AndOperatorText : Grid.OrOperatorText, Value = t }))" TValue="LogicalFilterOperator" Value="@Column.LogicalFilterOperator" Change="@(args => Column.SetLogicalFilterOperator((LogicalFilterOperator)args))" />
|
||||
|
||||
<RadzenDropDown InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Grid.SecondFilterOperatorAriaLabel + Column.GetFilterOperatorText(Column.GetSecondFilterOperator()) }})" @onclick:preventDefault="true" Data="@(Column.GetFilterOperators().Select(t => new { Value = Column.GetFilterOperatorText(t), Key = t }))" TextProperty="Value" ValueProperty="Key" TValue="FilterOperator" Value="@Column.GetSecondFilterOperator()" Change="@(args => Column.SetSecondFilterOperator((FilterOperator)args))" />
|
||||
@if (Column.SecondFilterValueTemplate != null)
|
||||
{
|
||||
@Column.SecondFilterValueTemplate(Column)
|
||||
}
|
||||
else if (PropertyAccess.IsNullableEnum(Column.FilterPropertyType) || PropertyAccess.IsEnum(Column.FilterPropertyType))
|
||||
{
|
||||
<RadzenDropDown Disabled="@(!Column.CanSetFilterValue(false))" AllowClear="false" AllowFiltering="false" TValue="@object" InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Column.Title + Grid.SecondFilterValueAriaLabel }})"
|
||||
Value=@Column.GetSecondFilterValue() Multiple="false" Placeholder="@Grid.EnumFilterSelectText" TextProperty="Text" ValueProperty="Value" Data=@EnumExtensions.EnumAsKeyValuePair(Nullable.GetUnderlyingType(Column.FilterPropertyType) ?? Column.FilterPropertyType, Grid.EnumFilterTranslationFunc)
|
||||
Change="@(args => Column.SetFilterValue(args,false))" />
|
||||
}
|
||||
else if (PropertyAccess.IsNumeric(Column.FilterPropertyType))
|
||||
{
|
||||
@(Grid.DrawNumericFilter(Column, false, false))
|
||||
}
|
||||
else if (PropertyAccess.IsDate(Column.FilterPropertyType))
|
||||
{
|
||||
<RadzenDatePicker Disabled="@(!Column.CanSetFilterValue(false))" TValue="@object" InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Column.Title + Grid.SecondFilterValueAriaLabel + Column.GetSecondFilterValue() }})"
|
||||
ShowTime="@Column.ShowTimeForDateTimeFilter()" ShowTimeOkButton="true" DateFormat="@Grid.getFilterDateFormat(Column)"
|
||||
Value="@Column.GetSecondFilterValue()" Change="@(args => Column.SetFilterValue(PropertyAccess.IsDateOnly(Column.FilterPropertyType) ? PropertyAccess.DateOnlyFromDateTime(args.Value) : args.Value, false))" AllowInput=@(Grid.AllowFilterDateInput) />
|
||||
<RadzenDropDown InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Grid.SecondFilterOperatorAriaLabel + Column.GetFilterOperatorText(Column.GetSecondFilterOperator()) }})" @onclick:preventDefault="true" Data="@(Column.GetFilterOperators().Select(t => new { Value = Column.GetFilterOperatorText(t), Key = t }))" TextProperty="Value" ValueProperty="Key" TValue="FilterOperator" Value="@Column.GetSecondFilterOperator()" Change="@(args => Column.SetSecondFilterOperator((FilterOperator)args))" />
|
||||
@if (Column.SecondFilterValueTemplate != null)
|
||||
{
|
||||
@Column.SecondFilterValueTemplate(Column)
|
||||
}
|
||||
else if (PropertyAccess.IsNullableEnum(Column.FilterPropertyType) || PropertyAccess.IsEnum(Column.FilterPropertyType))
|
||||
{
|
||||
<RadzenDropDown Disabled="@(!Column.CanSetFilterValue(false))" AllowClear="false" AllowFiltering="false" TValue="@object" InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Column.Title + Grid.SecondFilterValueAriaLabel }})"
|
||||
Value=@Column.GetSecondFilterValue() Multiple="false" Placeholder="@Grid.EnumFilterSelectText" TextProperty="Text" ValueProperty="Value" Data=@EnumExtensions.EnumAsKeyValuePair(Nullable.GetUnderlyingType(Column.FilterPropertyType) ?? Column.FilterPropertyType, Grid.EnumFilterTranslationFunc)
|
||||
Change="@(args => Column.SetFilterValue(args,false))" />
|
||||
}
|
||||
else if (PropertyAccess.IsNumeric(Column.FilterPropertyType))
|
||||
{
|
||||
@(Grid.DrawNumericFilter(Column, false, false))
|
||||
}
|
||||
else if (PropertyAccess.IsDate(Column.FilterPropertyType))
|
||||
{
|
||||
<RadzenDatePicker Disabled="@(!Column.CanSetFilterValue(false))" TValue="@object" InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Column.Title + Grid.SecondFilterValueAriaLabel + Column.GetSecondFilterValue() }})"
|
||||
ShowTime="@Column.ShowTimeForDateTimeFilter()" ShowTimeOkButton="true" DateFormat="@Grid.getFilterDateFormat(Column)"
|
||||
Value="@Column.GetSecondFilterValue()" Change="@(args => Column.SetFilterValue(PropertyAccess.IsDateOnly(Column.FilterPropertyType) ? PropertyAccess.DateOnlyFromDateTime(args.Value) : args.Value, false))" AllowInput=@(Grid.AllowFilterDateInput) />
|
||||
|
||||
}
|
||||
else if (Column.FilterPropertyType == typeof(bool) || Column.FilterPropertyType == typeof(bool?))
|
||||
{
|
||||
<RadzenCheckBox Disabled="@(!Column.CanSetFilterValue(false))" InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Column.Title + Grid.SecondFilterValueAriaLabel + Column.GetSecondFilterValue() }})" TriState="true" TValue="@object" Value="@Column.GetSecondFilterValue()" Change="@(args => { Column.SetFilterValue(args, false); Grid.SaveSettings(); })" />
|
||||
}
|
||||
else
|
||||
{
|
||||
<RadzenTextBox Disabled="@(!Column.CanSetFilterValue(false))" id="@($"{getColumnPopupID()}-sf2")" aria-label=@(Column.Title + Grid.SecondFilterValueAriaLabel + Column.GetSecondFilterValue()) Value="@($"{Column.GetSecondFilterValue()}")" Change="@(args => Column.SetFilterValue(args, false))" />
|
||||
}
|
||||
else if (Column.FilterPropertyType == typeof(bool) || Column.FilterPropertyType == typeof(bool?))
|
||||
{
|
||||
<RadzenCheckBox Disabled="@(!Column.CanSetFilterValue(false))" InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Column.Title + Grid.SecondFilterValueAriaLabel + Column.GetSecondFilterValue() }})" TriState="true" TValue="@object" Value="@Column.GetSecondFilterValue()" Change="@(args => { Column.SetFilterValue(args, false); Grid.SaveSettings(); })" />
|
||||
}
|
||||
else
|
||||
{
|
||||
<RadzenTextBox Disabled="@(!Column.CanSetFilterValue(false))" id="@($"{getColumnPopupID()}-sf2")" aria-label=@(Column.Title + Grid.SecondFilterValueAriaLabel + Column.GetSecondFilterValue()) Value="@($"{Column.GetSecondFilterValue()}")" Change="@(args => Column.SetFilterValue(args, false))" />
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -154,39 +153,44 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<RadzenListBox AllowVirtualization="@Column.AllowCheckBoxListVirtualization" AllowClear="true" Multiple="true" Style="height: 300px"
|
||||
TValue="IEnumerable<object>" Value=@Column.GetFilterValue() Change="@ListBoxChange"
|
||||
Data=@filterValues Count=@filterValuesCount LoadData="@LoadFilterValues"
|
||||
AllowFiltering="@(!string.IsNullOrEmpty(Column.GetFilterProperty()) && PropertyAccess.GetPropertyType(typeof(TItem), Column.GetFilterProperty()) == typeof(string))"
|
||||
Disabled="@(!Column.CanSetFilterValue())" FilterCaseSensitivity="FilterCaseSensitivity.CaseInsensitive"
|
||||
InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Column.Title + Grid.FilterValueAriaLabel + Column.GetFilterValue() }})">
|
||||
<Template>
|
||||
@if (context as Enum != null)
|
||||
{
|
||||
@EnumExtensions.GetDisplayDescription(context as Enum)
|
||||
}
|
||||
else
|
||||
{
|
||||
@(!string.IsNullOrEmpty(Column.FormatString) ? string.Format(Column.FormatProvider ?? Grid?.Culture ?? CultureInfo.CurrentCulture, Column.FormatString, context ?? "") : Convert.ToString(context ?? "", Grid?.Culture ?? CultureInfo.CurrentCulture))
|
||||
}
|
||||
</Template>
|
||||
</RadzenListBox>
|
||||
<RadzenProgressBarCircular Style="position:absolute;width:100%;" Visible="@isLoading" Value="100" ShowValue="false" Mode="ProgressBarMode.Indeterminate" />
|
||||
<RadzenListBox AllowVirtualization="@Column.AllowCheckBoxListVirtualization" AllowClear="true" Multiple="true" Style="height: 300px"
|
||||
TValue="IEnumerable<object>" Value=@Column.GetFilterValue() Change="@ListBoxChange"
|
||||
Data=@filterValues Count=@filterValuesCount LoadData="@LoadFilterValues"
|
||||
AllowFiltering="@(!string.IsNullOrEmpty(Column.GetFilterProperty()) && PropertyAccess.GetPropertyType(typeof(TItem), Column.GetFilterProperty()) == typeof(string))"
|
||||
Disabled="@(!Column.CanSetFilterValue())" FilterCaseSensitivity="FilterCaseSensitivity.CaseInsensitive"
|
||||
InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Column.Title + Grid.FilterValueAriaLabel + Column.GetFilterValue() }})">
|
||||
<Template>
|
||||
@if (context as Enum != null)
|
||||
{
|
||||
@EnumExtensions.GetDisplayDescription(context as Enum)
|
||||
}
|
||||
else
|
||||
{
|
||||
@(!string.IsNullOrEmpty(Column.FormatString) ? string.Format(Column.FormatProvider ?? Grid?.Culture ?? CultureInfo.CurrentCulture, Column.FormatString, context ?? "") : Convert.ToString(context ?? "", Grid?.Culture ?? CultureInfo.CurrentCulture))
|
||||
}
|
||||
</Template>
|
||||
</RadzenListBox>
|
||||
}
|
||||
}
|
||||
</form>
|
||||
}
|
||||
</div>
|
||||
@if (Column.FilterTemplate == null)
|
||||
{
|
||||
<div class="rz-grid-filter-buttons">
|
||||
<RadzenButton ButtonStyle="ButtonStyle.Base" class="rz-clear-filter" Click="@ClearFilter" Text=@Grid.ClearFilterText title="@Grid.ClearFilterText" />
|
||||
<RadzenButton onmousedown="@getBlur()" ButtonStyle="ButtonStyle.Primary" class="rz-apply-filter" form="@($"{getColumnPopupID()}-form")" ButtonType="ButtonType.Submit" Text=@Grid.ApplyFilterText title="@Grid.ApplyFilterText" />
|
||||
</div>
|
||||
}
|
||||
</Popup>
|
||||
</div>
|
||||
@if (Column.FilterTemplate == null)
|
||||
{
|
||||
<div class="rz-grid-filter-buttons">
|
||||
<RadzenButton ButtonStyle="ButtonStyle.Base" class="rz-clear-filter" Click="@ClearFilter" Text=@Grid.ClearFilterText title="@Grid.ClearFilterText" />
|
||||
<RadzenButton onmousedown="@getBlur()" ButtonStyle="ButtonStyle.Primary" class="rz-apply-filter" form="@($"{getColumnPopupID()}-form")" ButtonType="ButtonType.Submit" Text=@Grid.ApplyFilterText title="@Grid.ApplyFilterText" />
|
||||
</div>
|
||||
}
|
||||
</Popup>
|
||||
}
|
||||
</div>
|
||||
@if (Grid.allColumns.Any(c => c.Parent != null) && Grid.AllowFiltering && Column.Filterable && (filterMode == FilterMode.Simple || filterMode == FilterMode.SimpleWithMenu))
|
||||
{
|
||||
@Grid.RenderSimpleFilter(Column, filterMode)
|
||||
}
|
||||
</div>
|
||||
</th>
|
||||
</th>
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -195,7 +199,7 @@ else
|
||||
ColumnIndex = Grid.allColumns.IndexOf(column);//for child must have different columnindex
|
||||
|
||||
<RadzenDataGridHeaderCell RowIndex="@RowIndex" Grid="@Grid" Column="@column" Style="@column.GetStyle(true, true)" ColumnIndex="@ColumnIndex"
|
||||
CssClass="@($"rz-unselectable-text {(Grid.AllowSorting && column.Sortable ? "rz-sortable-column" : "")} {column.HeaderCssClass} {Grid.getFrozenColumnClass(column, Grid.ColumnsCollection.Where(c => c.GetVisible()).ToList())} {Grid.getCompositeCellCSSClass(column)} {Grid.getColumnAlignClass(column)}".Trim())" />
|
||||
CssClass="@($"rz-unselectable-text {(Grid.AllowSorting && column.Sortable ? "rz-sortable-column" : "")} {column.HeaderCssClass} {Grid.getFrozenColumnClass(column, Grid.ColumnsCollection.Where(c => c.GetVisible()).ToList())} {Grid.getCompositeCellCSSClass(column)} {Grid.getColumnAlignClass(column)}".Trim())" />
|
||||
}
|
||||
}
|
||||
@code {
|
||||
@@ -205,24 +209,19 @@ else
|
||||
int filterValuesCount;
|
||||
internal IEnumerable filterValues;
|
||||
string loadDataArgsString;
|
||||
bool isLoading = false;
|
||||
|
||||
async Task LoadFilterValues(LoadDataArgs loadDataArgs)
|
||||
{
|
||||
isLoading = true;
|
||||
|
||||
await Task.Yield();
|
||||
|
||||
var property = Column.Property != Column.FilterProperty && !string.IsNullOrEmpty(Column.FilterProperty) ? Column.Property :
|
||||
Column.GetFilterProperty();
|
||||
|
||||
var propertyType = PropertyAccess.GetPropertyType(typeof(TItem), property);
|
||||
|
||||
if (property.IndexOf(".") != -1)
|
||||
{
|
||||
property = $"np({property})";
|
||||
}
|
||||
|
||||
if (propertyType == typeof(string))
|
||||
{
|
||||
property = $@"({property} == null ? """" : {property})";
|
||||
}
|
||||
|
||||
var loadDataArgsString = $"{loadDataArgs.Skip}|{loadDataArgs.Top}{loadDataArgs.Filter}";
|
||||
|
||||
if (Column.Grid.LoadColumnFilterData.HasDelegate)
|
||||
@@ -231,7 +230,7 @@ else
|
||||
|
||||
await Column.Grid.LoadColumnFilterData.InvokeAsync(args);
|
||||
|
||||
filterValues = args.Data.AsQueryable().Select(DynamicLinqCustomTypeProvider.ParsingConfig, property).Distinct().Cast(propertyType ?? typeof(object));
|
||||
filterValues = args.Data.AsQueryable().Select(property).Distinct();
|
||||
filterValuesCount = args.Count;
|
||||
}
|
||||
else if(!string.IsNullOrEmpty(property) && (filterValues == null || this.loadDataArgsString != loadDataArgsString) && Column.Grid.Data != null)
|
||||
@@ -242,8 +241,8 @@ else
|
||||
|
||||
if(!string.IsNullOrEmpty(loadDataArgs.Filter))
|
||||
{
|
||||
query = Radzen.QueryableExtension.Where(Column.Grid.Data.AsQueryable().Where<TItem>(Column.Grid.allColumns.Where(c => c != Column)),
|
||||
property, loadDataArgs.Filter, StringFilterOperator.Contains, FilterCaseSensitivity.CaseInsensitive);
|
||||
query = Column.Grid.Data.AsQueryable().Where<TItem>(Column.Grid.allColumns.Where(c => c != Column))
|
||||
.Where(property, loadDataArgs.Filter, StringFilterOperator.Contains, FilterCaseSensitivity.CaseInsensitive);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -252,35 +251,34 @@ else
|
||||
|
||||
if (Column.Property != Column.FilterProperty && !string.IsNullOrEmpty(Column.FilterProperty))
|
||||
{
|
||||
query = query
|
||||
.SelectMany(DynamicLinqCustomTypeProvider.ParsingConfig, property)
|
||||
.Select(DynamicLinqCustomTypeProvider.ParsingConfig, Column.FilterProperty)
|
||||
.Distinct().OrderBy("it").Cast(typeof(object));
|
||||
query = query.SelectMany(property).Select(Column.FilterProperty).Distinct().OrderBy();
|
||||
}
|
||||
else
|
||||
{
|
||||
query = query.Select(DynamicLinqCustomTypeProvider.ParsingConfig, property).Distinct().OrderBy("it").Cast(propertyType ?? typeof(object));
|
||||
query = query.Select(property).Distinct().OrderBy();
|
||||
}
|
||||
|
||||
filterValuesCount = query.Count();
|
||||
filterValuesCount = query.Cast<object>().Count();
|
||||
|
||||
if(loadDataArgs.Skip != null)
|
||||
{
|
||||
query = query.Skip(loadDataArgs.Skip.Value);
|
||||
query = query.Cast<object>().Skip(loadDataArgs.Skip.Value);
|
||||
}
|
||||
|
||||
if(loadDataArgs.Top != null)
|
||||
{
|
||||
query = query.Take(loadDataArgs.Top.Value);
|
||||
query = query.Cast<object>().Take(loadDataArgs.Top.Value);
|
||||
}
|
||||
|
||||
filterValues = query.Select("it => it.ToString() == string.Empty ? null : it");
|
||||
filterValues = query.Cast(propertyType);
|
||||
|
||||
if (!Column.AllowCheckBoxListVirtualization)
|
||||
{
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
}
|
||||
|
||||
isLoading = false;
|
||||
}
|
||||
|
||||
void ListBoxChange(object args)
|
||||
@@ -343,7 +341,7 @@ else
|
||||
|
||||
bool IsAdvancedNumeric()
|
||||
{
|
||||
return Grid.FilterMode == FilterMode.Advanced &&
|
||||
return (Column.FilterMode ?? Grid.FilterMode) == FilterMode.Advanced &&
|
||||
PropertyAccess.IsNumeric(Column.FilterPropertyType) &&
|
||||
!(PropertyAccess.IsEnum(Column.FilterPropertyType) || PropertyAccess.IsNullableEnum(Column.FilterPropertyType));
|
||||
}
|
||||
|
||||
@@ -1,15 +1,5 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Forms;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using Microsoft.JSInterop;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
using System.Data.Common;
|
||||
using System.Linq;
|
||||
using System.Linq.Dynamic.Core;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
|
||||
@@ -1,21 +1,17 @@
|
||||
@using Radzen
|
||||
@using Radzen.Blazor.Rendering
|
||||
@using Microsoft.AspNetCore.Components.Forms
|
||||
@using System.Linq.Expressions
|
||||
@using System.Globalization
|
||||
@using Microsoft.JSInterop
|
||||
|
||||
@typeparam TValue
|
||||
@inherits RadzenComponent
|
||||
@implements IRadzenFormComponent
|
||||
@if (Visible)
|
||||
{
|
||||
<div @ref="@Element" @attributes="Attributes" class="@($"rz-datepicker{(Disabled ? " rz-state-disabled" : "")}") @GetCssClass()" style="@getStyle()" id="@GetId()">
|
||||
<div @ref="@Element" @attributes="Attributes" class="@GetCssClass()" style="@getStyle()" id="@GetId()">
|
||||
@if (!Inline)
|
||||
{
|
||||
<input @ref="@input" @attributes="InputAttributes" disabled="@Disabled" readonly="@IsReadonly" value="@FormattedValue" tabindex="@(Disabled ? "-1" : $"{TabIndex}")"
|
||||
@onchange="@ParseDate" autocomplete="off" type="text" name="@Name" @onkeydown="@(args => OnKeyPress(args))" @onkeydown:preventDefault=preventKeyPress @onkeydown:stopPropagation
|
||||
class="rz-inputtext @InputClass @(ReadOnly ? "rz-readonly" : "") @(!ShowButton ? "rz-input-trigger" : "")" id="@Name" placeholder="@Placeholder" />
|
||||
class="rz-inputtext @InputClass @(ReadOnly ? "rz-readonly" : "") @(!ShowButton ? "rz-input-trigger" : "")" id="@Name" placeholder="@CurrentPlaceholder" />
|
||||
@if (ShowButton)
|
||||
{
|
||||
<button aria-label="@ToggleAriaLabel" @onmousedown=@OnToggle class="@($"rz-datepicker-trigger rz-button rz-button-icon-only{(Disabled ? " rz-state-disabled" : "")} {ButtonClass}")" tabindex="-1" type="button">
|
||||
@@ -33,10 +29,10 @@
|
||||
@if (!TimeOnly)
|
||||
{
|
||||
<div class="rz-calendar-header">
|
||||
<a id="@(GetId() + "pm")" tabindex="-1" aria-label="@PrevMonthAriaLabel" @onclick:preventDefault="true" class="rz-button rz-button-md rz-variant-text rz-button-icon-only rz-secondary rz-shade-default rz-calendar-prev" @onclick="@(async () => { if (!Disabled) { try { if(CurrentDate.AddMonths(-1).Year >= YearFrom) {CurrentDate = CurrentDate.AddMonths(-1);}} catch (ArgumentOutOfRangeException) {}} })">
|
||||
<a id="@(GetId() + "pm")" tabindex="-1" aria-label="@PrevMonthAriaLabel" @onclick:preventDefault="true" class="rz-button rz-button-md rz-variant-text rz-button-icon-only rz-secondary rz-shade-default rz-calendar-prev" @onclick="@(() => { if (!Disabled) { try { if(CurrentDate.AddMonths(-1).Year >= YearFrom) {CurrentDate = CurrentDate.AddMonths(-1);}} catch (ArgumentOutOfRangeException) {}} })">
|
||||
<span class="notranslate rzi rz-calendar-prev-icon"></span>
|
||||
</a>
|
||||
<a id="@(GetId() + "nm")" tabindex="-1" aria-label="@NextMonthAriaLabel" @onclick:preventDefault="true" class="rz-button rz-button-md rz-variant-text rz-button-icon-only rz-secondary rz-shade-default rz-calendar-next" @onclick="@(async () => { if (!Disabled) { try { if(CurrentDate.AddMonths(1).Year <= YearTo) {CurrentDate = CurrentDate.AddMonths(1);}} catch (ArgumentOutOfRangeException) {} } })">
|
||||
<a id="@(GetId() + "nm")" tabindex="-1" aria-label="@NextMonthAriaLabel" @onclick:preventDefault="true" class="rz-button rz-button-md rz-variant-text rz-button-icon-only rz-secondary rz-shade-default rz-calendar-next" @onclick="@(() => { if (!Disabled) { try { if(CurrentDate.AddMonths(1).Year <= YearTo) {CurrentDate = CurrentDate.AddMonths(1);}} catch (ArgumentOutOfRangeException) {} } })">
|
||||
<span class="notranslate rzi rz-calendar-next-icon"></span>
|
||||
</a>
|
||||
<div class="rz-calendar-title">
|
||||
@@ -116,19 +112,19 @@
|
||||
{
|
||||
<div class="rz-timepicker" @onmousedown:stopPropagation>
|
||||
<RadzenNumeric InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", "hour" }})" TValue="int" Disabled="@Disabled" Value="@(HourFormat == "12" ? ((CurrentDate.Hour + 11) % 12) + 1 : CurrentDate.Hour)"
|
||||
Min="@(HourFormat == "12" ? 1 : -1)" Max="@(HourFormat == "12" ? 12 : 24)" TValue="double" Step="@HoursStep"
|
||||
Min="@(HourFormat == "12" ? 1 : -1)" Max="@(HourFormat == "12" ? 12 : 24)" Step="@HoursStep"
|
||||
Change="@UpdateHour" class="rz-hour-picker" @oninput=@OnUpdateHourInput Format="@(PadHours ? "00" : "")" Name="@($"{UniqueID}-h")" />
|
||||
<div class="rz-separator">
|
||||
<span>:</span>
|
||||
</div>
|
||||
<RadzenNumeric InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", "minutes" }})" TValue="int" Disabled="@Disabled" Value="CurrentDate.Minute" TValue="double" Step="@MinutesStep" Min="0" Max="59"
|
||||
<RadzenNumeric InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", "minutes" }})" TValue="int" Disabled="@Disabled" Value="CurrentDate.Minute" Step="@MinutesStep" Min="0" Max="59"
|
||||
Change="@UpdateMinutes" class="rz-minute-picker" @oninput=@OnUpdateHourMinutes Format="@(PadMinutes ? "00" : "")" Name="@($"{UniqueID}-m")"/>
|
||||
@if (ShowSeconds)
|
||||
{
|
||||
<div class="rz-separator">
|
||||
<span>:</span>
|
||||
</div>
|
||||
<RadzenNumeric InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", "seconds" }})" TValue="int" Disabled="@Disabled" Value="CurrentDate.Second" TValue="double" Step="@SecondsStep" Min="0" Max="59"
|
||||
<RadzenNumeric InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", "seconds" }})" TValue="int" Disabled="@Disabled" Value="CurrentDate.Second" Step="@SecondsStep" Min="0" Max="59"
|
||||
Change="@UpdateSeconds" class="rz-second-picker" @oninput=@OnUpdateHourSeconds Format="@(PadSeconds ? "00" : "")" Name="@($"{UniqueID}-s")"/>
|
||||
}
|
||||
@if (HourFormat == "12")
|
||||
|
||||
@@ -7,7 +7,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Linq.Dynamic.Core;
|
||||
using System.Linq.Expressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -750,6 +749,12 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public bool Disabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the FormFieldContext of the component
|
||||
/// </summary>
|
||||
[CascadingParameter]
|
||||
public IFormFieldContext FormFieldContext { get; set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether days part is shown.
|
||||
/// </summary>
|
||||
@@ -917,6 +922,9 @@ namespace Radzen.Blazor
|
||||
return $"{(Inline ? "overflow:auto;" : "")}{(Style != null ? Style : "")}";
|
||||
}
|
||||
|
||||
/// <summary> Gets the current placeholder. Returns empty string if this component is inside a RadzenFormField.</summary>
|
||||
protected string CurrentPlaceholder => FormFieldContext?.AllowFloatingLabel == true ? " " : Placeholder;
|
||||
|
||||
/// <summary>
|
||||
/// Closes this instance popup.
|
||||
/// </summary>
|
||||
@@ -977,10 +985,13 @@ namespace Radzen.Blazor
|
||||
/// <inheritdoc />
|
||||
protected override string GetComponentCssClass()
|
||||
{
|
||||
return ClassList.Create()
|
||||
return ClassList.Create("rz-datepicker")
|
||||
.Add("rz-datepicker-inline", Inline)
|
||||
.AddDisabled(Disabled)
|
||||
.Add("rz-state-empty", !HasValue)
|
||||
.Add(FieldIdentifier, EditContext)
|
||||
.ToString();
|
||||
|
||||
}
|
||||
|
||||
private async Task SetDay(DateTime newValue)
|
||||
@@ -1057,8 +1068,15 @@ namespace Radzen.Blazor
|
||||
shouldClose = !visible;
|
||||
}
|
||||
|
||||
var disabledChanged = parameters.DidParameterChange(nameof(Disabled), Disabled);
|
||||
|
||||
await base.SetParametersAsync(parameters);
|
||||
|
||||
if (disabledChanged)
|
||||
{
|
||||
FormFieldContext?.DisabledChanged(Disabled);
|
||||
}
|
||||
|
||||
if (shouldClose && !firstRender && IsJSRuntimeAvailable)
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.destroyPopup", PopupID);
|
||||
|
||||
@@ -5,7 +5,6 @@ using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Dynamic.Core;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
@@ -354,6 +353,7 @@ namespace Radzen.Blazor
|
||||
/// </summary>
|
||||
protected ElementReference popup;
|
||||
|
||||
bool isFirstRender;
|
||||
/// <summary>
|
||||
/// Called when [after render asynchronous].
|
||||
/// </summary>
|
||||
@@ -361,6 +361,8 @@ namespace Radzen.Blazor
|
||||
/// <returns>Task.</returns>
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
isFirstRender = firstRender;
|
||||
|
||||
if (firstRender)
|
||||
{
|
||||
if(Visible && LoadData.HasDelegate && Data == null)
|
||||
@@ -466,10 +468,13 @@ namespace Radzen.Blazor
|
||||
if (query == null)
|
||||
return;
|
||||
|
||||
var filterOperator = FilterOperator == StringFilterOperator.Contains ?
|
||||
Radzen.FilterOperator.Contains :
|
||||
FilterOperator == StringFilterOperator.StartsWith ? Radzen.FilterOperator.StartsWith :
|
||||
FilterOperator == StringFilterOperator.EndsWith ? Radzen.FilterOperator.EndsWith : Radzen.FilterOperator.Equals;
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
{
|
||||
string filterCaseSensitivityOperator = FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ? ".ToLower()" : "";
|
||||
|
||||
if (AllowFilteringByAllStringColumns && grid != null)
|
||||
{
|
||||
if (AllowFilteringByWord)
|
||||
@@ -478,16 +483,16 @@ namespace Radzen.Blazor
|
||||
|
||||
foreach (string word in words)
|
||||
{
|
||||
query = query.Where(DynamicLinqCustomTypeProvider.ParsingConfig, string.Join(" || ", grid.ColumnsCollection.Where(c => c.Filterable && IsColumnFilterPropertyTypeString(c))
|
||||
.Select(c => GetPropertyFilterExpression(c.GetFilterProperty(), filterCaseSensitivityOperator))),
|
||||
FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ? word.ToLower() : word);
|
||||
query = query.Where(grid.ColumnsCollection.Where(c => c.Filterable && IsColumnFilterPropertyTypeString(c))
|
||||
.Select(c => new FilterDescriptor() { Property = c.GetFilterProperty(), FilterValue = word, FilterOperator = filterOperator }),
|
||||
LogicalFilterOperator.Or, FilterCaseSensitivity);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
query = query.Where(DynamicLinqCustomTypeProvider.ParsingConfig, string.Join(" || ", grid.ColumnsCollection.Where(c => c.Filterable && IsColumnFilterPropertyTypeString(c))
|
||||
.Select(c => GetPropertyFilterExpression(c.GetFilterProperty(), filterCaseSensitivityOperator))),
|
||||
FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ? searchText.ToLower() : searchText);
|
||||
query = query.Where(grid.ColumnsCollection.Where(c => c.Filterable && IsColumnFilterPropertyTypeString(c))
|
||||
.Select(c => new FilterDescriptor() { Property = c.GetFilterProperty(), FilterValue = searchText, FilterOperator = filterOperator }),
|
||||
LogicalFilterOperator.Or, FilterCaseSensitivity);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -498,26 +503,24 @@ namespace Radzen.Blazor
|
||||
|
||||
foreach (string word in words)
|
||||
{
|
||||
query = query.Where(DynamicLinqCustomTypeProvider.ParsingConfig, $"{GetPropertyFilterExpression(TextProperty, filterCaseSensitivityOperator)}",
|
||||
FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ? word.ToLower() : word);
|
||||
query = query.Where(TextProperty, word, FilterOperator, FilterCaseSensitivity);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
query = query.Where(DynamicLinqCustomTypeProvider.ParsingConfig, $"{GetPropertyFilterExpression(TextProperty, filterCaseSensitivityOperator)}",
|
||||
FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ? searchText.ToLower() : searchText);
|
||||
query = query.Where(TextProperty, searchText, FilterOperator, FilterCaseSensitivity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(args.OrderBy))
|
||||
{
|
||||
query = query.OrderBy(DynamicLinqCustomTypeProvider.ParsingConfig, args.OrderBy);
|
||||
query = query.OrderBy(args.OrderBy);
|
||||
}
|
||||
|
||||
count = await Task.FromResult(query.Count());
|
||||
count = await Task.FromResult(query.Cast<object>().Count());
|
||||
|
||||
pagedData = await Task.FromResult(QueryableExtension.ToList(query.Skip(skip.HasValue ? skip.Value : 0).Take(args.Top.HasValue ? args.Top.Value : PageSize)).Cast<object>());
|
||||
pagedData = await Task.FromResult(query.Cast<object>().Skip(skip.HasValue ? skip.Value : 0).Take(args.Top.HasValue ? args.Top.Value : PageSize).ToList());
|
||||
|
||||
_internalView = query;
|
||||
|
||||
@@ -584,7 +587,11 @@ namespace Radzen.Blazor
|
||||
|
||||
if (!string.IsNullOrEmpty(ValueProperty))
|
||||
{
|
||||
var item = Query.Where(DynamicLinqCustomTypeProvider.ParsingConfig, $@"{ValueProperty} == @0", value).FirstOrDefault();
|
||||
var item = Query.Where(new FilterDescriptor[]
|
||||
{
|
||||
new FilterDescriptor() { Property = ValueProperty, FilterValue = value }
|
||||
}, LogicalFilterOperator.And, FilterCaseSensitivity.Default).FirstOrDefault();
|
||||
|
||||
if (item != null && SelectedItem != item)
|
||||
{
|
||||
SelectedItem = item;
|
||||
@@ -605,6 +612,15 @@ namespace Radzen.Blazor
|
||||
SelectedItemChanged.InvokeAsync(SelectedItem);
|
||||
selectedItems.Clear();
|
||||
selectedItems.Add(SelectedItem);
|
||||
try
|
||||
{
|
||||
if (grid != null && !isFirstRender)
|
||||
{
|
||||
InvokeAsync(() => grid.SelectRow(SelectedItem, false));
|
||||
JSRuntime.InvokeAsync<int[]>("Radzen.focusTableRow", grid.GridId(), "ArrowDown", Items.ToList().IndexOf(SelectedItem) - 1, null);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -617,8 +633,12 @@ namespace Radzen.Blazor
|
||||
{
|
||||
foreach (object v in valueList)
|
||||
{
|
||||
var item = Query.Where(DynamicLinqCustomTypeProvider.ParsingConfig, $@"{ValueProperty} == @0", v).FirstOrDefault();
|
||||
if (item != null && !selectedItems.AsQueryable().Where(DynamicLinqCustomTypeProvider.ParsingConfig, $@"object.Equals(it.{ValueProperty},@0)", v).Any())
|
||||
var item = Query.Where(new FilterDescriptor[]
|
||||
{
|
||||
new FilterDescriptor() { Property = ValueProperty, FilterValue = v }
|
||||
}, LogicalFilterOperator.And, FilterCaseSensitivity.Default).FirstOrDefault();
|
||||
|
||||
if (item != null && !selectedItems.AsQueryable().Where(i => object.Equals(GetItemOrValueFromProperty(i, ValueProperty), v)).Any())
|
||||
{
|
||||
selectedItems.Add(item);
|
||||
}
|
||||
|
||||
@@ -28,6 +28,13 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public string AlternateText { get; set; } = "gravatar";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the size. Defaulted to 36 (pixels).
|
||||
/// </summary>
|
||||
/// <value>The size of the image in pixels.</value>
|
||||
[Parameter]
|
||||
public int Size { get; set; } = 36;
|
||||
|
||||
/// <summary>
|
||||
/// Gets gravatar URL.
|
||||
/// </summary>
|
||||
@@ -38,9 +45,8 @@ namespace Radzen.Blazor
|
||||
var md5Email = MD5.Calculate(System.Text.Encoding.ASCII.GetBytes(Email != null ? Email : ""));
|
||||
|
||||
var style = "retro";
|
||||
var width = "36";
|
||||
|
||||
return $"https://secure.gravatar.com/avatar/{md5Email}?d={style}&s={width}";
|
||||
return $"https://secure.gravatar.com/avatar/{md5Email}?d={style}&s={Size}";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
@using Radzen.Blazor.Rendering
|
||||
@inherits RadzenHtmlEditorColorBase
|
||||
|
||||
<EditorColorPicker Title=@Title @bind-Value=@Value Icon="opacity" Change=@OnChange ShowHSV=@ShowHSV ShowRGBA=@ShowRGBA
|
||||
<EditorColorPicker Title=@Title @bind-Value=@value Icon="opacity" Change=@OnChange ShowHSV=@ShowHSV ShowRGBA=@ShowRGBA
|
||||
ShowColors=@ShowColors ShowButton=@ShowButton HexText=@HexText RedText=@RedText GreenText=@GreenText
|
||||
BlueText=@BlueText AlphaText=@AlphaText ButtonText=@ButtonText>
|
||||
@ChildContent
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
@@ -24,7 +25,7 @@ namespace Radzen.Blazor
|
||||
/// Specifies the default background color. Set to <c>"rgb(0, 0, 255)"</c> by default;
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string Value { get; set; } = "rgb(0, 0, 255)";
|
||||
public override string Value { get; set; } = "rgb(0, 0, 255)";
|
||||
/// <summary>
|
||||
/// Specifies the title (tooltip) displayed when the user hovers the tool. Set to <c>"Background color"</c> by default.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
@using Radzen.Blazor.Rendering
|
||||
@inherits RadzenHtmlEditorColorBase
|
||||
|
||||
<EditorColorPicker Title=@Title @bind-Value=@Value Icon="title" Change=@OnChange ShowHSV=@ShowHSV ShowRGBA=@ShowRGBA
|
||||
<EditorColorPicker Title=@Title @bind-Value=@value Icon="title" Change=@OnChange ShowHSV=@ShowHSV ShowRGBA=@ShowRGBA
|
||||
ShowColors=@ShowColors ShowButton=@ShowButton HexText=@HexText RedText=@RedText GreenText=@GreenText
|
||||
BlueText=@BlueText AlphaText=@AlphaText ButtonText=@ButtonText>
|
||||
@ChildContent
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace Radzen.Blazor
|
||||
/// Specifies the default text color. Set to <c>"rgb(255, 0, 0)"</c> by default;
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string Value { get; set; } = "rgb(255, 0, 0)";
|
||||
public override string Value { get; set; } = "rgb(255, 0, 0)";
|
||||
/// <summary>
|
||||
/// Specifies the title (tooltip) displayed when the user hovers the tool. Set to <c>"Text color"</c> by default.
|
||||
/// </summary>
|
||||
|
||||
@@ -84,5 +84,36 @@ namespace Radzen.Blazor
|
||||
{
|
||||
await Editor.ExecuteCommandAsync(CommandName, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The default value of the color picker.
|
||||
/// </summary>
|
||||
public abstract string Value { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The internal state of the component.
|
||||
/// </summary>
|
||||
protected string value;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
value = Value;
|
||||
|
||||
base.OnInitialized();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async Task SetParametersAsync(ParameterView parameters)
|
||||
{
|
||||
var valueChanged = parameters.DidParameterChange(nameof(Value), Value);
|
||||
|
||||
await base.SetParametersAsync(parameters);
|
||||
|
||||
if (valueChanged)
|
||||
{
|
||||
value = Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,6 +216,8 @@ namespace Radzen.Blazor
|
||||
{
|
||||
_value = value;
|
||||
}
|
||||
|
||||
stringValue = $"{value}";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -394,6 +396,8 @@ namespace Radzen.Blazor
|
||||
|
||||
newValue = ApplyMinMax(newValue);
|
||||
|
||||
stringValue = $"{newValue}";
|
||||
|
||||
if (EqualityComparer<TValue>.Default.Equals(Value, newValue))
|
||||
{
|
||||
await JSRuntime.InvokeAsync<string>("Radzen.setInputValue", input, FormattedValue);
|
||||
@@ -457,8 +461,14 @@ namespace Radzen.Blazor
|
||||
var converter = TypeDescriptor.GetConverter(typeof(TValue));
|
||||
if (converter.CanConvertTo(typeof(decimal)))
|
||||
return (decimal)converter.ConvertTo(null, Culture, input, typeof(decimal));
|
||||
|
||||
return (decimal)ConvertType.ChangeType(input, typeof(decimal));
|
||||
try
|
||||
{
|
||||
return (decimal)ConvertType.ChangeType(input, typeof(decimal), Culture);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return decimal.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
private TValue ConvertFromDecimal(decimal? input)
|
||||
@@ -472,7 +482,7 @@ namespace Radzen.Blazor
|
||||
return (TValue)converter.ConvertFrom(null, Culture, input);
|
||||
}
|
||||
|
||||
return (TValue)ConvertType.ChangeType(input, typeof(TValue));
|
||||
return (TValue)ConvertType.ChangeType(input, typeof(TValue), Culture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -13,19 +13,19 @@
|
||||
}
|
||||
<RadzenListBox @bind-Value=@selectedSourceItems Data="@source" Multiple="@Multiple" @bind-SearchText=@sourceSearchText
|
||||
FilterAsYouType=true FilterCaseSensitivity=FilterCaseSensitivity.CaseInsensitive
|
||||
TextProperty="@TextProperty" AllowFiltering=@AllowFiltering ItemRender="@OnSourceItemRender"
|
||||
Template=@ListBoxTemplate Placeholder="@(SourcePlaceholder ?? Placeholder)" SelectAllText="@SelectAllText"
|
||||
TextProperty="@TextProperty" DisabledProperty="@DisabledProperty" AllowFiltering=@AllowFiltering ItemRender="@OnSourceItemRender"
|
||||
Template=@ListBoxTemplate Placeholder="@(SourcePlaceholder ?? Placeholder)" SelectAllText="@SelectAllText" AllowSelectAll="@AllowSelectAll"
|
||||
Disabled=@(Disabled || Source == null || (Source != null && !Source.Any()))
|
||||
/>
|
||||
</RadzenStack>
|
||||
<RadzenStack Orientation="@(Orientation == Orientation.Vertical ? Orientation.Horizontal : Orientation.Vertical)" JustifyContent="@ButtonJustifyContent" Gap="@ButtonGap" class="rz-picklist-buttons">
|
||||
<RadzenButton Icon="keyboard_arrow_right" title="@SelectedSourceToTargetTitle" Click="@SelectedSourceToTarget" Disabled=@(Disabled || selectedSourceItems == null || (Multiple && (selectedSourceItems as IEnumerable)?.Cast<object>().Any() != true))
|
||||
<RadzenButton Icon="@SelectedSourceToTargetIcon" title="@SelectedSourceToTargetTitle" Click="@SelectedSourceToTarget" Disabled=@(Disabled || selectedSourceItems == null || (Multiple && (selectedSourceItems as IEnumerable)?.Cast<object>().Any() != true))
|
||||
ButtonStyle="@ButtonStyle" Size="@ButtonSize" Variant="@ButtonVariant" Shade="@ButtonShade" />
|
||||
<RadzenButton Icon="keyboard_arrow_left" title="@SelectedTargetToSourceTitle" Click="@SelectedTargetToSource" Disabled=@(Disabled || selectedTargetItems == null || (Multiple && (selectedTargetItems as IEnumerable)?.Cast<object>().Any() != true))
|
||||
<RadzenButton Icon="@SelectedTargetToSourceIcon" title="@SelectedTargetToSourceTitle" Click="@SelectedTargetToSource" Disabled=@(Disabled || selectedTargetItems == null || (Multiple && (selectedTargetItems as IEnumerable)?.Cast<object>().Any() != true))
|
||||
ButtonStyle="@ButtonStyle" Size="@ButtonSize" Variant="@ButtonVariant" Shade="@ButtonShade"/>
|
||||
<RadzenButton Icon="keyboard_double_arrow_right" title="@SourceToTargetTitle" Click="@SourceToTarget" Disabled=@(Disabled || source == null || (source != null && !source.Any()))
|
||||
<RadzenButton Icon="@SourceToTargetIcon" title="@SourceToTargetTitle" Click="@SourceToTarget" Disabled=@(Disabled || source == null || (source != null && !source.Any()))
|
||||
ButtonStyle="@ButtonStyle" Size="@ButtonSize" Variant="@ButtonVariant" Shade="@ButtonShade" Visible=@(AllowMoveAll && AllowMoveAllSourceToTarget) />
|
||||
<RadzenButton Icon="keyboard_double_arrow_left" title="@TargetToSourceTitle" Click="@TargetToSource" Disabled=@(Disabled || target == null|| (target != null && !target.Any()))
|
||||
<RadzenButton Icon="@TargetToSourceIcon" title="@TargetToSourceTitle" Click="@TargetToSource" Disabled=@(Disabled || target == null|| (target != null && !target.Any()))
|
||||
ButtonStyle="@ButtonStyle" Size="@ButtonSize" Variant="@ButtonVariant" Shade="@ButtonShade" Visible=@(AllowMoveAll && AllowMoveAllTargetToSource)/>
|
||||
</RadzenStack>
|
||||
<RadzenStack class="rz-picklist-target-wrapper">
|
||||
@@ -35,8 +35,8 @@
|
||||
}
|
||||
<RadzenListBox @bind-Value=@selectedTargetItems Data="@target" Multiple="@Multiple" @bind-SearchText=@targetSearchText
|
||||
FilterAsYouType=true FilterCaseSensitivity=FilterCaseSensitivity.CaseInsensitive
|
||||
TextProperty="@TextProperty" AllowFiltering=@AllowFiltering ItemRender="@OnTargetItemRender"
|
||||
Template=@ListBoxTemplate Placeholder="@(TargetPlaceholder ?? Placeholder)" SelectAllText="@SelectAllText"
|
||||
TextProperty="@TextProperty" DisabledProperty="@DisabledProperty" AllowFiltering=@AllowFiltering ItemRender="@OnTargetItemRender"
|
||||
Template=@ListBoxTemplate Placeholder="@(TargetPlaceholder ?? Placeholder)" SelectAllText="@SelectAllText" AllowSelectAll="@AllowSelectAll"
|
||||
Disabled=@(Disabled || Target == null|| (Target != null && !Target.Any()))
|
||||
/>
|
||||
</RadzenStack>
|
||||
|
||||
@@ -42,6 +42,13 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public bool Multiple { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether selecting all items is allowed.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if selecting all items is allowed; otherwise, <c>false</c>.</value>
|
||||
[Parameter]
|
||||
public bool AllowSelectAll { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether component is disabled.
|
||||
/// </summary>
|
||||
@@ -91,6 +98,13 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public string TextProperty { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the disabled property
|
||||
/// </summary>
|
||||
/// <value>The disabled property.</value>
|
||||
[Parameter]
|
||||
public string DisabledProperty { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the source template
|
||||
/// </summary>
|
||||
@@ -231,6 +245,34 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public string SelectedTargetToSourceTitle { get; set; } = "Move selected target items to source collection";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the source to target icon
|
||||
/// </summary>
|
||||
/// <value>The source to target icon.</value>
|
||||
[Parameter]
|
||||
public string SourceToTargetIcon { get; set; } = "keyboard_double_arrow_right";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the selected source to target icon
|
||||
/// </summary>
|
||||
/// <value>The selected source to target icon.</value>
|
||||
[Parameter]
|
||||
public string SelectedSourceToTargetIcon { get; set; } = "keyboard_arrow_right";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the target to source icon
|
||||
/// </summary>
|
||||
/// <value>The target to source icon.</value>
|
||||
[Parameter]
|
||||
public string TargetToSourceIcon { get; set; } = "keyboard_double_arrow_left";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the selected target to source icon
|
||||
/// </summary>
|
||||
/// <value>The selected target to source icon.</value>
|
||||
[Parameter]
|
||||
public string SelectedTargetToSourceIcon { get; set; } = "keyboard_arrow_left";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the final CSS style rendered by the component. Combines it with a <c>style</c> custom attribute.
|
||||
/// </summary>
|
||||
|
||||
@@ -12,27 +12,30 @@
|
||||
@ChildContent
|
||||
</CascadingValue>
|
||||
<div @ref=Element style=@Style @attributes=@Attributes class=@GetCssClass() id=@GetId()>
|
||||
<div class="rz-scheduler-nav">
|
||||
<div class="rz-scheduler-nav-prev-next">
|
||||
<button tabindex="0" class="rz-button rz-prev" @onclick=@OnPrev title="@PrevText"><RadzenIcon Icon="chevron_left" /></button>
|
||||
<button tabindex="0" class="rz-button rz-next" @onclick=@OnNext title="@NextText"><RadzenIcon Icon="chevron_right" /></button>
|
||||
<button tabindex="0" class="rz-button rz-today" @onclick=@OnToday title="@TodayText">@TodayText</button>
|
||||
</div>
|
||||
<div class="rz-scheduler-nav-title">@SelectedView?.Title</div>
|
||||
<div class="rz-scheduler-nav-views">
|
||||
@if (NavigationTemplate != null)
|
||||
{
|
||||
@NavigationTemplate
|
||||
}
|
||||
else
|
||||
{
|
||||
@foreach (var view in Views)
|
||||
{
|
||||
<RadzenButton Click=@(args => OnChangeView(view)) Icon=@view.Icon Text=@view.Text class="@($"{(IsSelected(view) ? " rz-state-active" : "")}")" />
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
@SelectedView?.Render()
|
||||
@if (ShowHeader)
|
||||
{
|
||||
<div class="rz-scheduler-nav">
|
||||
<div class="rz-scheduler-nav-prev-next">
|
||||
<button tabindex="0" class="rz-button rz-prev" @onclick=@OnPrev title="@PrevText"><RadzenIcon Icon="chevron_left" /></button>
|
||||
<button tabindex="0" class="rz-button rz-next" @onclick=@OnNext title="@NextText"><RadzenIcon Icon="chevron_right" /></button>
|
||||
<button tabindex="0" class="rz-button rz-today" @onclick=@OnToday title="@TodayText">@TodayText</button>
|
||||
</div>
|
||||
<div class="rz-scheduler-nav-title">@SelectedView?.Title</div>
|
||||
<div class="rz-scheduler-nav-views">
|
||||
@if (NavigationTemplate != null)
|
||||
{
|
||||
@NavigationTemplate
|
||||
}
|
||||
else
|
||||
{
|
||||
@foreach (var view in Views)
|
||||
{
|
||||
<RadzenButton Click=@(args => OnChangeView(view)) Icon=@view.Icon Text=@view.Text class="@($"{(IsSelected(view) ? " rz-state-active" : "")}")" />
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@SelectedView?.Render()
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ using Microsoft.JSInterop;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Dynamic.Core;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
@@ -145,6 +144,13 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public string TextProperty { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies whether to Show or Hide the Scheduler Header. Defaults to true />.
|
||||
/// </summary>
|
||||
/// <value>Show / hide header</value>
|
||||
[Parameter]
|
||||
public bool ShowHeader { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// A callback that will be invoked when the user clicks a slot in the current view. Commonly used to add new appointments.
|
||||
/// </summary>
|
||||
@@ -188,9 +194,9 @@ namespace Radzen.Blazor
|
||||
/// <RadzenScheduler Data=@appointments MonthSelect=@OnMonthSelect>
|
||||
/// </RadzenScheduler>
|
||||
/// @code {
|
||||
/// void OnMonthSelect(SchedulerTodaySelectEventArgs args)
|
||||
/// void OnMonthSelect(SchedulerMonthSelectEventArgs args)
|
||||
/// {
|
||||
/// args.Month = DateTime.Month.AddMonth(1);
|
||||
/// var selectedMonth = args.MonthStart.Month;
|
||||
/// }
|
||||
/// }
|
||||
/// </code>
|
||||
@@ -198,6 +204,24 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public EventCallback<SchedulerMonthSelectEventArgs> MonthSelect { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A callback that will be invoked when the user clicks a day header button or the day number in a MonthView.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// <RadzenScheduler Data=@appointments DaySelect=@OnDaySelect>
|
||||
/// </RadzenScheduler>
|
||||
/// @code {
|
||||
/// void OnDaySelect(SchedulerDaySelectEventArgs args)
|
||||
/// {
|
||||
/// var selectedDay = args.Day;
|
||||
/// }
|
||||
/// }
|
||||
/// </code>
|
||||
/// </example>
|
||||
[Parameter]
|
||||
public EventCallback<SchedulerDaySelectEventArgs> DaySelect { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A callback that will be invoked when the user clicks an appointment in the current view. Commonly used to edit existing appointments.
|
||||
/// </summary>
|
||||
@@ -387,6 +411,12 @@ namespace Radzen.Blazor
|
||||
await MonthSelect.InvokeAsync(new SchedulerMonthSelectEventArgs { MonthStart = monthStart, Appointments = appointments, View = SelectedView });
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task SelectDay(DateTime day, IEnumerable<AppointmentData> appointments)
|
||||
{
|
||||
await DaySelect.InvokeAsync(new SchedulerDaySelectEventArgs { Day = day, Appointments = appointments, View = SelectedView });
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<bool> SelectMore(DateTime start, DateTime end, IEnumerable<AppointmentData> appointments)
|
||||
{
|
||||
@@ -580,7 +610,7 @@ namespace Radzen.Blazor
|
||||
{
|
||||
if (SelectedView != null)
|
||||
{
|
||||
await LoadData.InvokeAsync(new SchedulerLoadDataEventArgs { Start = SelectedView.StartDate, End = SelectedView.EndDate });
|
||||
await LoadData.InvokeAsync(new SchedulerLoadDataEventArgs { Start = SelectedView.StartDate, End = SelectedView.EndDate, View = SelectedView });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -611,10 +641,22 @@ namespace Radzen.Blazor
|
||||
rangeStart = start;
|
||||
rangeEnd = end;
|
||||
|
||||
var predicate = $"{EndProperty} >= @0 && {StartProperty} < @1";
|
||||
|
||||
appointments = Data.AsQueryable()
|
||||
.Where(DynamicLinqCustomTypeProvider.ParsingConfig, predicate, start, end)
|
||||
.Where(
|
||||
new FilterDescriptor[] {
|
||||
new FilterDescriptor
|
||||
{
|
||||
Property = StartProperty,
|
||||
FilterValue = start,
|
||||
FilterOperator = FilterOperator.GreaterThanOrEquals
|
||||
},
|
||||
new FilterDescriptor
|
||||
{
|
||||
Property = EndProperty,
|
||||
FilterValue = end,
|
||||
FilterOperator = FilterOperator.LessThanOrEquals
|
||||
}
|
||||
}, LogicalFilterOperator.And, FilterCaseSensitivity.Default)
|
||||
.ToList()
|
||||
.Select(item => new AppointmentData { Start = startGetter(item), End = endGetter(item), Text = textGetter(item), Data = item });
|
||||
|
||||
|
||||
@@ -15,7 +15,27 @@
|
||||
{
|
||||
<div @ref="@Element" style="@Style" @attributes="Attributes" class="@GetCssClass()" id="@GetId()">
|
||||
@foreach (var item in allItems.Where(i => i.Visible))
|
||||
{<div @ref="@item.Element" id="@item.GetItemId()" @onclick="@(args => SelectItem(item))" @onkeypress="@(args => OnKeyPress(args, SelectItem(item)))" @onkeypress:preventDefault=preventKeyPress @onkeypress:stopPropagation @attributes="item.Attributes" style="@item.Style"
|
||||
class=@ButtonClassList(item) aria-label="@item.Text" tabindex="@(Disabled || item.Disabled ? "-1" : $"{TabIndex}")">@if(item.Template != null){ @item.Template(item)}else{@if (!string.IsNullOrEmpty(item.Icon)){<i class="notranslate rzi rz-navigation-item-icon" style="margin-right:2px;@(!string.IsNullOrEmpty(item.IconColor) ? $"color:{item.IconColor}" : "")">@((MarkupString)item.Icon)</i>}@if (!string.IsNullOrEmpty(item.Image)){<img class="rz-navigation-item-icon" src="@item.Image" style="@item.ImageStyle" alt=@item.ImageAlternateText/>}<span class="rz-button-text">@item.Text</span>}</div>}
|
||||
{
|
||||
<div @ref="@item.Element" id="@item.GetItemId()"
|
||||
@onclick="@(args => SelectItem(item))" @onkeypress="@(args => OnKeyPress(args, SelectItem(item)))" @onkeypress:preventDefault=preventKeyPress @onkeypress:stopPropagation
|
||||
@attributes="item.Attributes" style="@item.Style" class=@ButtonClassList(item) aria-label="@item.Text" tabindex="@(Disabled || item.Disabled ? "-1" : $"{TabIndex}")">
|
||||
@if (item.Template != null)
|
||||
{
|
||||
@item.Template(item)
|
||||
}
|
||||
else
|
||||
{
|
||||
@if (!string.IsNullOrEmpty(item.Icon))
|
||||
{
|
||||
<i class="notranslate rzi rz-navigation-item-icon" style="margin-right:2px;@(!string.IsNullOrEmpty(item.IconColor) ? $"color:{item.IconColor}" : "")">@((MarkupString)item.Icon)</i>
|
||||
}
|
||||
@if (!string.IsNullOrEmpty(item.Image))
|
||||
{
|
||||
<img class="rz-navigation-item-icon" src="@item.Image" style="@item.ImageStyle" alt=@item.ImageAlternateText/>
|
||||
}
|
||||
<span class="rz-button-text">@item.Text</span>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using Microsoft.JSInterop;
|
||||
using Radzen.Blazor.Rendering;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Dynamic.Core;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
@@ -34,16 +32,24 @@ namespace Radzen.Blazor
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the size.
|
||||
/// Gets or sets the size. Set to <c>ButtonSize.Medium</c> by default.
|
||||
/// </summary>
|
||||
/// <value>The size.</value>
|
||||
[Parameter]
|
||||
public ButtonSize Size { get; set; } = ButtonSize.Medium;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the orientation. Set to <c>Orientation.Horizontal</c> by default.
|
||||
/// </summary>
|
||||
/// <value>The orientation.</value>
|
||||
[Parameter]
|
||||
public Orientation Orientation { get; set; } = Orientation.Horizontal;
|
||||
|
||||
ClassList ButtonClassList(RadzenSelectBarItem item) => ClassList.Create($"rz-button rz-button-{getButtonSize()} rz-button-text-only")
|
||||
.Add("rz-state-active", IsSelected(item))
|
||||
.AddDisabled(Disabled || item.Disabled);
|
||||
|
||||
ClassList ButtonClassList(RadzenSelectBarItem item)
|
||||
=> ClassList.Create($"rz-button rz-button-{getButtonSize()} rz-button-text-only")
|
||||
.Add("rz-state-active", IsSelected(item))
|
||||
.AddDisabled(Disabled || item.Disabled);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value property.
|
||||
@@ -98,9 +104,10 @@ namespace Radzen.Blazor
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override string GetComponentCssClass()
|
||||
{
|
||||
return GetClassList("rz-selectbutton rz-buttonset").Add($"rz-buttonset-{items.Count}").ToString();
|
||||
}
|
||||
=> GetClassList("rz-selectbutton rz-buttonset")
|
||||
.Add($"rz-selectbutton-{(Orientation == Orientation.Vertical ? "vertical" : "horizontal")}")
|
||||
.Add($"rz-buttonset-{items.Count}")
|
||||
.ToString();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this <see cref="RadzenSelectBar{TValue}"/> is multiple.
|
||||
@@ -180,7 +187,7 @@ namespace Radzen.Blazor
|
||||
/// Selects the item.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
protected async System.Threading.Tasks.Task SelectItem(RadzenSelectBarItem item)
|
||||
protected async Task SelectItem(RadzenSelectBarItem item)
|
||||
{
|
||||
if (Disabled || item.Disabled)
|
||||
return;
|
||||
@@ -189,7 +196,7 @@ namespace Radzen.Blazor
|
||||
{
|
||||
var type = typeof(TValue).IsGenericType ? typeof(TValue).GetGenericArguments()[0] : typeof(TValue);
|
||||
|
||||
var selectedValues = Value != null ? QueryableExtension.ToList(((IEnumerable)Value).AsQueryable().Cast(type)) : new List<dynamic>();
|
||||
var selectedValues = Value != null ? new List<dynamic>(((IEnumerable)Value).Cast<dynamic>()) : new List<dynamic>();
|
||||
|
||||
if (!selectedValues.Contains(item.Value))
|
||||
{
|
||||
|
||||
@@ -5,7 +5,6 @@ using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Dynamic.Core;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
|
||||
@@ -8,6 +8,6 @@
|
||||
<div class="rz-helper-hidden-accessible">
|
||||
<input type="checkbox" name="@Name" id="@Name" checked="@Value" value="@ValueAsString" tabindex="-1" aria-checked="@(Value.ToString().ToLowerInvariant())" @attributes=@InputAttributes>
|
||||
</div>
|
||||
<span class="rz-switch-circle@(Disabled ? " rz-disabled" : "")"></span>
|
||||
<span class="rz-switch-circle@(Disabled ? " rz-disabled" : ReadOnly ? " rz-readonly" : "")"></span>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -15,6 +15,13 @@ namespace Radzen.Blazor
|
||||
/// </example>
|
||||
public partial class RadzenSwitch : FormComponent<bool>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether is read only.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if is read only; otherwise, <c>false</c>.</value>
|
||||
[Parameter]
|
||||
public bool ReadOnly { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override string GetComponentCssClass()
|
||||
{
|
||||
@@ -35,7 +42,7 @@ namespace Radzen.Blazor
|
||||
/// </summary>
|
||||
public async System.Threading.Tasks.Task Toggle()
|
||||
{
|
||||
if (Disabled)
|
||||
if (Disabled || ReadOnly)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
13
Radzen.Blazor/RadzenTable.razor
Normal file
13
Radzen.Blazor/RadzenTable.razor
Normal file
@@ -0,0 +1,13 @@
|
||||
@inherits RadzenComponentWithChildren
|
||||
@if (Visible)
|
||||
{
|
||||
<div @ref="@Element" style="@Style" @attributes="Attributes" class="@GetCssClass()" id="@GetId()">
|
||||
<div class="rz-data-grid-data">
|
||||
<table class="@GetTableCssClass()">
|
||||
<CascadingValue Value=this>
|
||||
@ChildContent
|
||||
</CascadingValue>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
57
Radzen.Blazor/RadzenTable.razor.cs
Normal file
57
Radzen.Blazor/RadzenTable.razor.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Routing;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using Microsoft.JSInterop;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// RadzenTable component.
|
||||
/// </summary>
|
||||
public partial class RadzenTable : RadzenComponentWithChildren
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the grid lines.
|
||||
/// </summary>
|
||||
/// <value>The grid lines.</value>
|
||||
[Parameter]
|
||||
public DataGridGridLines GridLines { get; set; } = DataGridGridLines.Default;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether RadzenTable should use alternating row styles.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if RadzenTable is using alternating row styles; otherwise, <c>false</c>.</value>
|
||||
[Parameter]
|
||||
public bool AllowAlternatingRows { get; set; } = true;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override string GetComponentCssClass()
|
||||
{
|
||||
return $"rz-data-grid rz-datatable rz-datatable-scrollable {(CurrentStyle.ContainsKey("height") ? "rz-has-height" : "")}".Trim();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the table CSS classes.
|
||||
/// </summary>
|
||||
protected virtual string GetTableCssClass()
|
||||
{
|
||||
var styles = new List<string>(new string[] { "rz-grid-table", "rz-grid-table-fixed" });
|
||||
|
||||
if (AllowAlternatingRows)
|
||||
{
|
||||
styles.Add("rz-grid-table-striped");
|
||||
}
|
||||
|
||||
if (GridLines != DataGridGridLines.Default)
|
||||
{
|
||||
styles.Add($"rz-grid-gridlines-{Enum.GetName(typeof(DataGridGridLines), GridLines).ToLower()}");
|
||||
}
|
||||
|
||||
return string.Join(" ", styles);
|
||||
}
|
||||
}
|
||||
}
|
||||
9
Radzen.Blazor/RadzenTableBody.razor
Normal file
9
Radzen.Blazor/RadzenTableBody.razor
Normal file
@@ -0,0 +1,9 @@
|
||||
@inherits RadzenComponentWithChildren
|
||||
@if (Visible)
|
||||
{
|
||||
<tbody @ref="@Element" style="@Style" @attributes="Attributes" class="@GetCssClass()" id="@GetId()">
|
||||
<CascadingValue Value=this>
|
||||
@ChildContent
|
||||
</CascadingValue>
|
||||
</tbody>
|
||||
}
|
||||
39
Radzen.Blazor/RadzenTableBody.razor.cs
Normal file
39
Radzen.Blazor/RadzenTableBody.razor.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// RadzenTableBody component.
|
||||
/// </summary>
|
||||
public partial class RadzenTableBody : RadzenComponentWithChildren
|
||||
{
|
||||
List<RadzenTableRow> rows = new List<RadzenTableRow>();
|
||||
|
||||
/// <summary>
|
||||
/// Adds the row.
|
||||
/// </summary>
|
||||
/// <param name="row">The row.</param>
|
||||
public void AddRow(RadzenTableRow row)
|
||||
{
|
||||
if (rows.IndexOf(row) == -1)
|
||||
{
|
||||
rows.Add(row);
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the row.
|
||||
/// </summary>
|
||||
/// <param name="row">The row.</param>
|
||||
public void RemoveRow(RadzenTableRow row)
|
||||
{
|
||||
if (rows.IndexOf(row) != -1)
|
||||
{
|
||||
rows.Remove(row);
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Radzen.Blazor/RadzenTableCell.razor
Normal file
11
Radzen.Blazor/RadzenTableCell.razor
Normal file
@@ -0,0 +1,11 @@
|
||||
@inherits RadzenComponentWithChildren
|
||||
@if (Visible)
|
||||
{
|
||||
<td @ref="@Element" style="@Style" @attributes="Attributes" class="@GetCssClass()" id="@GetId()">
|
||||
<span class="rz-cell-data">
|
||||
<CascadingValue Value=this>
|
||||
@ChildContent
|
||||
</CascadingValue>
|
||||
</span>
|
||||
</td>
|
||||
}
|
||||
40
Radzen.Blazor/RadzenTableCell.razor.cs
Normal file
40
Radzen.Blazor/RadzenTableCell.razor.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// RadzenTableRow component.
|
||||
/// </summary>
|
||||
public partial class RadzenTableCell : RadzenComponentWithChildren
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override string GetComponentCssClass()
|
||||
{
|
||||
return "rz-data-cell";
|
||||
}
|
||||
|
||||
RadzenTableRow _row;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the row.
|
||||
/// </summary>
|
||||
/// <value>The row.</value>
|
||||
[CascadingParameter]
|
||||
public RadzenTableRow Row
|
||||
{
|
||||
get
|
||||
{
|
||||
return _row;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_row != value)
|
||||
{
|
||||
_row = value;
|
||||
_row.AddCell(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
9
Radzen.Blazor/RadzenTableHeader.razor
Normal file
9
Radzen.Blazor/RadzenTableHeader.razor
Normal file
@@ -0,0 +1,9 @@
|
||||
@inherits RadzenComponentWithChildren
|
||||
@if (Visible)
|
||||
{
|
||||
<thead @ref="@Element" style="@Style" @attributes="Attributes" class="@GetCssClass()" id="@GetId()">
|
||||
<CascadingValue Value=this>
|
||||
@ChildContent
|
||||
</CascadingValue>
|
||||
</thead>
|
||||
}
|
||||
39
Radzen.Blazor/RadzenTableHeader.razor.cs
Normal file
39
Radzen.Blazor/RadzenTableHeader.razor.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// RadzenTableHeader component.
|
||||
/// </summary>
|
||||
public partial class RadzenTableHeader : RadzenComponentWithChildren
|
||||
{
|
||||
List<RadzenTableHeaderRow> rows = new List<RadzenTableHeaderRow>();
|
||||
|
||||
/// <summary>
|
||||
/// Adds the row.
|
||||
/// </summary>
|
||||
/// <param name="row">The row.</param>
|
||||
public void AddRow(RadzenTableHeaderRow row)
|
||||
{
|
||||
if (rows.IndexOf(row) == -1)
|
||||
{
|
||||
rows.Add(row);
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the row.
|
||||
/// </summary>
|
||||
/// <param name="row">The row.</param>
|
||||
public void RemoveRow(RadzenTableHeaderRow row)
|
||||
{
|
||||
if (rows.IndexOf(row) != -1)
|
||||
{
|
||||
rows.Remove(row);
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
9
Radzen.Blazor/RadzenTableHeaderCell.razor
Normal file
9
Radzen.Blazor/RadzenTableHeaderCell.razor
Normal file
@@ -0,0 +1,9 @@
|
||||
@inherits RadzenComponentWithChildren
|
||||
@if (Visible)
|
||||
{
|
||||
<th @ref="@Element" style="padding: var(--rz-grid-cell-padding);@Style" @attributes="Attributes" class="@GetCssClass()" id="@GetId()">
|
||||
<CascadingValue Value=this>
|
||||
@ChildContent
|
||||
</CascadingValue>
|
||||
</th>
|
||||
}
|
||||
34
Radzen.Blazor/RadzenTableHeaderCell.razor.cs
Normal file
34
Radzen.Blazor/RadzenTableHeaderCell.razor.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// RadzenTableRow component.
|
||||
/// </summary>
|
||||
public partial class RadzenTableHeaderCell : RadzenComponentWithChildren
|
||||
{
|
||||
RadzenTableHeaderRow _row;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the row.
|
||||
/// </summary>
|
||||
/// <value>The row.</value>
|
||||
[CascadingParameter]
|
||||
public RadzenTableHeaderRow Row
|
||||
{
|
||||
get
|
||||
{
|
||||
return _row;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_row != value)
|
||||
{
|
||||
_row = value;
|
||||
_row.AddCell(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
9
Radzen.Blazor/RadzenTableHeaderRow.razor
Normal file
9
Radzen.Blazor/RadzenTableHeaderRow.razor
Normal file
@@ -0,0 +1,9 @@
|
||||
@inherits RadzenComponentWithChildren
|
||||
@if (Visible)
|
||||
{
|
||||
<tr @ref="@Element" style="@Style" @attributes="Attributes" class="@GetCssClass()" id="@GetId()">
|
||||
<CascadingValue Value=this>
|
||||
@ChildContent
|
||||
</CascadingValue>
|
||||
</tr>
|
||||
}
|
||||
62
Radzen.Blazor/RadzenTableHeaderRow.razor.cs
Normal file
62
Radzen.Blazor/RadzenTableHeaderRow.razor.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// RadzenTableRow component.
|
||||
/// </summary>
|
||||
public partial class RadzenTableHeaderRow : RadzenComponentWithChildren
|
||||
{
|
||||
RadzenTableHeader _header;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the table body.
|
||||
/// </summary>
|
||||
/// <value>The table body.</value>
|
||||
[CascadingParameter]
|
||||
public RadzenTableHeader Header
|
||||
{
|
||||
get
|
||||
{
|
||||
return _header;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_header != value)
|
||||
{
|
||||
_header = value;
|
||||
_header.AddRow(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<RadzenTableHeaderCell> cells = new List<RadzenTableHeaderCell>();
|
||||
|
||||
/// <summary>
|
||||
/// Adds the cell.
|
||||
/// </summary>
|
||||
/// <param name="cell">The cell.</param>
|
||||
public void AddCell(RadzenTableHeaderCell cell)
|
||||
{
|
||||
if (cells.IndexOf(cell) == -1)
|
||||
{
|
||||
cells.Add(cell);
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the cell.
|
||||
/// </summary>
|
||||
/// <param name="cell">The cell.</param>
|
||||
public void RemoveCell(RadzenTableHeaderCell cell)
|
||||
{
|
||||
if (cells.IndexOf(cell) != -1)
|
||||
{
|
||||
cells.Remove(cell);
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
9
Radzen.Blazor/RadzenTableRow.razor
Normal file
9
Radzen.Blazor/RadzenTableRow.razor
Normal file
@@ -0,0 +1,9 @@
|
||||
@inherits RadzenComponentWithChildren
|
||||
@if (Visible)
|
||||
{
|
||||
<tr @ref="@Element" style="@Style" @attributes="Attributes" class="@GetCssClass()" id="@GetId()">
|
||||
<CascadingValue Value=this>
|
||||
@ChildContent
|
||||
</CascadingValue>
|
||||
</tr>
|
||||
}
|
||||
68
Radzen.Blazor/RadzenTableRow.razor.cs
Normal file
68
Radzen.Blazor/RadzenTableRow.razor.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// RadzenTableRow component.
|
||||
/// </summary>
|
||||
public partial class RadzenTableRow : RadzenComponentWithChildren
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override string GetComponentCssClass()
|
||||
{
|
||||
return "rz-data-row";
|
||||
}
|
||||
|
||||
RadzenTableBody _body;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the table body.
|
||||
/// </summary>
|
||||
/// <value>The table body.</value>
|
||||
[CascadingParameter]
|
||||
public RadzenTableBody Body
|
||||
{
|
||||
get
|
||||
{
|
||||
return _body;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_body != value)
|
||||
{
|
||||
_body = value;
|
||||
_body.AddRow(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<RadzenTableCell> cells = new List<RadzenTableCell>();
|
||||
|
||||
/// <summary>
|
||||
/// Adds the cell.
|
||||
/// </summary>
|
||||
/// <param name="cell">The cell.</param>
|
||||
public void AddCell(RadzenTableCell cell)
|
||||
{
|
||||
if (cells.IndexOf(cell) == -1)
|
||||
{
|
||||
cells.Add(cell);
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the cell.
|
||||
/// </summary>
|
||||
/// <param name="cell">The cell.</param>
|
||||
public void RemoveCell(RadzenTableCell cell)
|
||||
{
|
||||
if (cells.IndexOf(cell) != -1)
|
||||
{
|
||||
cells.Remove(cell);
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -130,11 +130,20 @@ namespace Radzen.Blazor
|
||||
}
|
||||
}
|
||||
|
||||
private string GetPath()
|
||||
{
|
||||
var uri = new Uri(NavigationManager.Uri);
|
||||
|
||||
var anchor = GetAnchor();
|
||||
|
||||
return $"{uri.PathAndQuery}#{anchor}";
|
||||
}
|
||||
|
||||
protected override void BuildRenderTree(RenderTreeBuilder builder)
|
||||
{
|
||||
builder.OpenElement(1, "a");
|
||||
builder.AddAttribute(2, "name", GetAnchor());
|
||||
builder.AddAttribute(3, "href", Path);
|
||||
builder.AddAttribute(2, "id", GetAnchor());
|
||||
builder.AddAttribute(3, "href", GetPath());
|
||||
builder.AddAttribute(4, "class", "rz-link");
|
||||
builder.AddAttribute(5, "target", "_top"); // To support relative links without the Blazor router interfering
|
||||
builder.AddElementReferenceCapture(6, capture => element = capture);
|
||||
|
||||
@@ -115,7 +115,10 @@ namespace Radzen.Blazor
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
ThemeService.ThemeChanged -= OnThemeChanged;
|
||||
if (ThemeService != null)
|
||||
{
|
||||
ThemeService.ThemeChanged -= OnThemeChanged;
|
||||
}
|
||||
persistingSubscription.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace Radzen.Blazor
|
||||
.Add("rzi-caret-right", !clientExpanded)
|
||||
.Add(Tree.ItemIconCssClass)
|
||||
.Add(IconCssClass);
|
||||
private ClassList LabelClassList => ClassList.Create("rz-treenode-label")
|
||||
private ClassList LabelClassList => ClassList.Create("rz-treenode-label")
|
||||
.Add(Tree.ItemLabelCssClass)
|
||||
.Add(LabelCssClass);
|
||||
/// <summary>
|
||||
@@ -105,17 +105,17 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public IEnumerable Data { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the CSS classes added to the content.
|
||||
/// <summary>
|
||||
/// Gets or sets the CSS classes added to the content.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string ContentCssClass { get; set; }
|
||||
public string ContentCssClass { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the CSS classes added to the icon.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string IconCssClass { get; set; }
|
||||
public string IconCssClass { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the CSS classes added to the label.
|
||||
@@ -157,7 +157,7 @@ namespace Radzen.Blazor
|
||||
bool clientExpanded;
|
||||
internal async Task Toggle()
|
||||
{
|
||||
if (expanded)
|
||||
if (expanded && !Tree.SingleExpand)
|
||||
{
|
||||
clientExpanded = !clientExpanded;
|
||||
|
||||
@@ -229,7 +229,7 @@ namespace Radzen.Blazor
|
||||
|
||||
if (Tree.SingleExpand)
|
||||
{
|
||||
var siblings = ParentItem?.items ?? Tree.items;
|
||||
var siblings = (ParentItem?.items ?? Tree.items).ToList();
|
||||
|
||||
foreach (var sibling in siblings)
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
@using Radzen.Blazor
|
||||
@using Radzen.Blazor.Rendering
|
||||
|
||||
@inherits SchedulerViewBase
|
||||
@inherits SchedulerYearViewBase
|
||||
|
||||
@code {
|
||||
public override RenderFragment Render()
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Radzen.Blazor
|
||||
/// </RadzenScheduler>
|
||||
/// </code>
|
||||
/// </example>
|
||||
public partial class RadzenYearPlannerView : SchedulerViewBase
|
||||
public partial class RadzenYearPlannerView : SchedulerYearViewBase
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Icon => "view_list";
|
||||
@@ -91,7 +91,7 @@ namespace Radzen.Blazor
|
||||
/// </summary>
|
||||
/// <value>The start month.</value>
|
||||
[Parameter]
|
||||
public Month StartMonth { get; set; } = Month.January;
|
||||
public override Month StartMonth { get; set; } = Month.January;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override DateTime Next()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
@using Radzen.Blazor
|
||||
@using Radzen.Blazor.Rendering
|
||||
|
||||
@inherits SchedulerViewBase
|
||||
@inherits SchedulerYearViewBase
|
||||
|
||||
@code {
|
||||
public override RenderFragment Render()
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Radzen.Blazor
|
||||
/// </RadzenScheduler>
|
||||
/// </code>
|
||||
/// </example>
|
||||
public partial class RadzenYearTimelineView : SchedulerViewBase
|
||||
public partial class RadzenYearTimelineView : SchedulerYearViewBase
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Icon => "view_timeline";
|
||||
@@ -91,7 +91,7 @@ namespace Radzen.Blazor
|
||||
/// </summary>
|
||||
/// <value>The start month.</value>
|
||||
[Parameter]
|
||||
public Month StartMonth { get; set; } = Month.January;
|
||||
public override Month StartMonth { get; set; } = Month.January;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override DateTime Next()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
@using Radzen.Blazor
|
||||
@using Radzen.Blazor.Rendering
|
||||
|
||||
@inherits SchedulerViewBase
|
||||
@inherits SchedulerYearViewBase
|
||||
|
||||
@code {
|
||||
public override RenderFragment Render()
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Radzen.Blazor
|
||||
/// </RadzenScheduler>
|
||||
/// </code>
|
||||
/// </example>
|
||||
public partial class RadzenYearView : SchedulerViewBase
|
||||
public partial class RadzenYearView : SchedulerYearViewBase
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Icon => "calendar_month";
|
||||
@@ -89,7 +89,7 @@ namespace Radzen.Blazor
|
||||
/// </summary>
|
||||
/// <value>The start month.</value>
|
||||
[Parameter]
|
||||
public Month StartMonth { get; set; } = Month.January;
|
||||
public override Month StartMonth { get; set; } = Month.January;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override DateTime Next()
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
@inherits DropableViewBase
|
||||
|
||||
<div class="rz-view rz-day-view">
|
||||
<div class="rz-view-header">
|
||||
<div class="rz-view-header" @onclick=@(args => OnDayClick(@StartDate))>
|
||||
<div class="rz-slot-hour-header"></div>
|
||||
<div class="rz-slot-header">
|
||||
@StartDate.ToString("ddd", Scheduler.Culture)
|
||||
@@ -64,6 +64,13 @@
|
||||
await Scheduler.SelectSlot(date, date.AddMinutes(MinutesPerSlot), AppointmentsInSlot(date, date.AddMinutes(MinutesPerSlot)));
|
||||
}
|
||||
|
||||
async Task OnDayClick(DateTime day)
|
||||
{
|
||||
var dayStart = day.Date.Add(StartTime);
|
||||
var dayEnd = day.Date.Add(EndTime);
|
||||
await Scheduler.SelectDay(day.Date, AppointmentsInSlot(dayStart, dayEnd));
|
||||
}
|
||||
|
||||
IDictionary<string, object> Attributes(DateTime date)
|
||||
{
|
||||
var attributes = Scheduler.GetSlotAttributes(date, date.AddMinutes(MinutesPerSlot));
|
||||
@@ -84,7 +91,9 @@
|
||||
var updown = key == "ArrowUp" || key == "ArrowDown";
|
||||
var leftright = key == "ArrowLeft" || key == "ArrowRight";
|
||||
|
||||
currentAppointments = AppointmentsInSlot(CurrentDate, CurrentDate.AddDays(1));
|
||||
var dayStart = CurrentDate.Date.Add(StartTime);
|
||||
var dayEnd = CurrentDate.Date.Add(EndTime);
|
||||
currentAppointments = AppointmentsInSlot(dayStart, dayEnd);
|
||||
|
||||
if (arrow && currentAppointments.Any())
|
||||
{
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
{
|
||||
var dayOfWeek = StartDate.AddDays(days++);
|
||||
<div @onclick="@(args => OnSlotClick(dayOfWeek))" ondragover="event.preventDefault();" @ondrop=@(args => @OnDrop(dayOfWeek)) @attributes=@Attributes(dayOfWeek)>
|
||||
<div class="rz-slot-title @(dayOfWeek == CurrentDate ? " rz-state-focused" : "")">
|
||||
<div class="rz-slot-title @(dayOfWeek == CurrentDate ? " rz-state-focused" : "")" @onclick=@(args => OnDayClick(dayOfWeek)) @onclick:stopPropagation>
|
||||
@dayOfWeek.Day
|
||||
</div>
|
||||
</div>
|
||||
@@ -125,6 +125,11 @@
|
||||
await Scheduler.SelectSlot(date, date.AddDays(1), AppointmentsInSlot(date, date.AddDays(1)));
|
||||
}
|
||||
|
||||
async Task OnDayClick(DateTime day)
|
||||
{
|
||||
await Scheduler.SelectDay(day, AppointmentsInSlot(day, day.AddDays(1)));
|
||||
}
|
||||
|
||||
double DetermineTop(HashSet<double> existingTops)
|
||||
{
|
||||
var top = 1.5;
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
<div class="rz-slot-hour-header"></div>
|
||||
@for (var day = StartDate; day < EndDate; day = day.AddDays(1))
|
||||
{
|
||||
<div class="rz-slot-header">
|
||||
var loopDay = day;
|
||||
<div class="rz-slot-header" @onclick=@(args => OnDayClick(@loopDay))>
|
||||
@day.ToString(HeaderFormat, Scheduler.Culture)
|
||||
</div>
|
||||
}
|
||||
@@ -78,6 +79,13 @@
|
||||
await Scheduler.SelectSlot(date, date.AddMinutes(MinutesPerSlot), AppointmentsInSlot(date, date.AddMinutes(MinutesPerSlot)));
|
||||
}
|
||||
|
||||
async Task OnDayClick(DateTime day)
|
||||
{
|
||||
var dayStart = day.Date.Add(StartTime);
|
||||
var dayEnd = day.Date.Add(EndTime);
|
||||
await Scheduler.SelectDay(day.Date, AppointmentsInSlot(dayStart, dayEnd));
|
||||
}
|
||||
|
||||
IDictionary<string, object> Attributes(DateTime date)
|
||||
{
|
||||
var attributes = Scheduler.GetSlotAttributes(date, date.AddMinutes(MinutesPerSlot));
|
||||
|
||||
@@ -95,7 +95,7 @@
|
||||
</div>
|
||||
<div class="rz-slots">
|
||||
<div @attributes=@Attributes(realstart, "rz-slot", false)>
|
||||
<div class="rz-slot-header" style="cursor: pointer;" @onclick=@(args => OnMonthClick(startMonth))>
|
||||
<div class="rz-slot-header" @onclick=@(args => OnMonthClick(startMonth))>
|
||||
@realstart.ToString("MMM", Scheduler.Culture)
|
||||
</div>
|
||||
</div>
|
||||
@@ -126,7 +126,7 @@
|
||||
}
|
||||
}
|
||||
<div @attributes=@Attributes(realstart, "rz-slot", false)>
|
||||
<div class="rz-slot-header" style="cursor: pointer;" @onclick=@(args => OnMonthClick(startMonth))>
|
||||
<div class="rz-slot-header" @onclick=@(args => OnMonthClick(startMonth))>
|
||||
@realstart.ToString("MMM", Scheduler.Culture)
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -81,22 +81,21 @@
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@if (excessCount > 0)
|
||||
{
|
||||
var slotIndex = start.Subtract(date).Days;
|
||||
var slotWidth = (SLOT_WIDTH / CALENDAR_WIDTH) * 100;
|
||||
var left = ((slotIndex + 1) * slotWidth) + (100.0 / 85.0);
|
||||
var top = ((MaxAppointmentsInSlot + 1) * 1.5) + 1.7;
|
||||
var listDate = start;
|
||||
<a class="rz-event-list-btn" style="top: @(top.ToInvariantString())em; left: @(left.ToInvariantString())%" @onclick=@(args => OnListClick(listDate, appointments))>@String.Format(MoreText, excessCount)</a>
|
||||
@if (excessCount > 0)
|
||||
{
|
||||
var slotIndex = start.Subtract(date).Days;
|
||||
var slotWidth = (SLOT_WIDTH / CALENDAR_WIDTH) * 100;
|
||||
var left = ((slotIndex + 1) * slotWidth) + (100.0 / 85.0);
|
||||
var top = ((MaxAppointmentsInSlot + 1) * 1.5) + 1.7;
|
||||
var listDate = start;
|
||||
<a class="rz-event-list-btn" style="top: @(top.ToInvariantString())em; left: @(left.ToInvariantString())%" @onclick=@(args => OnListClick(listDate, appointments))>@String.Format(MoreText, excessCount)</a>
|
||||
}
|
||||
}
|
||||
}
|
||||
</div>
|
||||
<div class="rz-slots">
|
||||
<div @attributes=@Attributes(realstart, "rz-slot", false)>
|
||||
<div class="rz-slot-header" style="cursor: pointer;" @onclick=@(args => OnMonthClick(startMonth))>
|
||||
<div class="rz-slot-header" @onclick=@(args => OnMonthClick(startMonth))>
|
||||
@realstart.ToString("MMMM", Scheduler.Culture)
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
tabindex="0" @onkeydown="@(args => OnKeyPress(args))" @onkeydown:preventDefault="@preventKeyPress" @onkeydown:stopPropagation
|
||||
@onfocus=@(args => {CurrentDate = currentDate; CurrentMonth = currentMonth; })>
|
||||
|
||||
<div class="rz-slot-header rz-pb-2" style="cursor: pointer;" @onclick=@(args => OnMonthClick(startMonth))>
|
||||
<div class="rz-slot-header rz-pb-2" @onclick=@(args => OnMonthClick(startMonth))>
|
||||
<span class="rz-text-subtitle1">
|
||||
@realstart.ToString("MMMM yyyy", Scheduler.Culture)
|
||||
</span>
|
||||
|
||||
@@ -89,6 +89,11 @@ namespace Radzen.Blazor
|
||||
/// <param name="round">Wether to round.</param>
|
||||
public double NiceNumber(double range, bool round)
|
||||
{
|
||||
if (range == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
var sign = Math.Sign(range);
|
||||
range = Math.Abs(range);
|
||||
var exponent = Math.Floor(Math.Log10(range));
|
||||
|
||||
25
Radzen.Blazor/SchedulerDaySelectEventArgs.cs
Normal file
25
Radzen.Blazor/SchedulerDaySelectEventArgs.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Radzen.Blazor;
|
||||
|
||||
namespace Radzen
|
||||
{
|
||||
/// <summary>
|
||||
/// Supplies information about a <see cref="RadzenScheduler{TItem}.DaySelect" /> event that is being raised.
|
||||
/// </summary>
|
||||
public class SchedulerDaySelectEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Selected date.
|
||||
/// </summary>
|
||||
public DateTime Day { get; set; }
|
||||
/// <summary>
|
||||
/// List of appointments.
|
||||
/// </summary>
|
||||
public IEnumerable<AppointmentData> Appointments { get; set; }
|
||||
/// <summary>
|
||||
/// Current View.
|
||||
/// </summary>
|
||||
public ISchedulerView View { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -16,5 +16,10 @@ namespace Radzen
|
||||
/// The start of the currently rendered period.
|
||||
/// </summary>
|
||||
public DateTime End { get; set; }
|
||||
/// <summary>
|
||||
/// The selected view of the scheduler.
|
||||
/// </summary>
|
||||
public ISchedulerView View { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ namespace Radzen
|
||||
public class SchedulerMonthSelectEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Monthg start date. You can change this value to navigate to a different date.
|
||||
/// Month start date.
|
||||
/// </summary>
|
||||
public DateTime MonthStart { get; set; }
|
||||
/// <summary>
|
||||
|
||||
36
Radzen.Blazor/SchedulerYearViewBase.cs
Normal file
36
Radzen.Blazor/SchedulerYearViewBase.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using Radzen;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// A base class for <see cref="RadzenScheduler{TItem}" /> views.
|
||||
/// </summary>
|
||||
public abstract class SchedulerYearViewBase : SchedulerViewBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the StartMonth of the view.
|
||||
/// </summary>
|
||||
/// <value>The start month.</value>
|
||||
public abstract Month StartMonth { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Called by the Blazor runtime when parameters are set.
|
||||
/// </summary>
|
||||
/// <param name="parameters">The parameters.</param>
|
||||
public override async Task SetParametersAsync(ParameterView parameters)
|
||||
{
|
||||
if (parameters.DidParameterChange(nameof(StartMonth), StartMonth))
|
||||
{
|
||||
if (Scheduler != null)
|
||||
{
|
||||
await Scheduler.Reload();
|
||||
}
|
||||
}
|
||||
|
||||
await base.SetParametersAsync(parameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -184,7 +184,7 @@ namespace Radzen
|
||||
Text = "Material",
|
||||
Value = "material",
|
||||
Primary = "#4340d2",
|
||||
Secondary = "#e91e63",
|
||||
Secondary = "#e31c65",
|
||||
Base = "#f5f5f5",
|
||||
Selection = "rgba(67, 64, 210, 0.12)",
|
||||
SelectionText = "#4340d2",
|
||||
|
||||
@@ -27,6 +27,7 @@ $checkbox-tri-icon-font-size: $checkbox-icon-font-size !default;
|
||||
|
||||
.rz-checkbox-list-vertical {
|
||||
box-sizing: border-box;
|
||||
border-radius: var(--rz-border-radius);
|
||||
|
||||
.rz-checkbox {
|
||||
display: flex;
|
||||
@@ -39,6 +40,7 @@ $checkbox-tri-icon-font-size: $checkbox-icon-font-size !default;
|
||||
|
||||
.rz-checkbox-list-horizontal {
|
||||
box-sizing: border-box;
|
||||
border-radius: var(--rz-border-radius);
|
||||
|
||||
.rz-checkbox {
|
||||
display: inline-flex;
|
||||
@@ -65,6 +67,7 @@ $checkbox-tri-icon-font-size: $checkbox-icon-font-size !default;
|
||||
width: var(--rz-checkbox-width);
|
||||
min-width: var(--rz-checkbox-width);
|
||||
height: var(--rz-checkbox-height);
|
||||
border-radius: var(--rz-checkbox-border-radius);
|
||||
|
||||
&:focus {
|
||||
outline: var(--rz-outline-normal);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
height: 0;
|
||||
|
||||
input {
|
||||
width: 100%;
|
||||
height: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
|
||||
@@ -61,6 +61,11 @@ $timepicker-border: none !default;
|
||||
.rz-datepicker {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
border-radius: var(--rz-input-border-radius);
|
||||
|
||||
&:has(>.rz-inputtext:not(:disabled):not(.rz-state-disabled):focus) {
|
||||
outline: none; // unify .invalid styles with other forms components
|
||||
}
|
||||
|
||||
.rz-readonly {
|
||||
cursor: pointer;
|
||||
@@ -70,6 +75,9 @@ $timepicker-border: none !default;
|
||||
@extend %input;
|
||||
width: 100%;
|
||||
line-height: var(--rz-datepicker-line-height);
|
||||
}
|
||||
|
||||
&:has(.rz-datepicker-trigger) > .rz-inputtext {
|
||||
padding-inline-end: calc(1rem + var(--rz-datepicker-trigger-icon-width));
|
||||
}
|
||||
|
||||
|
||||
@@ -360,7 +360,8 @@ $form-field-helper-padding: 0 0.5rem !default;
|
||||
.rz-checkbox-list-horizontal ~ &,
|
||||
.rz-chkbox ~ &,
|
||||
.rz-fileupload ~ &,
|
||||
.rz-state-empty:has(.rz-placeholder) ~ & {
|
||||
.rz-state-empty:has(.rz-placeholder) ~ &,
|
||||
.rz-form-field.rz-state-focused & {
|
||||
inset-inline-end: auto;
|
||||
inset-block-start: var(--rz-form-field-label-floating-top);
|
||||
padding-block-start: 0;
|
||||
@@ -383,7 +384,8 @@ $form-field-helper-padding: 0 0.5rem !default;
|
||||
.rz-form-field:not(.rz-variant-outlined) .rz-checkbox-list-horizontal ~ &,
|
||||
.rz-form-field:not(.rz-variant-outlined) .rz-chkbox ~ &,
|
||||
.rz-form-field:not(.rz-variant-outlined) .rz-fileupload ~ &,
|
||||
.rz-form-field:not(.rz-variant-outlined) .rz-state-empty:has(.rz-placeholder) ~ & {
|
||||
.rz-form-field:not(.rz-variant-outlined) .rz-state-empty:has(.rz-placeholder) ~ &,
|
||||
.rz-form-field:not(.rz-variant-outlined).rz-state-focused & {
|
||||
background-color: inherit !important;
|
||||
}
|
||||
|
||||
@@ -393,7 +395,8 @@ $form-field-helper-padding: 0 0.5rem !default;
|
||||
|
||||
.rz-state-focused &,
|
||||
.rz-variant-filled.rz-state-focused &,
|
||||
.rz-variant-flat.rz-state-focused & {
|
||||
.rz-variant-flat.rz-state-focused &,
|
||||
.rz-form-field.rz-state-focused & {
|
||||
color: var(--rz-form-field-label-focus-color);
|
||||
}
|
||||
|
||||
|
||||
@@ -670,7 +670,8 @@ $column-draggable-shadow: 0 8px 10px 0 rgba(0, 0, 0, 0.1) !default;
|
||||
}
|
||||
}
|
||||
|
||||
&.rz-frozen-cell-right {
|
||||
&.rz-frozen-cell-right,
|
||||
&.rz-frozen-cell-right-inner {
|
||||
&:before {
|
||||
z-index: -2;
|
||||
background-color: var(--rz-grid-frozen-cell-background-color);
|
||||
@@ -693,7 +694,8 @@ $column-draggable-shadow: 0 8px 10px 0 rgba(0, 0, 0, 0.1) !default;
|
||||
}
|
||||
}
|
||||
|
||||
&.rz-frozen-cell-right {
|
||||
&.rz-frozen-cell-right,
|
||||
&.rz-frozen-cell-right-inner {
|
||||
&:after {
|
||||
background-color: var(--rz-grid-selected-background-color);
|
||||
}
|
||||
@@ -722,7 +724,8 @@ $column-draggable-shadow: 0 8px 10px 0 rgba(0, 0, 0, 0.1) !default;
|
||||
}
|
||||
}
|
||||
|
||||
&.rz-frozen-cell-right {
|
||||
&.rz-frozen-cell-right,
|
||||
&.rz-frozen-cell-right-inner {
|
||||
&:after {
|
||||
background-color: var(--rz-grid-cell-focus-background-color);
|
||||
color: var(--rz-grid-cell-focus-color);
|
||||
@@ -760,7 +763,8 @@ $column-draggable-shadow: 0 8px 10px 0 rgba(0, 0, 0, 0.1) !default;
|
||||
}
|
||||
}
|
||||
|
||||
&.rz-frozen-cell-right {
|
||||
&.rz-frozen-cell-right,
|
||||
&.rz-frozen-cell-right-inner {
|
||||
&:after {
|
||||
background-color: var(--rz-grid-hover-background-color);
|
||||
}
|
||||
|
||||
@@ -85,7 +85,9 @@ input {
|
||||
font-family: inherit;
|
||||
font-size: var(--rz-input-font-size);
|
||||
transition: var(--rz-input-transition);
|
||||
outline: none;
|
||||
&:not(.invalid) {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
@extend %input-base;
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ $radio-checked-border: var(--rz-input-border) !default;
|
||||
|
||||
.rz-radio-button-list-vertical {
|
||||
box-sizing: border-box;
|
||||
border-radius: var(--rz-border-radius);
|
||||
|
||||
.rz-radio-btn {
|
||||
display: flex;
|
||||
@@ -34,6 +35,7 @@ $radio-checked-border: var(--rz-input-border) !default;
|
||||
|
||||
.rz-radio-button-list-horizontal {
|
||||
box-sizing: border-box;
|
||||
border-radius: var(--rz-border-radius);
|
||||
|
||||
.rz-radio-btn {
|
||||
display: inline-flex;
|
||||
|
||||
@@ -13,6 +13,7 @@ $rating-ban-icon-color: $rating-color !default;
|
||||
display: inline-flex;
|
||||
font-size: var(--rz-rating-font-size);
|
||||
height: 1em;
|
||||
border-radius: var(--rz-border-radius);
|
||||
|
||||
&.rz-state-disabled {
|
||||
.rzi {
|
||||
@@ -22,6 +23,7 @@ $rating-ban-icon-color: $rating-color !default;
|
||||
}
|
||||
|
||||
a {
|
||||
display: inline-flex;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
text-decoration: none;
|
||||
@@ -46,7 +48,8 @@ $rating-ban-icon-color: $rating-color !default;
|
||||
opacity: var(--rz-rating-opacity);
|
||||
|
||||
&:before {
|
||||
content: "star_border";
|
||||
content: "star";
|
||||
font-variation-settings: "FILL" 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,35 +58,25 @@ $rating-ban-icon-color: $rating-color !default;
|
||||
|
||||
&:before {
|
||||
content: "star";
|
||||
font-variation-settings: "FILL" 1;
|
||||
}
|
||||
}
|
||||
|
||||
&:not(.rz-state-disabled):not(.rz-state-readonly) {
|
||||
|
||||
a:hover {
|
||||
a:hover, a:focus-visible {
|
||||
cursor: pointer;
|
||||
|
||||
.rzi-star,
|
||||
.rzi-star-o,
|
||||
.rzi-ban {
|
||||
color: var(--rz-rating-selected-color);
|
||||
}
|
||||
|
||||
.rzi-star-o:before {
|
||||
content: "star";
|
||||
color: var(--rz-rating-focus-color);
|
||||
}
|
||||
}
|
||||
|
||||
a:focus-visible {
|
||||
.rzi-star,
|
||||
.rzi-star-o,
|
||||
.rzi-ban {
|
||||
color: var(--rz-rating-focus-color);
|
||||
}
|
||||
|
||||
.rzi-star-o:before {
|
||||
content: "star";
|
||||
}
|
||||
a:focus-visible > span {
|
||||
outline: var(--rz-outline-focus);
|
||||
border-radius: var(--rz-border-radius)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ $rz-security-code-input-line-height: 1 !default;
|
||||
.rz-security-code {
|
||||
box-sizing: border-box;
|
||||
display: inline-flex;
|
||||
border-radius: var(--rz-input-border-radius);
|
||||
}
|
||||
|
||||
.rz-security-code-wrapper {
|
||||
|
||||
@@ -11,6 +11,15 @@ $selectbar-sizes: xs, sm, md, lg;
|
||||
.rz-selectbutton {
|
||||
box-sizing: border-box;
|
||||
display: inline-flex;
|
||||
border-radius: var(--rz-selectbar-border-radius);
|
||||
|
||||
&.rz-selectbutton-horizontal {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
&.rz-selectbutton-vertical {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.rz-button {
|
||||
&:focus-visible {
|
||||
@@ -19,30 +28,58 @@ $selectbar-sizes: xs, sm, md, lg;
|
||||
}
|
||||
}
|
||||
|
||||
@each $size in $selectbar-sizes { //.rz-selectbutton .rz-button.rz-button-md
|
||||
.rz-selectbutton .rz-button.rz-button-#{$size} {
|
||||
margin-inline-start: -1px;
|
||||
display: inline-block;
|
||||
background-color: var(--rz-selectbar-background-color);
|
||||
color: var(--rz-selectbar-color);
|
||||
border: var(--rz-selectbar-border);
|
||||
border-radius: 0;
|
||||
|
||||
&:first-child {
|
||||
margin-inline-start: 0;
|
||||
border-start-start-radius: var(--rz-selectbar-border-radius);
|
||||
border-end-start-radius: var(--rz-selectbar-border-radius);
|
||||
@each $size in $selectbar-sizes {
|
||||
.rz-selectbutton {
|
||||
.rz-button.rz-button-#{$size} {
|
||||
display: inline-block;
|
||||
background-color: var(--rz-selectbar-background-color);
|
||||
color: var(--rz-selectbar-color);
|
||||
border: var(--rz-selectbar-border);
|
||||
border-radius: 0;
|
||||
|
||||
&.rz-state-active {
|
||||
background-color: var(--rz-selectbar-selected-background-color);
|
||||
color: var(--rz-selectbar-selected-color);
|
||||
border: var(--rz-selectbar-selected-border);
|
||||
}
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-start-end-radius: var(--rz-selectbar-border-radius);
|
||||
border-end-end-radius: var(--rz-selectbar-border-radius);
|
||||
&.rz-selectbutton-horizontal {
|
||||
.rz-button.rz-button-#{$size} {
|
||||
&:first-child {
|
||||
border-start-start-radius: var(--rz-selectbar-border-radius);
|
||||
border-end-start-radius: var(--rz-selectbar-border-radius);
|
||||
}
|
||||
|
||||
&:not(:first-child) {
|
||||
border-inline-start: none;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-start-end-radius: var(--rz-selectbar-border-radius);
|
||||
border-end-end-radius: var(--rz-selectbar-border-radius);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.rz-state-active {
|
||||
background-color: var(--rz-selectbar-selected-background-color);
|
||||
color: var(--rz-selectbar-selected-color);
|
||||
border: var(--rz-selectbar-selected-border);
|
||||
&.rz-selectbutton-vertical {
|
||||
.rz-button.rz-button-#{$size} {
|
||||
text-align: center;
|
||||
|
||||
&:first-child {
|
||||
border-top-left-radius: var(--rz-selectbar-border-radius);
|
||||
border-top-right-radius: var(--rz-selectbar-border-radius);
|
||||
}
|
||||
|
||||
&:not(:first-child) {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-bottom-left-radius: var(--rz-selectbar-border-radius);
|
||||
border-bottom-right-radius: var(--rz-selectbar-border-radius);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user