Robot
January 21, 2023, 5:17am
1
Hi,
I am using a data filter here is my sample code. I wonder if I can use the required validator in order to make the user select dates or pop up an alert when pressing the apply filter button.
I want the data to come to the data grid when the button is pressed (after the button press data is loaded to the grid), not when the page is loaded. So is it possible to bind button action to a method by getting the data filter selection?
Thank you.
<RadzenCard class="mb-3">
<RadzenDataFilter @ref="_dataFilter" Auto=_auto Data="@_reconciliations" TItem="RazerReconciliations" ViewChanged=@(view => _filteredOrders = view.ToList())
FilterCaseSensitivity="FilterCaseSensitivity.CaseInsensitive">
<Properties>
<MyCustomDataFilterProperty TItem="RazerReconciliations" Property="TransactionDateTime" Title="Transaction Start Date" FormatString="{0:d}"/>
<MyCustomDataFilterProperty TItem="RazerReconciliations" Property="TransactionDateTime" Title="Transaction End Date" FormatString="{0:d}" />
</Properties>
</RadzenDataFilter>
<RadzenButton Text="Apply Filter" Click="@(args => _dataFilter.Filter())" id="btn"/>
</RadzenCard>
enchev
January 23, 2023, 7:06am
2
You can define a DatePicker and desired validator in a TemplateForm using FilterTemplate:
and perform the validation on filter button click:
1 Like
Robot
January 24, 2023, 1:50pm
3
Thank you @enchev for your help. One last thing about the data filter, how to filter for a date range? I mean I want to apply the filter for TransactionDateTime but somehow both filters get the same date when I change them. What I am doing wrong? Can you please help?
<RadzenCard class="mb-3">
<RadzenDataFilter @ref="_dataFilter" Auto=_auto Data="@_reconciliations" TItem="RazerReconciliations" ViewChanged=@(view => _filteredOrders = view.ToList())
FilterCaseSensitivity="FilterCaseSensitivity.CaseInsensitive">
<Properties>
<MyCustomDataFilterProperty TItem="RazerReconciliations" Property="TransactionDateTime" Title="Transaction Date" FilterValue="@selectedStartDate">
<FilterTemplate Context="filterContext">
<RadzenTemplateForm TItem="object" @ref="formStart" Data="@("dummyStart")">
<RadzenDatePicker @bind-Value=selectedStartDate Name="TransactionDateTime" DateFormat="d" />
<RadzenRequiredValidator Component="TransactionDateTime" />
</RadzenTemplateForm>
</FilterTemplate>
</MyCustomDataFilterProperty>
<MyCustomDataFilterProperty TItem="RazerReconciliations" Property="TransactionDateTime" Title="Transaction Date" FilterValue="@selectedEndDate">
<FilterTemplate Context="filterContext">
<RadzenTemplateForm TItem="object" @ref="formEnd" Data="@("dummyEnd")">
<RadzenDatePicker @bind-Value=selectedEndDate Name="TransactionDateTime" DateFormat="d" />
<RadzenRequiredValidator Component="TransactionDateTime" />
</RadzenTemplateForm>
</FilterTemplate>
</MyCustomDataFilterProperty>
</Properties>
</RadzenDataFilter>
<RadzenButton Text="Apply Filter" Click=@Filter id="btn" />
</RadzenCard>
Robot
January 26, 2023, 9:20am
4
Do you have a solution suggestion for this issue @enchev ? Is there a FilterOperator like between?
enchev
January 26, 2023, 9:31am
5
I'm afraid that I don't have any suggestion. Two filters with using >= and =< is best I can think of.
Robot
January 26, 2023, 10:23am
6
I did try to use two filters for Transaction Date as you said but somehow the date gets the same value. You can see this in my previous post.
enchev
January 26, 2023, 11:05am
7
The problem is caused by the fact that you've declared two RadzenDataFilterProperty with same Property value (Property="TransactionDateTime").
You can have two filters for a single property:
Robot
January 26, 2023, 12:53pm
8
Can I somehow get the dates selected in order to use them in my query to populate data in the grid when the user clicks apply filter button?
<RadzenDataFilter @ref="_dataFilter" Auto=_auto Data="@_reconciliations" TItem="RazerReconciliations" ViewChanged=@(view => _filteredOrders = view.ToList())
FilterCaseSensitivity="FilterCaseSensitivity.CaseInsensitive">
<Properties>
<MyCustomDataFilterProperty TItem="RazerReconciliations" Property="TransactionDateTime" Title="Transaction Date" FormatString="{0:d}">
</MyCustomDataFilterProperty>
</Properties>
</RadzenDataFilter>
<RadzenButton Text="Apply Filter" Click=@Filter id="btn" />
Apply Filter click:
async Task Filter()
{
if (formStart.EditContext.Validate())
{
await _dataFilter.Filter();
await ShowLoading();
_reconciliationResults = await ViewReconciliationsUseCase.ExecuteAsync(**selectedStartDate**, **selectedEndDate**);
}
}
enchev
January 26, 2023, 1:57pm
9
I see what you are after however we need to introduce breaking change in order to support such scenario and we are willing to do that. We need to change the Context of the FilterTemplate to the actual underlying filter:
Once you have access to the underlying filter you can bind the FilterValue to desired component:
You can also remove the TemplateForm and use much simple validation:
You can also access all filters from the DataFilter instance:
The change is already in our master branch and it will be released with our next update early next week:
committed 01:56PM - 26 Jan 23 UTC
Here is also the entire code:
@page "/datafilter"
@using RadzenBlazorDemos.Data
@using RadzenBlazorDemos.Models.Northwind
@using Microsoft.EntityFrameworkCore
@inherits DbContextPage
<RadzenExample Name="DataFilter" AdditionalSourceCodePages=@(new List<string>() { "MyCustomDataFilterProperty.razor" }) Documentation="false">
<div class="container-fluid">
<div class="row">
<div class="col">
<RadzenCard class="mb-3" style="display: flex; align-items: center; gap: 0.5rem">
<RadzenCheckBox @bind-Value="@auto" Name="auto" />
<RadzenLabel Text="Auto filter" Component="auto" Style="margin-left: 8px; margin-right: 32px; vertical-align: middle;" />
<RadzenButton Text="Apply Filter" Click="@Filter" Disabled="@auto" />
</RadzenCard>
<RadzenCard class="mb-3">
<RadzenDataFilter @ref="dataFilter" Auto=auto Data="@orders" TItem="Order" ViewChanged=@(view => filteredOrders = view.ToList())>
<Properties>
<RadzenDataFilterProperty TItem="Order" Property="OrderID" Title="Order ID" FilterValue="@selectedIds"
Type="typeof(IEnumerable<int>)" FilterOperator="FilterOperator.Contains">
<FilterTemplate Context="filterContext">
<RadzenDropDown @bind-Value=@selectedIds Style="width:100%;"
Change=@OnSelectedIdsChange Data="@(orderIds)" AllowClear="true" Multiple="true" />
</FilterTemplate>
</RadzenDataFilterProperty>
<RadzenDataFilterProperty TItem="Order" Property="Employee.LastName" Title="Employee Last Name" />
<MyCustomDataFilterProperty TItem="Order" Property="OrderDate" Title="Order Date">
<FilterTemplate Context="filterContext">
<RadzenDatePicker @bind-Value=@(filterContext.FilterValue) Name="OrderDate" AllowClear />
<RadzenLabel Component="OrderDate" Text="Required" Style="color: red;" Visible=@(filterContext.FilterValue == null) />
</FilterTemplate>
</MyCustomDataFilterProperty>
<RadzenDataFilterProperty TItem="Order" Property="Freight" Title="Freight" />
</Properties>
</RadzenDataFilter>
</RadzenCard>
<RadzenDataGrid @ref="ordersGrid" AllowPaging="true" AllowSorting="true" Data="@(filteredOrders ?? orders)" TItem="Order"
ColumnWidth="200px" PageSize="20" Style="height: 500px">
<Columns>
<RadzenDataGridColumn Width="50px" TItem="Order" Title="#" Filterable="false" Sortable="false" TextAlign="TextAlign.Center" Frozen=true>
<Template>
@(orders.IndexOf(context) + 1)
</Template>
</RadzenDataGridColumn>
<RadzenDataGridColumn Width="200px" TItem="Order" Property="OrderID" Title="Order ID">
<FooterTemplate>
Displayed orders: <b>@ordersGrid.View.Count()</b> of <b>@orders.Count()</b>
</FooterTemplate>
</RadzenDataGridColumn>
<RadzenDataGridColumn Width="200px" TItem="Order" Property="Customer.CompanyName" Title="Customer" />
<RadzenDataGridColumn TItem="Order" Property="Employee.LastName" Title="Employee">
<Template Context="order">
@order.Employee?.FirstName @order.Employee?.LastName
</Template>
</RadzenDataGridColumn>
<RadzenDataGridColumn TItem="Order" Property="OrderDate" Title="Order Date" FormatString="{0:d}">
<FooterTemplate>
Last order date: <b>@String.Format("{0:d}", orders.OrderByDescending(o => o.OrderDate).LastOrDefault()?.OrderDate)</b>
</FooterTemplate>
</RadzenDataGridColumn>
<RadzenDataGridColumn TItem="Order" Property="Freight" Title="Freight">
<Template Context="order">
@String.Format(new System.Globalization.CultureInfo("en-US"), "{0:C}", order.Freight)
</Template>
<FooterTemplate>
Total amount: <b>@String.Format(new System.Globalization.CultureInfo("en-US"), "{0:C}", orders.Sum(o => o.Freight))</b>
</FooterTemplate>
</RadzenDataGridColumn>
<RadzenDataGridColumn TItem="Order" Property="ShipName" Title="Ship Name" />
</Columns>
</RadzenDataGrid>
</div>
</div>
</div>
</RadzenExample>
@code {
RadzenTemplateForm<object> form;
async Task Filter()
{
if (!dataFilter.Filters.Any(f => f.FilterValue == null))
{
await dataFilter.Filter();
}
}
bool auto = true;
RadzenDataFilter<Order> dataFilter;
IList<Order> filteredOrders;
IList<Order> orders;
RadzenDataGrid<Order> ordersGrid;
IEnumerable<int> selectedIds;
IEnumerable<int> orderIds;
void OnSelectedIdsChange(object value)
{
if (selectedIds != null && !selectedIds.Any())
{
selectedIds = null;
}
}
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
orders = dbContext.Orders.Include("Customer").Include("Employee").ToList();
orderIds = orders.Select(o => o.OrderID).Distinct();
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await base.OnAfterRenderAsync(firstRender);
if (firstRender)
{
await dataFilter.AddFilter(new CompositeFilterDescriptor()
{
Property = "OrderDate",
FilterValue = DateTime.Now,
FilterOperator = FilterOperator.GreaterThanOrEquals
});
await dataFilter.AddFilter(new CompositeFilterDescriptor()
{
Property = "OrderDate",
FilterValue = DateTime.Now.AddDays(10),
FilterOperator = FilterOperator.LessThanOrEquals
});
}
}
}
Robot
January 26, 2023, 2:32pm
10
Thank you, I will looking forward to it
Robot
January 30, 2023, 11:09am
11
Hi @enchev , is it released?