Add support for DateOnly and TimeOnly properties to the ToODataString() method in the DataSourceExtensions namespace.
===
TELERIK NOTE
@Steven I forked this thread from the already complete feature request Provide support for DateOnly and TimeOnly structs for the respective pickers
Currently DateOnly and TimeOnly types are not supported by the ToODataString() method. As a result, they are serialized with the default ToString() method. Please use DateTime instead or implement a custom serialization method. Downloading our source code and using the built-in method as a base is also an option.
===
ORIGINAL POST
Would you have any updates regarding this support for early 2024?
My main issue regarding this at the moment is:
- My Backend returns DTOs with DateOnly properties.
- I wish to use these properties in a grid
- So far... So good... We can see the items etc... But then...
- We want to filter these properties...
- When we get the OData query... Our DateOnly is not in the correct ISO format... As there's no support for those in DataSourceExtensions.cs
I already tried solving this by creating my own GridColumn type, but I'm afraid there's nothing I can do about the OData serialization without just writing our own DataSourceExtensions... At which point we're just making it confusing for other developers needing to include this...
public class DateOnlyGridColumn : GridColumn
{
private DateOnly? _filterValue;
public DateOnly? FilterValue
{
get => _filterValue;
set
{
if (_filterValue != value)
{
_filterValue = value;
StateHasChanged();
}
}
}
public DateOnlyGridColumn()
{
DisplayFormat = "{0:dd/M/yyyy}";
FilterMenuTemplate = FilterMenu;
FilterMenuButtonsTemplate = FilterButtons;
}
private RenderFragment<FilterMenuTemplateContext> FilterMenu => (context) => (builder) =>
{
builder.OpenComponent<TelerikDatePicker<DateOnly?>>(0);
builder.AddAttribute(0, "Value", FilterValue);
builder.AddAttribute(2, "ValueChanged", EventCallback.Factory.Create<DateOnly?>(this, (value) => FilterValue = value));
builder.CloseComponent();
};
private RenderFragment<FilterMenuTemplateContext> FilterButtons => (context) => (builder) =>
{
// Filter button
builder.OpenComponent<TelerikButton>(0);
builder.AddAttribute(1, "OnClick", EventCallback.Factory.Create<MouseEventArgs>(this, async () => await ApplyFilter(context)));
builder.AddAttribute(2, "ThemeColor", ThemeConstants.Button.ThemeColor.Primary);
builder.AddAttribute(3, "ChildContent", (RenderFragment)(childBuilder =>
childBuilder.AddContent(0, "Filter")));
builder.CloseComponent();
// Clear button
builder.OpenComponent<TelerikButton>(4);
builder.AddAttribute(5, "OnClick", EventCallback.Factory.Create<MouseEventArgs>(this, async () =>
{
FilterValue = null;
await context.ClearFilterAsync();
}));
builder.AddAttribute(6, "ChildContent", (RenderFragment)(childBuilder =>
childBuilder.AddContent(0, "Clear")));
builder.CloseComponent();
};
private async Task ApplyFilter(FilterMenuTemplateContext filterContext)
{
if (filterContext == null || string.IsNullOrEmpty(Field) || !FilterValue.HasValue)
return;
var filter = new FilterDescriptor
{
Member = Field,
MemberType = typeof(DateOnly),
Operator = FilterOperator.IsEqualTo,
Value = FilterValue.Value, //.ToString("o") Convert to ISO-8601 format
};
filterContext.FilterDescriptor.FilterDescriptors.Clear();
filterContext.FilterDescriptor.FilterDescriptors.Add(filter);
await filterContext.FilterAsync();
}
}