From 386f1a48927e7769ce6b13b3a0f4e7e58b54b405 Mon Sep 17 00:00:00 2001 From: Vikram Reddy Date: Sat, 4 May 2024 22:32:12 +0530 Subject: [PATCH] #503 - Grid filters - DoesNotContain support added. --- .../Form/AutoComplete/AutoComplete.razor.cs | 1 + blazorbootstrap/Enums/StringFilterOperator.cs | 5 ++++ .../Extensions/ExpressionExtensions.cs | 23 +++++++++++++++++++ blazorbootstrap/Extensions/TypeExtensions.cs | 14 ----------- .../Utilities/FilterOperatorHelper.cs | 2 +- 5 files changed, 30 insertions(+), 15 deletions(-) diff --git a/blazorbootstrap/Components/Form/AutoComplete/AutoComplete.razor.cs b/blazorbootstrap/Components/Form/AutoComplete/AutoComplete.razor.cs index 6a3043c7e..f78281031 100644 --- a/blazorbootstrap/Components/Form/AutoComplete/AutoComplete.razor.cs +++ b/blazorbootstrap/Components/Form/AutoComplete/AutoComplete.razor.cs @@ -172,6 +172,7 @@ private FilterOperator GetFilterOperator() => { StringFilterOperator.Equals => FilterOperator.Equals, StringFilterOperator.Contains => FilterOperator.Contains, + StringFilterOperator.DoesNotContain => FilterOperator.DoesNotContain, StringFilterOperator.StartsWith => FilterOperator.StartsWith, StringFilterOperator.EndsWith => FilterOperator.EndsWith, _ => FilterOperator.Contains diff --git a/blazorbootstrap/Enums/StringFilterOperator.cs b/blazorbootstrap/Enums/StringFilterOperator.cs index c8ba2770c..1bb4dfd98 100644 --- a/blazorbootstrap/Enums/StringFilterOperator.cs +++ b/blazorbootstrap/Enums/StringFilterOperator.cs @@ -12,6 +12,11 @@ public enum StringFilterOperator /// Contains, + /// + /// Satisfied if the current value does not contain the specified value. + /// + DoesNotContain, + /// /// Satisfied if the current value starts with the specified value. /// diff --git a/blazorbootstrap/Extensions/ExpressionExtensions.cs b/blazorbootstrap/Extensions/ExpressionExtensions.cs index 7eab75f32..f12b3be13 100644 --- a/blazorbootstrap/Extensions/ExpressionExtensions.cs +++ b/blazorbootstrap/Extensions/ExpressionExtensions.cs @@ -392,6 +392,7 @@ or StringConstants.PropertyTypeNameDecimal return filterItem.Operator switch { FilterOperator.Contains => GetStringContainsExpressionDelegate(parameterExpression, filterItem), + FilterOperator.DoesNotContain => GetStringDoesNotContainExpressionDelegate(parameterExpression, filterItem), FilterOperator.StartsWith => GetStringStartsWithExpressionDelegate(parameterExpression, filterItem), FilterOperator.EndsWith => GetStringEndsWithExpressionDelegate(parameterExpression, filterItem), FilterOperator.Equals => GetStringEqualsExpressionDelegate(parameterExpression, filterItem), @@ -675,6 +676,28 @@ public static Expression> GetStringContainsExpressionDelegate< return Expression.Lambda>(finalExpression, parameterExpression); } + public static Expression> GetStringDoesNotContainExpressionDelegate(ParameterExpression parameterExpression, FilterItem filterItem) + { + var propertyExp = Expression.Property(parameterExpression, filterItem.PropertyName); + var someValue = Expression.Constant(filterItem.Value, typeof(string)); + var comparisonExpression = Expression.Constant(filterItem.StringComparison); + + // Handle null check + var nullCheckExpression = Expression.NotEqual(propertyExp, Expression.Constant(null, typeof(string))); + + // Create method call expression for Contains method + var methodInfo = typeof(string).GetMethod(nameof(string.Contains), new[] { typeof(string), typeof(StringComparison) }); + var containsExpression = Expression.Call(propertyExp, methodInfo!, someValue, comparisonExpression); + + // "not contains" expression + var notContainsExpression = Expression.Not(containsExpression); + + // Combine null check and contains expression using AndAlso + var finalExpression = Expression.AndAlso(nullCheckExpression, notContainsExpression); + + return Expression.Lambda>(finalExpression, parameterExpression); + } + public static Expression> GetStringEndsWithExpressionDelegate(ParameterExpression parameterExpression, FilterItem filterItem) { var propertyExp = Expression.Property(parameterExpression, filterItem.PropertyName); diff --git a/blazorbootstrap/Extensions/TypeExtensions.cs b/blazorbootstrap/Extensions/TypeExtensions.cs index 2d947c444..bddf250d1 100644 --- a/blazorbootstrap/Extensions/TypeExtensions.cs +++ b/blazorbootstrap/Extensions/TypeExtensions.cs @@ -23,20 +23,6 @@ public static string GetPropertyTypeName(this Type type, string propertyName) return string.Empty; var propertyTypeName = propertyType?.ToString(); - - //if(propertyTypeName is null) // Nullable type scenario - //{ - // var props = type.GetProperties(); - // if(props.Length > 0) - // { - // var propertyInfo = props?.FirstOrDefault(x=>x.Name == propertyName); - // if (propertyInfo is null) - // throw new InvalidDataException($"PropertyName `{propertyName}` is invalid."); - - // propertyTypeName = Nullable.GetUnderlyingType(propertyInfo.PropertyType)?.FullName; - // } - //} - if (string.IsNullOrWhiteSpace(propertyTypeName)) return string.Empty; diff --git a/blazorbootstrap/Utilities/FilterOperatorHelper.cs b/blazorbootstrap/Utilities/FilterOperatorHelper.cs index d53530db9..4e50b38a1 100644 --- a/blazorbootstrap/Utilities/FilterOperatorHelper.cs +++ b/blazorbootstrap/Utilities/FilterOperatorHelper.cs @@ -120,7 +120,7 @@ public static IEnumerable GetStringFilterOperators() List result = new() { new FilterOperatorInfo("*a*", "Contains", FilterOperator.Contains), - //result.Add(new("!*a*", "Does not contain", FilterOperator.DoesNotContain)); + new FilterOperatorInfo("!*a*", "Does not contain", FilterOperator.DoesNotContain), new FilterOperatorInfo("a**", "Starts with", FilterOperator.StartsWith), new FilterOperatorInfo("**a", "Ends with", FilterOperator.EndsWith), //result.Add(new("=''", "Is empty", FilterOperator.IsEmpty));