Completed
Last Updated: 15 Aug 2019 12:15 by ADMIN
Release 1.5.0
Kenny
Created on: 15 May 2019 07:21
Category: Grid
Type: Bug Report
18
The grid does not update on data source change

When you change the data source of the grid, it must re-render the data again.

For example, when you use a custom edit form, you add/edit the data with your own code and not through the grid. This is useful, for example, when you only want to show a few columns in the grid, but the model has many more editable fields. Or, when you want a customized layout/behavior of the edit form.

Minimum repro:

 

@using Telerik.Blazor.Components.Grid
@using Telerik.Blazor.Components.Button
 
<TelerikButton OnClick="@ChangeProduct">Works: Change an existing product</TelerikButton>
<TelerikButton OnClick="@AddProduct">Does not work: Add a new product</TelerikButton>
<TelerikButton OnClick="@RemoveProduct">Does not work: Remove an existing product</TelerikButton>
 
<TelerikGrid Data=@GridData
             Pageable="true">
    <TelerikGridColumns>
        <TelerikGridColumn Field=@nameof(Product.ProductName) Title="Product Name" />
        <TelerikGridColumn Field=@nameof(Product.UnitPrice) Title="Unit Price">
        </TelerikGridColumn>
    </TelerikGridColumns>
</TelerikGrid>
 
 
@functions {
    public List<Product> GridData { get; set; }
 
    void AddProduct()
    {
        GridData.Insert(0, new Product()
        {
            ProductId = DateTime.Now.Millisecond,
            ProductName = "some product name",
            UnitPrice = DateTime.Now.Second
        });
 
        //after updating the data, the grid should show the item at the top of the first page.
        //at the moment, you need to page, for example, for the data to be updated
    }
 
    protected void ChangeProduct()
    {
        GridData.Where(p => p.ProductId == 2).First().ProductName = "changed at " + DateTime.Now;
    }
 
    protected void RemoveProduct()
    {
        GridData.RemoveAt(4);
 
        //after updating the data, the grid should remove the fourth item immediately
        //at the moment, you need to page, for example, for the data to be updated
    }
 
 
    protected override void OnInit()
    {
        GridData = new List<Product>();
        for (int i = 0; i < 25; i++)
        {
            GridData.Add(new Product()
            {
                ProductId = i,
                ProductName = "Product" + i.ToString(),
                UnitPrice = (decimal)(i * 3.14),
            });
        }
    }
 
    public class Product
    {
        public string ProductName { get; set; }
        public decimal UnitPrice { get; set; }
        public int ProductId { get; set; }
    }
}
6 comments
ADMIN
Marin Bratanov
Posted on: 15 Aug 2019 12:15
Hi all,

Here's the new demo that showcases support for observable collections that is available in 1.5.0: https://demos.telerik.com/blazor-ui/grid/observable-data.


Regards,
Marin Bratanov
Progress Telerik UI for Blazor
Marin Bratanov
Posted on: 02 Aug 2019 13:34
Our next release (planned version number 1.5.0) will provide support for INotifyCollectionChanged, so if the data source of the grid is an ObservableCollection<T>, instead of a List<T>, adding/removing items will start updating the grid automatically. Perhaps we will also add a .Refresh() method so you can trigger a re-evaluation of the data source for other situations, but this may or may not make it into 1.5.0.
Kenny
Posted on: 19 Jun 2019 22:04
Ah yes!  The combination of the two worked.  I too had to add the delay or it would not work.
ADMIN
Marin Bratanov
Posted on: 19 Jun 2019 13:57
Hello Marcel,

Thank you for sharing this idea, I should have thought of that when logging the bug :)

On my end, this didn't update as-is, though, but that may just be my slow laptop and some optimization where Blazor tries to do as little diffs as possible. That said, adding a small unnoticeable delay did work for me too, here's what I used (only the changed methods are added):

async Task EnsureGridDataSourceUpdates()
{
    var tmp = this.GridData; // save for later
 
    this.GridData = null; // set to something else -> null
 
    this.StateHasChanged(); // to let the ui reevaluate
 
    await Task.Delay(10); //let the UI update - may not always be necessary, so you may avoid using all async methods
 
    this.GridData = tmp; // reassign your data
 
    this.StateHasChanged(); // to let the ui reevaluate
}
 
async Task AddProduct()
{
    GridData.Insert(0, new Product()
    {
        ProductId = DateTime.Now.Millisecond,
        ProductName = "some product name",
        UnitPrice = DateTime.Now.Second
    });
 
    await this.EnsureGridDataSourceUpdates();
}
 
protected async Task RemoveProduct()
{
    GridData.RemoveAt(4);
 
    await this.EnsureGridDataSourceUpdates();
}


Regards,
Marin Bratanov
Progress Telerik UI for Blazor

Marcel
Posted on: 18 Jun 2019 20:53

@kenny hi,

you may work around it by reassigning the property which is set as the Data for the Grid.

 

In your example this would help:

var tmp = this.GridData; // save for later

this.GridData = null; // set to something else -> null

this.StateHasChanged(); // to let the ui reevaluate

this.GridData = tmp; // reassign your data

this.StateHasChanged(); // to let the ui reevaluate

 

This will reapply the whole dataSource, so a minimal refresh like the one known from 'INotifyCollectionChanged' would be much better.

Kenny
Posted on: 18 Jun 2019 20:05

Hey, any idea when this will be released?  It is causing me to hold back a release.

Any ideas for a workaround?  Even a really hacky workaround ;-)

 

Thanks,

Kenny