RadzenDataGrid: Added Is Empty and Is not empty Filter operators (#514)

* Updated the RadzenDataGrid's filter operators too have a 'Is Empty' and 'Is not empty' Options

* IsNull/IsNotNull should work with null while IsEmpty/IsNotEmpty with empty string

Co-authored-by: Hugo Human <hugo@tangentsolutions.co.za>
Co-authored-by: Vladimir Enchev <vladimir.enchev@gmail.com>
This commit is contained in:
130nk3r5
2022-07-07 14:14:30 +02:00
committed by GitHub
parent 59b535b0d8
commit cb7223dee1
7 changed files with 128 additions and 26 deletions

View File

@@ -827,9 +827,17 @@ namespace Radzen
/// </summary>
IsNull,
/// <summary>
/// Satisfied if the current value is <see cref="string.Empty"/>.
/// </summary>
IsEmpty,
/// <summary>
/// Satisfied if the current value is not null.
/// </summary>
IsNotNull
IsNotNull,
/// <summary>
/// Satisfied if the current value is not <see cref="string.Empty"/>.
/// </summary>
IsNotEmpty
}
/// <summary>

View File

@@ -45,7 +45,9 @@ namespace Radzen
{FilterOperator.Contains, "Contains"},
{FilterOperator.DoesNotContain, "DoesNotContain"},
{FilterOperator.IsNull, "=="},
{FilterOperator.IsNotNull, "!="}
{FilterOperator.IsEmpty, "=="},
{FilterOperator.IsNotNull, "!="},
{FilterOperator.IsNotEmpty, "!="}
};
/// <summary>
@@ -64,7 +66,9 @@ namespace Radzen
{FilterOperator.Contains, "contains"},
{FilterOperator.DoesNotContain, "DoesNotContain"},
{FilterOperator.IsNull, "eq"},
{FilterOperator.IsNotNull, "ne"}
{FilterOperator.IsEmpty, "eq"},
{FilterOperator.IsNotNull, "ne"},
{FilterOperator.IsNotEmpty, "ne"}
};
/// <summary>
@@ -140,8 +144,10 @@ namespace Radzen
public static string ToFilterString<T>(this IEnumerable<RadzenDataGridColumn<T>> columns)
{
Func<RadzenDataGridColumn<T>, bool> canFilter = (c) => c.Filterable && c.FilterPropertyType != null &&
(!(c.GetFilterValue() == null || c.GetFilterValue() as string == string.Empty) || c.GetFilterOperator() == FilterOperator.IsNotNull || c.GetFilterOperator() == FilterOperator.IsNull)
&& c.GetFilterProperty() != null;
(!(c.GetFilterValue() == null || c.GetFilterValue() as string == string.Empty) || c.GetFilterOperator() == FilterOperator.IsNotNull
|| c.GetFilterOperator() == FilterOperator.IsNull || c.GetFilterOperator() == FilterOperator.IsEmpty
|| c.GetFilterOperator() == FilterOperator.IsNotEmpty)
&& c.GetFilterProperty() != null;
if (columns.Where(canFilter).Any())
{
@@ -232,7 +238,10 @@ namespace Radzen
secondValue = (string)Convert.ChangeType(column.GetSecondFilterValue(), typeof(string));
}
if (!string.IsNullOrEmpty(value) || column.GetFilterOperator() == FilterOperator.IsNotNull || column.GetFilterOperator() == FilterOperator.IsNull)
if (!string.IsNullOrEmpty(value) || column.GetFilterOperator() == FilterOperator.IsNotNull
|| column.GetFilterOperator() == FilterOperator.IsNull
|| column.GetFilterOperator() == FilterOperator.IsEmpty
|| column.GetFilterOperator() == FilterOperator.IsNotEmpty)
{
var linqOperator = LinqFilterOperators[column.GetFilterOperator()];
if (linqOperator == null)
@@ -408,6 +417,14 @@ namespace Radzen
{
return $@"np({property}) == null";
}
else if (columnFilterOperator == FilterOperator.IsEmpty)
{
return $@"np({property}) == ''";
}
else if (columnFilterOperator == FilterOperator.IsNotEmpty)
{
return $@"np({property}) != ''";
}
else if (columnFilterOperator == FilterOperator.IsNotNull)
{
return $@"np({property}) != null";
@@ -419,6 +436,10 @@ namespace Radzen
{
return $"{property} {linqOperator} null";
}
else if (column.GetFilterOperator() == FilterOperator.IsEmpty || column.GetFilterOperator() == FilterOperator.IsNotEmpty)
{
return $"{property} {linqOperator} ''";
}
else
{
return $"{property} {linqOperator} {value}";
@@ -433,6 +454,10 @@ namespace Radzen
{
return $"{property} {linqOperator} null";
}
else if (column.GetFilterOperator() == FilterOperator.IsEmpty || column.GetFilterOperator() == FilterOperator.IsNotEmpty)
{
return $"{property} {linqOperator} ''";
}
else
{
var dateTimeValue = DateTime.Parse(value, null, System.Globalization.DateTimeStyles.RoundtripKind);
@@ -453,6 +478,10 @@ namespace Radzen
{
return $"{property} {linqOperator} null";
}
else if (column.GetFilterOperator() == FilterOperator.IsEmpty || column.GetFilterOperator() == FilterOperator.IsNotEmpty)
{
return $"{property} {linqOperator} ''";
}
else
{
return $@"{property} {linqOperator} Guid(""{value}"")";
@@ -614,6 +643,10 @@ namespace Radzen
{
return $"{property} {odataFilterOperator} null";
}
else if (columnFilterOperator == FilterOperator.IsEmpty || columnFilterOperator == FilterOperator.IsNotEmpty)
{
return $"{property} {odataFilterOperator} ''";
}
}
else if (IsEnumerable(column.FilterPropertyType) && column.FilterPropertyType != typeof(string))
{
@@ -643,6 +676,10 @@ namespace Radzen
{
return $"{property} {odataFilterOperator} null";
}
else if (columnFilterOperator == FilterOperator.IsEmpty || columnFilterOperator == FilterOperator.IsNotEmpty)
{
return $"{property} {odataFilterOperator} ''";
}
else
{
return $"{property} eq {value.ToLower()}";
@@ -657,6 +694,10 @@ namespace Radzen
{
return $"{property} {odataFilterOperator} null";
}
else if (columnFilterOperator == FilterOperator.IsEmpty || columnFilterOperator == FilterOperator.IsNotEmpty)
{
return $"{property} {odataFilterOperator} ''";
}
else
{
return $"{property} {odataFilterOperator} {DateTime.Parse(value, null, System.Globalization.DateTimeStyles.RoundtripKind).ToString("yyyy-MM-ddTHH:mm:ss.fffZ")}";
@@ -733,8 +774,10 @@ namespace Radzen
public static string ToODataFilterString<T>(this IEnumerable<RadzenDataGridColumn<T>> columns)
{
Func<RadzenDataGridColumn<T>, bool> canFilter = (c) => c.Filterable && c.FilterPropertyType != null &&
(!(c.GetFilterValue() == null || c.GetFilterValue() as string == string.Empty) || c.GetFilterOperator() == FilterOperator.IsNotNull || c.GetFilterOperator() == FilterOperator.IsNull)
&& c.GetFilterProperty() != null;
(!(c.GetFilterValue() == null || c.GetFilterValue() as string == string.Empty)
|| c.GetFilterOperator() == FilterOperator.IsNotNull || c.GetFilterOperator() == FilterOperator.IsNull
|| c.GetFilterOperator() == FilterOperator.IsEmpty || c.GetFilterOperator() == FilterOperator.IsNotEmpty)
&& c.GetFilterProperty() != null;
if (columns.Where(canFilter).Any())
{
@@ -749,7 +792,8 @@ namespace Radzen
var value = column.GetFilterValue();
var secondValue = column.GetSecondFilterValue();
if (value != null || column.GetFilterOperator() == FilterOperator.IsNotNull || column.GetFilterOperator() == FilterOperator.IsNull)
if (value != null || column.GetFilterOperator() == FilterOperator.IsNotNull || column.GetFilterOperator() == FilterOperator.IsNull
|| column.GetFilterOperator() == FilterOperator.IsEmpty || column.GetFilterOperator() == FilterOperator.IsNotEmpty)
{
var linqOperator = ODataFilterOperators[column.GetFilterOperator()];
if (linqOperator == null)
@@ -874,8 +918,10 @@ namespace Radzen
public static IQueryable<T> Where<T>(this IQueryable<T> source, IEnumerable<RadzenDataGridColumn<T>> columns)
{
Func<RadzenDataGridColumn<T>, bool> canFilter = (c) => c.Filterable && c.FilterPropertyType != null &&
(!(c.GetFilterValue() == null || c.GetFilterValue() as string == string.Empty) || c.GetFilterOperator() == FilterOperator.IsNotNull || c.GetFilterOperator() == FilterOperator.IsNull)
&& c.GetFilterProperty() != null;
(!(c.GetFilterValue() == null || c.GetFilterValue() as string == string.Empty)
|| c.GetFilterOperator() == FilterOperator.IsNotNull || c.GetFilterOperator() == FilterOperator.IsNull
|| c.GetFilterOperator() == FilterOperator.IsEmpty || c.GetFilterOperator() == FilterOperator.IsNotEmpty)
&& c.GetFilterProperty() != null;
if (columns.Where(canFilter).Any())
{
@@ -893,14 +939,18 @@ namespace Radzen
property = $"({property})";
}
if (column.FilterPropertyType == typeof(string) && !(column.GetFilterOperator() == FilterOperator.IsNotNull || column.GetFilterOperator() == FilterOperator.IsNull))
if (column.FilterPropertyType == typeof(string) &&
!(column.GetFilterOperator() == FilterOperator.IsNotNull || column.GetFilterOperator() == FilterOperator.IsNull
|| column.GetFilterOperator() == FilterOperator.IsEmpty || column.GetFilterOperator() == FilterOperator.IsNotEmpty))
{
property = $@"({property} == null ? """" : {property})";
}
string filterCaseSensitivityOperator = column.FilterPropertyType == typeof(string)
&& column.GetFilterOperator() != FilterOperator.IsNotNull && column.GetFilterOperator() != FilterOperator.IsNull &&
column.Grid.FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ? ".ToLower()" : "";
&& column.GetFilterOperator() != FilterOperator.IsNotNull && column.GetFilterOperator() != FilterOperator.IsNull
&& column.GetFilterOperator() != FilterOperator.IsEmpty && column.GetFilterOperator() != FilterOperator.IsNotEmpty
&& column.Grid.FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ? ".ToLower()" : "";
var comparison = LinqFilterOperators[column.GetFilterOperator()];

View File

@@ -188,6 +188,12 @@
<li class="@(DateFilterOperatorStyle(column, FilterOperator.IsNull))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.IsNull))" style="display: block;">
<span>@IsNullText</span>
</li>
<li class="@(DateFilterOperatorStyle(column, FilterOperator.IsEmpty))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.IsEmpty))" style="display: block;">
<span>@IsEmptyText</span>
</li>
<li class="@(DateFilterOperatorStyle(column, FilterOperator.IsNotEmpty))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.IsNotEmpty))" style="display: block;">
<span>@IsNotEmptyText</span>
</li>
<li class="@(DateFilterOperatorStyle(column, FilterOperator.IsNotNull))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.IsNotNull))" style="display: block;">
<span>@IsNotNullText</span>
</li>

View File

@@ -849,6 +849,20 @@ namespace Radzen.Blazor
/// <value>The null text.</value>
[Parameter]
public string IsNullText { get; set; } = "Is null";
/// <summary>
/// Gets or sets the is empty text.
/// </summary>
/// <value>The empty text.</value>
[Parameter]
public string IsEmptyText { get; set; } = "Is empty";
/// <summary>
/// Gets or sets the is not empty text.
/// </summary>
/// <value>The not empty text.</value>
[Parameter]
public string IsNotEmptyText { get; set; } = "Is not empty";
internal class NumericFilterEventCallback
{
@@ -1428,15 +1442,17 @@ namespace Radzen.Blazor
if (LoadData.HasDelegate)
{
var filters = allColumns.ToList().Where(c => c.Filterable && c.GetVisible() && (c.GetFilterValue() != null
|| c.GetFilterOperator() == FilterOperator.IsNotNull || c.GetFilterOperator() == FilterOperator.IsNull)).Select(c => new FilterDescriptor()
{
|| c.GetFilterOperator() == FilterOperator.IsNotNull || c.GetFilterOperator() == FilterOperator.IsNull
|| c.GetFilterOperator() == FilterOperator.IsEmpty | c.GetFilterOperator() == FilterOperator.IsNotEmpty))
.Select(c => new FilterDescriptor()
{
Property = c.GetFilterProperty(),
FilterValue = c.GetFilterValue(),
FilterOperator = c.GetFilterOperator(),
SecondFilterValue = c.GetSecondFilterValue(),
SecondFilterOperator = c.GetSecondFilterOperator(),
LogicalFilterOperator = c.GetLogicalFilterOperator()
});
});
await LoadData.InvokeAsync(new Radzen.LoadDataArgs()
{

View File

@@ -717,7 +717,10 @@ namespace Radzen.Blazor
internal bool CanSetFilterValue()
{
return GetFilterOperator() == FilterOperator.IsNull || GetFilterOperator() == FilterOperator.IsNotNull;
return GetFilterOperator() == FilterOperator.IsNull
|| GetFilterOperator() == FilterOperator.IsNotNull
|| GetFilterOperator() == FilterOperator.IsEmpty
|| GetFilterOperator() == FilterOperator.IsNotEmpty;
}
/// <summary>
@@ -814,10 +817,12 @@ namespace Radzen.Blazor
return new FilterOperator[] { FilterOperator.Equals, FilterOperator.NotEquals, FilterOperator.IsNull, FilterOperator.IsNotNull };
return Enum.GetValues(typeof(FilterOperator)).Cast<FilterOperator>().Where(o => {
var isStringOperator = o == FilterOperator.Contains || o == FilterOperator.DoesNotContain || o == FilterOperator.StartsWith || o == FilterOperator.EndsWith;
var isStringOperator = o == FilterOperator.Contains || o == FilterOperator.DoesNotContain
|| o == FilterOperator.StartsWith || o == FilterOperator.EndsWith || o == FilterOperator.IsEmpty || o == FilterOperator.IsNotEmpty;
return FilterPropertyType == typeof(string) ? isStringOperator
|| o == FilterOperator.Equals || o == FilterOperator.NotEquals || o == FilterOperator.IsNull || o == FilterOperator.IsNotNull
: !isStringOperator;
|| o == FilterOperator.Equals || o == FilterOperator.NotEquals
|| o == FilterOperator.IsNull || o == FilterOperator.IsNotNull
: !isStringOperator;
});
}
@@ -847,8 +852,12 @@ namespace Radzen.Blazor
return Grid?.NotEqualsText;
case FilterOperator.IsNull:
return Grid?.IsNullText;
case FilterOperator.IsEmpty:
return Grid?.IsEmptyText;
case FilterOperator.IsNotNull:
return Grid?.IsNotNullText;
case FilterOperator.IsNotEmpty:
return Grid?.IsNotEmptyText;
default:
return $"{filterOperator}";
}
@@ -883,6 +892,10 @@ namespace Radzen.Blazor
return "∅";
case FilterOperator.IsNotNull:
return "!∅";
case FilterOperator.IsEmpty:
return "= ''";
case FilterOperator.IsNotEmpty:
return "≠ ''";
default:
return $"{filterOperator}";
}

View File

@@ -31,6 +31,12 @@
<li class="@(FilterOperatorStyle(Column, FilterOperator.EndsWith))" @onclick="@(args => ApplyFilter(FilterOperator.EndsWith))" style="display: block;">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.EndsWith)</span><span>@Grid.EndsWithText</span>
</li>
<li class="@(FilterOperatorStyle(Column, FilterOperator.IsEmpty))" @onclick="@(args => ApplyFilter(FilterOperator.IsEmpty))" style="display: block;">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.IsEmpty)</span><span>@Grid.IsEmptyText</span>
</li>
<li class="@(FilterOperatorStyle(Column, FilterOperator.IsNotEmpty))" @onclick="@(args => ApplyFilter(FilterOperator.IsNotEmpty))" style="display: block;">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.IsNotEmpty)</span><span>@Grid.IsNotEmptyText</span>
</li>
}
<li class="@(FilterOperatorStyle(Column, FilterOperator.Equals))" @onclick="@(args => ApplyFilter(FilterOperator.Equals))" style="display: block;">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.Equals)</span><span>@Grid.EqualsText</span>
@@ -79,17 +85,19 @@
protected string FilterIconStyle()
{
var additionalStyle = Column.GetFilterValue() != null || Column.GetSecondFilterValue() != null ||
Column.GetFilterOperator() == FilterOperator.IsNotNull || Column.GetFilterOperator() == FilterOperator.IsNull
? "rz-grid-filter-active" : "";
Column.GetFilterOperator() == FilterOperator.IsNotNull || Column.GetFilterOperator() == FilterOperator.IsNull
|| Column.GetFilterOperator() == FilterOperator.IsEmpty || Column.GetFilterOperator() == FilterOperator.IsNotEmpty
? "rz-grid-filter-active" : "";
return $"rz-filter-button rz-button rz-button-md rz-button-icon-only btn-light {additionalStyle}";
}
protected async Task ApplyFilter(FilterOperator value)
{
if (value == FilterOperator.IsNull || value == FilterOperator.IsNotNull)
if (value == FilterOperator.IsNull || value == FilterOperator.IsNotNull
|| value == FilterOperator.IsEmpty || value == FilterOperator.IsNotEmpty)
{
Column.SetFilterValue(null);
Column.SetFilterValue(null, false);
Column.SetFilterValue(value == FilterOperator.IsEmpty || value == FilterOperator.IsNotEmpty ? string.Empty : null);
Column.SetFilterValue(value == FilterOperator.IsEmpty || value == FilterOperator.IsNotEmpty ? string.Empty : null, false);
}
Column.SetFilterOperator(value);

View File

@@ -165,6 +165,7 @@ else
{
var additionalStyle = column.GetFilterValue() != null || column.GetSecondFilterValue() != null ||
column.GetFilterOperator() == FilterOperator.IsNotNull || column.GetFilterOperator() == FilterOperator.IsNull
|| column.GetFilterOperator() == FilterOperator.IsEmpty || column.GetFilterOperator() == FilterOperator.IsNotEmpty
? "rz-grid-filter-active" : "";
return $"rzi rz-grid-filter-icon {additionalStyle}";
}