Unplanned
Last Updated: 10 May 2023 09:57 by ADMIN
Created by: Andy
Comments: 3
Category: Grid
Type: Feature Request
2

Are there any plans to have the datagrid be both groupable and draggable?

Thanks,

Andy

Unplanned
Last Updated: 05 May 2023 12:04 by ADMIN
Created by: Philip
Comments: 1
Category: Grid
Type: Bug Report
1

Hello

 

What is the purpose of this (https://docs.telerik.com/blazor-ui/components/grid/selection/overview#row-drag-and-drop);

Row Drag and Drop

If the user drags selected rows, the current row selection will be cleared on row drop.

 

Is this a bug? As when you select multiple rows, then drag and drop the rows, it clears the bound selectedItems object (but the rows still remain ticked in the UI). Just confirming this is something that will be fixed?

 

Cheers

Phil

Unplanned
Last Updated: 30 Apr 2023 04:40 by Ron Hary
Created by: Ron Hary
Comments: 1
Category: Grid
Type: Feature Request
1
I want to bind the Grid to a collection of DynamicObject. 
Unplanned
Last Updated: 28 Apr 2023 12:07 by Chris

I am binding a Grid to a collection of ExpandoObjects. In the collection, there are decimal values. When I try to add Aggregates for the decimal values the Grid throws an exception. 

 

<AdminEdit>

As a workaround, you can cast the decimal values to double instead.

</AdminEdit>

Unplanned
Last Updated: 26 Apr 2023 12:56 by Riley
Created by: Stéphane
Comments: 1
Category: Grid
Type: Feature Request
25
I would like to trigger Grid's validation from my business code. 
Unplanned
Last Updated: 25 Apr 2023 06:05 by ADMIN

Hello,

I'm having issues trying to figure out how to change values (from the model) when I'm Incell Mode without triggers the OnRead events after.  The actual code is working great since I was able to remove the Incell mode on the OnChangeModel event below,  but OnRead is keeps call after (which I didn't need and slow user experience)

Is there a way to cancel the OnRead ?

 <TelerikGrid OnRead="ReadItems" EditMode="GridEditMode.Incell"
                     @ref="@GridRef">
    <GridColumns>
      <GridEditDropDownColumn Field="Test1" Data="@Eval?.ListEvaluationTypes" Title="Title" Width="130px" OnChange="OnChangeModel" />
    </GridColumns>
</TelerikGrid>

 

   private TelerikGrid<EvaluationListDTO> GridRef { get; set; }

   protected async Task OnChangeModel(object model)
        {
            var item = (EvaluationListDTO)model;

            var state = GridRef?.GetState();

           //Save in the Database  

                // use the state to remove the edited item (close the editor)
                state.EditItem = null;
                state.OriginalEditItem = null;
                await GridRef.SetStateAsync(state);
        }

Unplanned
Last Updated: 21 Apr 2023 19:54 by Frank
When you have Sortable set to true and you click on the header, the sorting direction goes from ascending to descending to neutral. I would like to configure my Grid so that when clicking on the header the sorting direction will start from descending, go to neutral, and after that to ascending or any other order. 
Unplanned
Last Updated: 21 Apr 2023 13:29 by Víctor
Created by: Víctor
Comments: 0
Category: Grid
Type: Feature Request
4

===ADMIN EDIT===

Currently, we use groups for calculating all aggregates in Grid. We can optimize the process so that when there are no groups, specific aggregates are still calculated.

Unplanned
Last Updated: 21 Apr 2023 08:51 by Deasun
Double quotes are useful to wrap cell values when the comma is not a delimiter, but part of the value. 
Unplanned
Last Updated: 19 Apr 2023 08:57 by ADMIN
Currently, the GroupHeaderTemplate takes up the whole row. Once it exposes aggregates for all the fields, I will need an option to align them with the corresponding columns.
Completed
Last Updated: 10 Apr 2023 13:57 by ADMIN
Release 4.2.0 (04/26/2023)
I am trying to customize the Update button in the popup to show a different text while I am updating an item. THe same approach works in the Inline mode, but not in Popup.
Declined
Last Updated: 05 Apr 2023 18:32 by ADMIN
Created by: Ed
Comments: 3
Category: Grid
Type: Feature Request
0

The Blazor TelerikGrid component should support a dropdown column.  It should be exactly the same as the dropdown column in the Ajax grid.

https://docs.telerik.com/devtools/aspnet-ajax/controls/grid/columns/column-types#dropdown

Unplanned
Last Updated: 05 Apr 2023 09:13 by ADMIN
Created by: Kenny
Comments: 9
Category: Grid
Type: Feature Request
23

It would be nice if I could specify an item in the inline editor (or any other for that matter) to get focus when the editor is activated.

Thanks,
Kenny

===

Telerik edit:

A possible workaround is:

  1. Define an <EditorTemplate> for the column(s) that can receive automatic focus in edit mode. The editor component inside it must have a @ref.
  2. (optional) Set a flag that points to the edit field to focus, if it will be dynamic.
  3. Check the flag value in OnAfterRenderAsync and focus the respective editor programmatically after a delay.

The example below also shows how to enter Grid edit mode programmatically and how to focus a specific field when editing with OnRowClick.

<TelerikGrid @ref="@GridInlineRef"
             Data="@GridInlineData"
             EditMode="@GridEditMode.Inline"
             OnAdd="@OnGridAddEdit"
             OnEdit="@OnGridAddEdit"
             OnCreate="@OnGridInlineCreate"
             OnUpdate="@OnGridInlineUpdate"
             OnRowClick="@OnGridRowClick">
    <GridToolBarTemplate>
        <GridCommandButton Command="Add">Add</GridCommandButton>
    </GridToolBarTemplate>
    <GridColumns>
        <GridColumn Field="@nameof(Product.Name)">
            <EditorTemplate>
                @{ var editItem = (Product)context; }
                <TelerikTextBox @ref="@NameTextBoxRef" @bind-Value="@editItem.Name" DebounceDelay="0" />
            </EditorTemplate>
        </GridColumn>
        <GridColumn Field="@nameof(Product.Price)">
            <EditorTemplate>
                @{ var editItem = (Product)context; }
                <TelerikNumericTextBox @ref="@PriceNumericTextBoxRef" @bind-Value="@editItem.Price" DebounceDelay="0" />
            </EditorTemplate>
        </GridColumn>
        <GridColumn Field="@nameof(Product.Stock)">
            <EditorTemplate>
                @{ var editItem = (Product)context; }
                <TelerikNumericTextBox @ref="@StockNumericTextBoxRef" @bind-Value="@editItem.Stock" DebounceDelay="0" />
            </EditorTemplate>
        </GridColumn>
        <GridCommandColumn>
            <GridCommandButton Command="Edit">Edit</GridCommandButton>
            <GridCommandButton Command="Save" ShowInEdit="true">Update</GridCommandButton>
            <GridCommandButton Command="Cancel" ShowInEdit="true">Cancel</GridCommandButton>
        </GridCommandColumn>
    </GridColumns>
</TelerikGrid>

@code {
    private TelerikGrid<Product>? GridInlineRef { get; set; }
    private TelerikTextBox? NameTextBoxRef { get; set; }
    private TelerikNumericTextBox<decimal?>? PriceNumericTextBoxRef { get; set; }
    private TelerikNumericTextBox<int>? StockNumericTextBoxRef { get; set; }
    private string EditFieldToFocus { get; set; } = string.Empty;

    private List<Product> GridInlineData { get; set; } = new List<Product>();

    private void OnGridAddEdit(GridCommandEventArgs args)
    {
        EditFieldToFocus = nameof(Product.Stock);
    }

    private async Task OnGridRowClick(GridRowClickEventArgs args)
    {
        EditFieldToFocus = args.Field;
        var itemToEdit = (Product)args.Item;

        args.ShouldRender = true;

        if (GridInlineRef != null)
        {
            var gridState = GridInlineRef.GetState();

            gridState.InsertedItem = null!;
            gridState.OriginalEditItem = itemToEdit;
            gridState.EditItem = itemToEdit.Clone();

            await GridInlineRef.SetStateAsync(gridState);
        }
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (!string.IsNullOrEmpty(EditFieldToFocus))
        {
            await Task.Delay(200);

            switch (EditFieldToFocus)
            {
                case nameof(Product.Name):
                    if (NameTextBoxRef != null)
                    {
                        await NameTextBoxRef.FocusAsync();
                    }
                    break;
                case nameof(Product.Price):
                    if (PriceNumericTextBoxRef != null)
                    {
                        await PriceNumericTextBoxRef.FocusAsync();
                    }
                    break;
                case nameof(Product.Stock):
                    if (StockNumericTextBoxRef != null)
                    {
                        await StockNumericTextBoxRef.FocusAsync();
                    }
                    break;
                default:
                    break;
            }

            EditFieldToFocus = string.Empty;
        }
    }

    #region Programmatic Inline Editing

    private async Task InlineAdd()
    {
        var gridState = GridInlineRef!.GetState();

        gridState.InsertedItem = new Product();
        gridState.InsertedItem.Name = "New value";
        gridState.OriginalEditItem = null!;
        gridState.EditItem = null!;

        await GridInlineRef.SetStateAsync(gridState);
    }

    private async Task InlineEdit()
    {
        if (GridInlineData.Any())
        {
            var gridState = GridInlineRef!.GetState();

            gridState.InsertedItem = null!;
            gridState.OriginalEditItem = GridInlineData.First();
            gridState.EditItem = GridInlineData.First().Clone();
            gridState.EditItem.Name = "Updated inline value";

            EditFieldToFocus = nameof(Product.Price);

            await GridInlineRef.SetStateAsync(gridState);
        }
    }

    private async Task InlineCancel()
    {
        var gridState = GridInlineRef!.GetState();

        gridState.InsertedItem = null!;
        gridState.OriginalEditItem = null!;
        gridState.EditItem = null!;

        await GridInlineRef.SetStateAsync(gridState);
    }

    private async Task InlineUpdate()
    {
        var gridState = GridInlineRef!.GetState();

        if (gridState.EditItem != null)
        {
            OnGridInlineUpdate(new GridCommandEventArgs()
            {
                Item = gridState.EditItem
            });
        }
        else if (gridState.InsertedItem != null)
        {
            OnGridInlineCreate(new GridCommandEventArgs()
            {
                Item = gridState.InsertedItem
            });
        }

        gridState.InsertedItem = null!;
        gridState.OriginalEditItem = null!;
        gridState.EditItem = null!;

        await GridInlineRef.SetStateAsync(gridState);
    }

    #endregion Programmatic Inline Editing

    #region Grid Inline Editing Handlers

    private void OnGridInlineUpdate(GridCommandEventArgs args)
    {
        var updatedItem = (Product)args.Item;
        var index = GridInlineData.FindIndex(i => i.Id == updatedItem.Id);
        if (index != -1)
        {
            GridInlineData[index] = updatedItem;
        }
    }

    private void OnGridInlineCreate(GridCommandEventArgs args)
    {
        var createdItem = (Product)args.Item;
        createdItem.Id = Guid.NewGuid();
        GridInlineData.Insert(0, createdItem);
    }

    #endregion Grid Inline Editing Handlers

    #region Data Generation and Model

    protected override void OnInitialized()
    {
        for (int i = 1; i <= 3; i++)
        {
            GridInlineData.Add(new Product()
            {
                Id = Guid.NewGuid(),
                Name = $"Product {i}",
                Price = Random.Shared.Next(1, 100) * 1.23m,
                Stock = (short)Random.Shared.Next(0, 1000)
            });
        }
    }

    public class Product
    {
        public Guid Id { get; set; }
        public string Name { get; set; } = string.Empty;
        public decimal? Price { get; set; }
        public int Stock { get; set; }
        public DateTime ReleaseDate { get; set; }
        public bool InProduction { get; set; }

        public Product Clone()
        {
            return new Product()
            {
                Id = Id,
                Name = Name,
                Price = Price,
                Stock = Stock,
                ReleaseDate = ReleaseDate,
                InProduction = InProduction
            };
        }
    }

    #endregion Data Generation and Model
}

 

Declined
Last Updated: 03 Apr 2023 11:07 by ADMIN
Created by: Clark
Comments: 1
Category: Grid
Type: Bug Report
1

Problem

It seems the Grid and GridSearchBox assume the search string by taking the value of GridState.SearchFilter.FilterDescriptors[0].Value and this is causing a few issues:

  1. If the first filter is a CompositeFilterDescriptor, it causes an exception.
  2. If there is no filter, the search box gets cleared.
  3. If the first filter has a different value than what was typed (because filters were added/changed programmatically), the search box value will be changed.

Background

I am expanding grid search to include non-string columns, and I want this to apply by default across our entire application without having to update every grid individually or developers having to remember to opt in.

To search other type columns, I’ve largely taken the logic from Search Grid in numeric and date fields - Telerik UI for Blazor and it works well. However, that solution utilizes a custom search box component that I would have to add to each grid.

Instead, I have placed this filter creation logic in the OnStateChanged handler as exemplified in How to Search Grid Items with a StartsWith Filter Operator - Telerik UI for Blazor, as we already have a handler for this event that all grids utilize.

This has worked wonderfully except for the issues I’ve mentioned.

Issue #1 – CompositeFilterDescriptor causes exception

If the first filter is a CompositeFilterDescriptor, it causes an exception. Specifically:

Unable to cast object of type 'Telerik.DataSource.CompositeFilterDescriptor' to type 'Telerik.DataSource.FilterDescriptor'.
   at Telerik.Blazor.Components.Common.TableGridBase`2.LoadSearchFilter(IFilterDescriptor descriptor)
   at Telerik.Blazor.Components.TelerikGrid`1.SetStateInternal(GridState`1 state)
   at Telerik.Blazor.Components.TelerikGrid`1.<SetStateAsync>d__311.MoveNext()
   at Web.Pages.Grid.<OnStateChangedHandler>d__18.MoveNext() in C:\src\Web\Pages\Grid.razor:line 196

If there is another filter in the collection that is not a CompositeFilterDescriptor, I can work around this problem by moving it to the front of the list.

// Make sure first filter is not composite.
var nonCompositeFilter = newSearchFilter.FilterDescriptors.OfType<FilterDescriptor>().FirstOrDefault();
if (nonCompositeFilter is not null && newSearchFilter.FilterDescriptors[0] is CompositeFilterDescriptor)
{
    newSearchFilter.FilterDescriptors.Remove(nonCompositeFilter);
    newSearchFilter.FilterDescriptors.Insert(0, nonCompositeFilter);
}

However, if all filters are composite, the exception is unavoidable.

Issue #2 – Search box gets cleared

If the GridState.SearchFilter.FilterDescriptors collection is empty, the search box gets cleared. This is a problem when a user needs to type more characters for a filter to be created.

For example, let’s say you are only searching DateTime columns and using the logic from Search Grid in numeric and date fields - Telerik UI for Blazor. As you type, it checks to see if the input is an integer between 1000 and 2100. Until you type the fourth digit, it will not meet that condition thus will not add a filter. So if you begin by typing “2”, it searches and a filter will not be added yet. However, because there are no filters, it will clear the search box. You won’t be able to type out a full year value of “2023” unless you type fast enough to outpace the debounce delay.

Issue #3 – Search box gets changed

Using the same example as above but with an Enum column instead of a DateTime, begin typing text. If the text matches an enum name, a filter is added for the enum item’s underlying value. For example:

  1. Type “e”.
  2. The first enum item’s name matches “e”, so a filter is added for (int)item IsEqualTo 0.
  3. The search box text is replaced with “0”.

Possible solutions?

  1. Is there some sort of “dummy” filter descriptor I could add to the beginning of the FilterDescriptors collection? Like, it would contain the search string as the Value but it would always evaluate to true and never affect which records match?
  2. I give in and create a custom search box component to hold the search string value separate from GridState, which would require me to update every current and future grid after all.
  3. Telerik could add a SearchString property to the GridState separate from the SearchFilter so that any filter changes would not affect the search string. Or something.

Sample project attached.

Duplicated
Last Updated: 30 Mar 2023 08:15 by ADMIN
Created by: Daniel
Comments: 1
Category: Grid
Type: Feature Request
4

I am trying to get the currently filtered data out of the grid as per this KB article and I want to include the searchbox filters. I do not, however, want to use OnRead but I want to get the grid state on a click of a button and get the filters plus the searchbox filters from it instead.

---

ADMIN EDIT

Here is a sample of getting those filters through the OnRead event without using remote operations - all the data is in the view model (the SourceData field) so this does not change the way operations happen compared to not using OnRead.

@using Telerik.DataSource
@using Telerik.DataSource.Extensions

@( new MarkupString(output) )

<br />
<TelerikButton OnClick="@GetFilters">Get Filters</TelerikButton>


<TelerikGrid Data=@GridData TotalCount=@Total OnRead=@ReadItems
             FilterMode=@GridFilterMode.FilterRow Sortable=true Pageable=true EditMode="@GridEditMode.Inline">
    <GridToolBar>
        <GridSearchBox />
    </GridToolBar>
    <GridColumns>
        <GridColumn Field=@nameof(Employee.ID) />
        <GridColumn Field=@nameof(Employee.Name) Title="Name" />
        <GridColumn Field=@nameof(Employee.HireDate) Title="Hire Date" />
        <GridCommandColumn>
            <GridCommandButton Command="Save" Icon="save" ShowInEdit="true">Update</GridCommandButton>
            <GridCommandButton Command="Edit" Icon="edit">Edit</GridCommandButton>
            <GridCommandButton Command="Delete" Icon="delete">Delete</GridCommandButton>
            <GridCommandButton Command="Cancel" Icon="cancel" ShowInEdit="true">Cancel</GridCommandButton>
        </GridCommandColumn>
    </GridColumns>
</TelerikGrid>

@code {
    TelerikGrid<Employee> GridRef { get; set; }
    string output { get; set; }
    public DataSourceRequest CurrentRequest { get; set; }
    void GetFilters()
    {
        output = string.Empty;


        foreach (var item in CurrentRequest.Filters)
        {
            if (item is FilterDescriptor) // filter row
            {
                FilterDescriptor currFilter = item as FilterDescriptor;
                output += $"field: {currFilter.Member}, operator {currFilter.Operator}, value: {currFilter.Value}<br />";
            }

            if (item is CompositeFilterDescriptor) // filter menu
            {
                CompositeFilterDescriptor currFilter = item as CompositeFilterDescriptor;
                output += $"START nested filter: logical operator: {currFilter.LogicalOperator}, details:<br />";
                // there will actually be 1 or 2 only, this showcases the concept and the types
                foreach (FilterDescriptor nestedFilter in currFilter.FilterDescriptors)
                {

                    output += $"field: {nestedFilter.Member}, operator {nestedFilter.Operator}, value: {nestedFilter.Value}<br />";
                }
                output += "END nested filter<br />";
            }
        }
    }




    public List<Employee> SourceData { get; set; }
    public List<Employee> GridData { get; set; }
    public int Total { get; set; } = 0;

    protected override void OnInitialized()
    {
        SourceData = GenerateData();
    }

    protected async Task ReadItems(GridReadEventArgs args)
    {
        CurrentRequest = args.Request;


        var datasourceResult = SourceData.ToDataSourceResult(args.Request);

        GridData = (datasourceResult.Data as IEnumerable<Employee>).ToList();
        Total = datasourceResult.Total;

        StateHasChanged();
    }

    //This sample implements only reading of the data. To add the rest of the CRUD operations see
    //https://docs.telerik.com/blazor-ui/components/grid/editing/overview

    private List<Employee> GenerateData()
    {
        var result = new List<Employee>();
        var rand = new Random();
        for (int i = 0; i < 100; i++)
        {
            result.Add(new Employee()
            {
                ID = i,
                Name = "Name " + i,
                HireDate = DateTime.Now.Date.AddDays(rand.Next(-20, 20))
            });
        }

        return result;
    }

    public class Employee
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public DateTime HireDate { get; set; }
    }
}

---

Unplanned
Last Updated: 20 Mar 2023 10:54 by Michael

Imagine a Grid with two editable columns, which are separated by a few non-editable ones. In the standard use case, tabbing from the first editable column should jump over the non-editable columns, and the user should end up in the second editable column.

However, if the Grid uses virtual columns and the second editable column is not rendered, tab-to-edit will stop working.

Unplanned
Last Updated: 15 Mar 2023 11:53 by Jakub
Expose a parameter that allows changing the default behavior of the CheckboxList filters. Currently, all distinct options are included in the CheckBoxList. It would be useful if we can configure this and make the filters cascade like in an excel table.
Completed
Last Updated: 14 Mar 2023 12:09 by ADMIN

Hello,

I seem to have stubled upon a strange bug in TelerikGrid. We have wrapped a TelerikGrid and the Columns are also wrapped to allow special actions.
The bug is present in "raw-telerik-code" as well.

We have an edge case where we have a TelerikGrid and some of its columns should be Locked (Stickied/Frozen) as a default behaviour.
But depending on user interaction we want to change the state. We cannot use a property for each column that we want to be Locked/Unlocked as it should be handled by the GridState.

When the Column is using default behaviour (not Templated), it works as intended. But as soon as you use a <Template> for the Column, the Locked state cannot be changed from the default/supplied value.

TLDR: Programmatically changing the Locked state of a column where the cell is templated will not change the locked state.

I have prepared two REPL examples. One for 3.7.0 as it is what we currently are using, and one for 4.0.1 as to prove that it still exists in the current itteration.

3.7.0
https://blazorrepl.telerik.com/cHEHurlI06olUsJ410


4.0.1
https://blazorrepl.telerik.com/cdYRuBvo07aB6BGY39

 

With best regards

Completed
Last Updated: 08 Mar 2023 10:07 by ADMIN
Release 4.1.0 (15/03/2023)
Created by: Meindert
Comments: 2
Category: Grid
Type: Bug Report
2
Triggering edit mode leads to re-renders in other cells. 
Unplanned
Last Updated: 06 Mar 2023 11:53 by Peter

Currently, the Grid doesn't display its built-in loading animation on initial data (page) load.

The OnRead handler is now completely decoupled with the Data parameter, so the limitation can be removed at least for OnRead scenarios.