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
bobtnt
December 28, 2022, 1:05am
3
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.
bobtnt
December 28, 2022, 1:26pm
4
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. )
korchev
December 28, 2022, 2:11pm
5
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:
2 Likes
bobtnt
December 28, 2022, 5:44pm
6
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.
korchev
December 28, 2022, 6:14pm
7
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
bobtnt
January 4, 2023, 3:55pm
8
Thank you very much again!
lavazza
February 9, 2024, 10:50pm
9
Hi, most is working here but ... when you put any value and you click CancelEditRow(data) still save the changes any hint ?
korchev
February 10, 2024, 8:07am
10
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.