Currently, the validation of the grid can be disabled altogether via the GridValidationSettings.Enabled option. However, we cannot control the validation of the grid per column.
Also, we cannot control when the validation is triggered. The simple inputs expose the ValidateOn option, but it cannot be set to the default editors of the grid without the need for an explicit declaration of a custom editor.
When filtering using a GridSearchBox - to filter across all columns, we have an issue where if you change a GridColumns Visible attribute to false that row will still be visible in the grid results even though it no longer matches the filter.
Take this snippet for example: Telerik REPL for Blazor - The best place to play, experiment, share & learn using Blazor.
1. Use Search box and search for a Name. e.g "Chang"
2. Click "Toggle Name Visibility" button
Expected: Since Name column is now hidden, the column should no longer be used in filter and the row should no longer be displayed. In reference to the GridSearchBox: https://docs.telerik.com/blazor-ui/components/grid/filter/searchbox#filter-from-code where it's mentioned that the search box will filter only on columns that are visible. It doesnt seem to refresh the filter.
Actual: Row still displayed even though it no longer matches filter
Just wanting to raise this as an issue and also hoping you may know a potential work-around for this?
A potential work-around I have tried is re-applying the existing filter in the search box by following documentation here in the "Filter From Code" section: https://docs.telerik.com/blazor-ui/components/grid/filter/searchbox#filter-from-code
While I am able to apply a filter from code I cannot seem to retrieve the value that is currently in the search box as I want to reuse it. How can I achieve this with a GridSearchBox? There doesnt seem to be a property available on the GridSearchBox component for binding it's value. Would I need to create a custom filter input to achieve this?
When a filter descriptor is created and the value is of type DateTime? (nullable DateTime) the serialized value is incorrect.
DataSourceRequest request1 = new()
{
Filters = new[] {new FilterDescriptor("Test", FilterOperator.IsEqualTo, DateTime.Now.Date) {MemberType = typeof(DateTime)}},
Sorts = new List<SortDescriptor>()
};
DataSourceRequest request2 = new()
{
Filters = new[] { new FilterDescriptor("Test", FilterOperator.IsEqualTo, DateTime.Now.Date) { MemberType = typeof(DateTime?) } },
Sorts = new List<SortDescriptor>()
};
string query1 = request1.ToODataString(); // outputs $count=true&$filter=(Test%20eq%202022-05-12T00:00:00.0000000Z)&$skip=0
string query2 = request2.ToODataString(); // outputs $count=true&$filter=(Test%20eq%202022-05-12%2000:00:00)&$skip=0
The exception is -
System.ArgumentNullException: Value cannot be null. (Parameter 'source')
Here is a test page, based on this one -
@using Telerik.DataSource
@using Telerik.DataSource.Extensions
@using System.IO
<TelerikGrid TItem="@object"
LoadGroupsOnDemand="true"
Groupable="true"
OnStateInit="@((GridStateEventArgs<object> args) => OnStateInitHandler(args))"
OnRead="@ReadItems"
ScrollMode="@GridScrollMode.Virtual" PageSize="20" RowHeight="60"
Navigable="true" Sortable="true" FilterMode="@GridFilterMode.FilterRow" Height="600px">
<GridColumns>
<GridColumn Field="@nameof(Employee.Name)" FieldType="@typeof(string)" Groupable="false" />
<GridColumn Field="@nameof(Employee.Team)" FieldType="@typeof(string)" Title="Team" />
<GridColumn Field="@nameof(Employee.Salary)" FieldType="@typeof(decimal)" Groupable="false" />
<GridColumn Field="@nameof(Employee.IsOnLeave)" FieldType="@typeof(bool)" Title="On Vacation" />
</GridColumns>
</TelerikGrid>
@code {
List<object> GridData { get; set; }
protected async Task ReadItems(GridReadEventArgs args)
{
DataEnvelope<Employee> result = await MyService.GetData(args.Request);
if (args.Request.Groups.Count > 0)
{
args.Data = result.GroupedData.Cast<AggregateFunctionsGroup>().ToList();
}
else
{
args.Data = result.CurrentPageData.Cast<Employee>().ToList();
}
args.Total = result.TotalItemCount;
if (args.Request.Groups.Count > 0)
{
try
{
List<AggregateFunctionsGroup> items = result.GroupedData.Cast<AggregateFunctionsGroup>().ToList();
await using var s = new MemoryStream();
await System.Text.Json.JsonSerializer.SerializeAsync(s, items);
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
}
void OnStateInitHandler(GridStateEventArgs<object> args)
{
// set initial grouping
GridState<object> desiredState = new GridState<object>()
{
GroupDescriptors = new List<GroupDescriptor>()
{
new GroupDescriptor()
{
Member = "Team",
MemberType = typeof(string)
},
new GroupDescriptor()
{
Member = "IsOnLeave",
MemberType = typeof(bool)
}
}
};
args.GridState = desiredState;
}
public class Employee
{
public int EmployeeId { get; set; }
public string Name { get; set; }
public string Team { get; set; }
public bool IsOnLeave { get; set; }
public decimal Salary { get; set; }
}
public class DataEnvelope<T>
{
public List<AggregateFunctionsGroup> GroupedData { get; set; }
public List<T> CurrentPageData { get; set; }
public int TotalItemCount { get; set; }
}
public static class MyService
{
private static List<Employee> SourceData { get; set; }
public static async Task<DataEnvelope<Employee>> GetData(DataSourceRequest request)
{
if (SourceData == null)
{
SourceData = new List<Employee>();
var rand = new Random();
for (int i = 1; i <= 2500; i++)
{
SourceData.Add(new Employee()
{
EmployeeId = i,
Name = "Employee " + i.ToString(),
Team = "Team " + i % 100,
IsOnLeave = i % 3 == 0,
Salary = rand.Next(1000, 5000)
});
}
}
await Task.Delay(500);// deliberate delay to showcase async operations, remove in a real app
// retrieve data as needed, you can find more examples and runnable projects here
// https://github.com/telerik/blazor-ui/tree/master/grid/datasourcerequest-on-server
var datasourceResult = SourceData.ToDataSourceResult(request);
DataEnvelope<Employee> dataToReturn;
if (request.Groups.Count > 0)
{
dataToReturn = new DataEnvelope<Employee>
{
GroupedData = datasourceResult.Data.Cast<AggregateFunctionsGroup>().ToList(),
TotalItemCount = datasourceResult.Total
};
}
else
{
dataToReturn = new DataEnvelope<Employee>
{
CurrentPageData = datasourceResult.Data.Cast<Employee>().ToList(),
TotalItemCount = datasourceResult.Total
};
}
return await Task.FromResult(dataToReturn);
}
}
}
In hierarchical Grid with InCell edit the DateTime cells of the child Grid cannot be edited through the calendar popup. Trying to open the DatePicker or DateTimePicker popup of the child Grid automatically closes the edited cell.
If the Grid has no data, selecting null PageSize throws:
Error: System.ArgumentException: Page Size cannot be less than one (Parameter 'PageSize') ---
ADMIN EDIT
---
A possible workaround for the time being will be to use some conditional CSS to disable the PageSize dropdown while there is no data in the Grid: https://blazorrepl.telerik.com/QcOpkTlb38EDFboT34.
The feature request is to be able to customize the GridCsvExportOptions and GridExcelExportOptions from the API methods -
It will be useful to be able to customize the columns and data to be exported.
===
Telerik edit:
A possible workaround is to click the built-in Grid export buttons with JavaScript. With this approach, you will be able to use the built-in export options and events. Here is a REPL example.
Grid headers are misaligned if they are navigated in a scrolling scenario with a Frozen column.
===
ADMIN EDIT
===
The behavior affects the TreeList as well in a similar fashion. The misalignment is bigger when there is a frozen column but it is also reproducible without it in this demo.
I am adding validation messages for the popup form fields and I do not want to display the ValidationSummary in addition to them. Please add option to remove it.
---
ADMIN EDIT
---
Built-in field validation messages will be exposed in future version of the product. Thus, you can add inline or tooltip validation messages to the Popup edit form without an EditorTemplate.
For the time being, you can remove the ValidationSummary with some CSS. Here is an example of hiding the ValidationSummary and adding inline ValidationMessage for the ProductName field: https://blazorrepl.telerik.com/cckycgPf37NZfy9J11
Expose GroupableSettings with an option to specify whether to render the group footer. The possible values should be always (like current implementation), or when the group is expanded. An example (just for demonstration) api would be:
```
<GridSettings>
<GridGroupableSettings Footer="@GridGroupableFooterVisible.Always | @GridGroupableFooterVisible.Expanded"></GridGroupableSettings>
</GridSettings>
```
I'd like for someone to be able to select all of the rows in a particular group. The main selection checkbox will just select all of the rows.
It would be nice if this also worked for sub grouping.
I want to place the Pager on top of the Grid. I know it can be handled with a Pager component integration in the Grid Toolbar, but I want to use the Toolbar for other purposes/actions. Please allow control over the Pager position.
I have created a custom model where I added an ExpandoObject and a couple properties to it. The Grid seems to render the data successfully but the data operations are not possible - the nested properties are treated as invalid. Please add support for nested ExpandoObject properties in custom models.
---
ADMIN EDIT
---
For the time being, there is a workaround that you may try. Use the ExpandoObject directly, do not nest it in the custom model - bind the Grid Data to a collection of ExpandoObject and populate its properties in the OnInitialized.
@using System.Dynamic
<TelerikGrid Data="@Data"
Pageable="true" Sortable="true" Groupable="true"
FilterMode="Telerik.Blazor.GridFilterMode.FilterRow"
EditMode="@GridEditMode.Incell"
Resizable="true" Reorderable="true">
<GridColumns>
<GridColumn Field="Id" FieldType="typeof(string)" Width="120px" />
<GridColumn Field="DetailData.PropertyInt" Title="Column A" FieldType="@typeof(int)" />
<GridColumn Field="DetailData.ProptertyString" Title="Column B" FieldType="@typeof(string)"/>
<GridColumn Field="DetailData.PropertyDate" Title="Column C" FieldType="@typeof(DateTime)"/>
</GridColumns>
</TelerikGrid>
@code {
public ExpandoObject[] Data { get; set; } = Array.Empty<ExpandoObject>();
protected override async Task OnInitializedAsync()
{
Data = new ExpandoObject[]
{
GetPopulatedExpando(1),
GetPopulatedExpando(2),
GetPopulatedExpando(3),
GetPopulatedExpando(4),
GetPopulatedExpando(5),
};
}
private ExpandoObject GetPopulatedExpando(int id)
{
dynamic expando = new ExpandoObject();
expando.Id = id;
dynamic nested = new ExpandoObject();
nested.PropertyInt = id;
nested.ProptertyString = "ID " + id;
nested.PropertyDate = new DateTime(2022, 4, id);
expando.DetailData = nested;
return expando;
}
}
Disabling the LoaderContainer prevents the Incell edit mode to work as expected
<AdminEdit>
As a workaround, set the Navigable attribute to true.
</AdminEdit>
I would like to request a simple update to the Grid component.
When a column width is too small - the column header text is cut-off or is unreadable.
For example:
It would be nice that on mouse hover, the full title would be rendered. Currently to achieve this, I have to implement a custom <HeaderTemplate> for every grid column and add a span myself:
<GridColumn Field="@nameof(SalesOrderLineItem.Quantity)">
<HeaderTemplate>
<span title="Order Quantity">Order Quantity</span>
</HeaderTemplate>
</GridColumn>
Can you update the GridColumn component and add a title attribute to the column <th> element so the browser can show the fill title should the user hover over it?
Internally it looks like you are using RadSpreadStreamProcessing for grid.ExportToExcelAsync() if you gave us an optional lamdba to manipulate IRowExporter while you are processing, it would make things a lot easier.
There were a couple other feature requests out there that you closed offering alternatives ways of doing this and we are actually just importing the stream back to RadSpreadProcessing object and then manipulating that way. Adding the Lambda would be a much more efficient way of handling this use case and probably very simple for you to implement.