Inline Editing on Dynamic Grid

Hi There,

I have been following the example for the dynamic data grid and successfully have the rows and data showing up for any data I upload into the grid. I was hoping I would be able to take it one step further and do inline editing on the data entered. However, since component attributes do not support complex content, I cannot seem to get the binding to work right between the context for the row and the components I use in the edittemplate. Is there a way to do this?

Thanks in advance for any help you can provide.

1 Like

Hi @roycroftcr1,

Indeed the built-in Blazor editing and validation relies on @bind-Value which does not support array access expressions. A possible workaround is to use the Value property and the Change event of the components. Something like:

<RadzenDataGridColumn TItem="IDictionary<string, object>" Title="@column.Key" Type="column.Value"
    Property="@GetColumnPropertyExpression(column.Key, column.Value)" >
     <Template>
         @context[@column.Key]
    </Template>
     <EditTemplate>
          <RadzenTextBox Value=@context[@column.Key] 
            Change=@(value => @context[@column.Key] = value)  />
     </EditTemplate>
</RadzenDataGridColumn>

Validation won't work in this case though. Also full disclosure - I haven't tested that.

1 Like

Thanks for the answer. Tried the above. Error: cannot convert from object to string.

Tried to fix it by changing
Value=@context[@column.Key]
to
Value=Convert.ToString(@context[@column.Key])

But that doesn't help. Text box is showing: System.Collections.Generic.Dictionary`2[System.String,System.Object]

Also tried: Value=@context[@column.Key].ToString(). Same result.

The issue is @context cannot be accessed from EditTemplate in the same manner as from Template. Is there already a plan to make this working? Thanks again.

The following would work for editing (except it's missing EditTemplate features).

  <RadzenDataGridColumn TItem="IDictionary<string, object>" Title="@column.Key" Type="column.Value"
              Property="@GetColumnPropertyExpression(column.Key, column.Value)">
    <Template>
        @if(isInEditMode){
            <RadzenTextBox Value=@Convert.ToString(@context[@column.Key])   Change=@(args => @context[@column.Key]=args )></RadzenTextBox>
        }
        else{
            @context[@column.Key]
        }
    </Template>
  </RadzenDataGridColumn>

(Make your own button to toggle "isInEditMode" to true or false. )

Here is a modified version of our dynamic data online demo which uses inline editing.

    <RadzenDataGrid @ref="dataGrid" Data="@data" TItem="IDictionary<string, object>"
                         AllowFiltering="true" FilterMode="FilterMode.SimpleWithMenu" AllowPaging="true" AllowSorting="true">
            <Columns>
                @foreach(var column in columns)
                {
                    <RadzenDataGridColumn TItem="IDictionary<string, object>" Title="@column.Key" Type="column.Value"
                            Property="@GetColumnPropertyExpression(column.Key, column.Value)" >
                        <Template>
                            @context[@column.Key]
                        </Template>
                        <EditTemplate>
                            <RadzenTextBox Value=@context[@column.Key].ToString()
                                Change=@(value => @context[@column.Key] = value)  />
                        </EditTemplate>
                    </RadzenDataGridColumn>
                }
            <RadzenDataGridColumn TItem="IDictionary<string, object>" Context="order" Filterable="false" Sortable="false" TextAlign="TextAlign.Right" Width="156px">
                <Template Context="data">
                    <RadzenButton Icon="edit" ButtonStyle="ButtonStyle.Light" Variant="Variant.Flat" Size="ButtonSize.Medium" Click="@(args => dataGrid.EditRow(data))" @onclick:stopPropagation="true">
                    </RadzenButton>
                </Template>
                <EditTemplate Context="data">
                    <RadzenButton Icon="check" ButtonStyle="ButtonStyle.Success" Variant="Variant.Flat" Size="ButtonSize.Medium" Click="@((args) => dataGrid.UpdateRow(data))">
                    </RadzenButton>
                    <RadzenButton Icon="close" ButtonStyle="ButtonStyle.Light" Variant="Variant.Flat" Size="ButtonSize.Medium" Class="my-1 ms-1" Click="@((args) => dataGrid.CancelEditRow(data))">
                    </RadzenButton>
                </EditTemplate>
            </RadzenDataGridColumn>
        </Columns>
</RadzenDataGrid>
@code {
    public IEnumerable<IDictionary<string, object>> data { get; set; }
    private RadzenDataGrid<IDictionary<string, object>> dataGrid;

    public IDictionary<string, Type> columns { get; set; }

    public string GetColumnPropertyExpression(string name, Type type)
    {
        var expression = $@"it[""{name}""].ToString()";

        if (type == typeof(int))
        {
            return $"int.Parse({expression})";
        }
        else if (type == typeof(DateTime))
        {
            return $"DateTime.Parse({expression})";
        }

        return expression;
    }

    protected override async Task OnInitializedAsync()
    {
        await base.OnInitializedAsync();

        columns = new Dictionary<string, Type>()
        {
            { "EmployeeID", typeof(int) },
            { "FirstName", typeof(string) },
            { "LastName", typeof(string) },
            { "HireDate", typeof(DateTime) },
        };

        data = Enumerable.Range(0, 100).Select(i =>
        {
            var row = new Dictionary<string, object>();

            foreach (var column in columns)
            {
                row.Add(column.Key, column.Value == typeof(int) ? i :
                    column.Value == typeof(DateTime) ? DateTime.Now.AddMonths(i) : $"{column.Key}{i}");
            }

            return row;
        });
    }
}


And here it is in action:

dynamic-editing

2 Likes

Thank you very much for such a quick response! It works!!

The issue I reported earlier was due to my own misunderstanding of how EditTemplate works. Please disregard.

Glad it worked. Just to add something else - the solution is a bit simplified as it edits all fields as strings. If you have numbers you can use @if() to use a different editor:

<EditTemplate>
@if (context[column.Key] is int)
{
     <RadzenNumeric TValue="int" Value=@((int)context[column.Key])
         Change=@(value => context[column.Key] = value)  />
}
else
{
     <RadzenTextBox Value=@context[column.Key].ToString()
        Change=@(value => context[column.Key] = value)  />
}
</EditTemplate>
3 Likes

Thank you very much again!

Hi, most is working here but ... when you put any value and you click CancelEditRow(data) still save the changes :frowning: any hint ?

Hi @lavazza,

I suggest reviewing our forum FAQ and updating your question so it is clear what you are asking. It is very unlikely somebody would answer it right now.