When working with grid column templates, it would be incredibly helpful if you could filter by the content of the cell itself rather than be restricted to a field that is a part of the model. Considering that the main use case of a template is to display something in a different format from how it appears on the model I think it's fair to say that most users would then expect to be able to filter the text they see rather than some value behind the scenes.
This has been problematic for example when trying to show data from a separate object by joining on a common ID value via the template. I understand one option would be to create a separate view model for the purposes of the grid but that potentially adds additional complexity to a project just to add some basic text filtering.
One workaround I've implemented for now is to use the OnRead event to manually filter the initial collection of data for my templated columns. I use a dictionary to map id values to my desired display text and then filter using LINQ. This is workable but again adds a lot of extra steps for something that would ideally be much simpler.
Thanks,
Kevin
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);
}
}
}
This feature request is to provide an option to configure the displayed format of the editor for the GridColumn. It is essential for the numeric and date editing. An alternative would be to follow the DisplayFormat parameter and reuse it in the DatePickers and NumericTextBox. However, we need to gather feedback for the required functionality from our customers.
Scenario
Rendering the grid column like so:
<GridColumn Visible="true" Field="ScalePercent" Title="Scale Percent" DisplayFormat="{0:P5}" VisibleInColumnChooser="false" />
The data in the grid column will show the 5 decimal precision. However, when we go in edit mode the value in the NumericTextBox is restricted to two decimal places.
Workaround
1. Usage of templates
2. Generic change of globalization setting for the NumericTextBox
`culture.NumberFormat.NumberDecimalDigits`
Hi,
is it possible to implement grid attribute that would disable alternating row coloring altogether?
It would leave onHover settings as is.
It's causing us problems when we color rows using onRowRender to custom color a row based on some value in the record, but alternating css "jumps in" and overrides onRowRender.
See attached screenshot (all rows should be green), but alt are still dark-grey )instead of green.
This should me marked as feature or bug.
BR, Smiljan
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
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.
Add a setting similar to the AllowUnsort so that I can disable the unsorted state of the Grid.
ADMIN EDIT:
Here is how to achieve this with the Grid state.
Currently the blazor grid must be a specific, static height. If one is not provided, the grid uses a default of 500px.
Kendo grid implementations in other UI frameworks allow for more flexibility in the height of the grid. It would be great if the blazor implementation could support this as well.
Two specific scenarios that are valueable:
1) Grid height adjusts to accomodate all of the items in the grid
For other kendo grid implementations, this is typically the case when "Scrollable" is set to false. If there is a plan to allow toggling scrolling for the blazor grid, then I think that this would come along with that.
2) Ability to set grid height to 100%
With other kendo implementations this is normally done via CSS, and is useful for when you want a "full screen" grid. This is normally combined with "Scrollable=true" and often combined with Pagination="true" as well. Currently it's not possible to do this - since the height is defined on the k-grid element, it cannot be overridden with CSS.
My grid starts with Groupable=false and at some point I may need to make it groupable. The group panel appears, but I cannot drag the column headers to it to actually group.
---
ADMIN EDIT
A workaround is to hide the grid so it can re-initialize with the new groupable setting:
Is Groupable: @IsGroupable
<TelerikButton OnClick="@ToggleGroupable">Toggle Groupable</TelerikButton>
@if (isGridVisible)
{
<TelerikGrid Data=@GridData @ref="@GridRef" Groupable="@IsGroupable" Pageable="true" Height="400px">
<GridColumns>
<GridColumn Field=@nameof(Employee.Name) Groupable="false" />
<GridColumn Field=@nameof(Employee.Team) Title="Team" />
<GridColumn Field=@nameof(Employee.IsOnLeave) Title="On Vacation" />
</GridColumns>
</TelerikGrid>
}
@code {
bool IsGroupable { get; set; }
bool isGridVisible { get; set; } = true;
TelerikGrid<Employee> GridRef { get; set; }
async Task ToggleGroupable()
{
//save state (sorting, paging,...) - it will be lost when we hide the grid
var state = GridRef.GetState();
//hide the grid so it can later re-initialize with the new groupable setting
isGridVisible = false;
await InvokeAsync(StateHasChanged);
await Task.Delay(20);
IsGroupable = !IsGroupable;
isGridVisible = true;
//afte the grid re-initialized and rendered with the new setting, restore its state
await InvokeAsync(StateHasChanged);
await Task.Delay(20);
await GridRef.SetState(state);
}
public List<Employee> GridData { get; set; }
protected override void OnInitialized()
{
GridData = new List<Employee>();
var rand = new Random();
for (int i = 0; i < 15; i++)
{
GridData.Add(new Employee()
{
EmployeeId = i,
Name = "Employee " + i.ToString(),
Team = "Team " + i % 3,
IsOnLeave = i % 2 == 0
});
}
}
public class Employee
{
public int EmployeeId { get; set; }
public string Name { get; set; }
public string Team { get; set; }
public bool IsOnLeave { get; set; }
}
}
---
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.
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.
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?