asp.net-coreblazor-server-side.net-6.0radzen

Radzen DataGrid possible bug when adding a new row


When adding a new row, I clicked the Add New Order button, edit template opens. If I click somewhere like Vendor filter, the Add New Order button stays disabled as in the screenshot and the edit template disappears.

enter image description here And also after clicking Add New Order fill the necessary fields/clicking the SaveRow button, this newly added row doesn't appear on the data grid until I refresh the page. How can I make it appear without refreshing the page?

By the way, I am using SQL Server Express 2019.

Hope you can help me.

Here is the code:

@page "/orders"
@using IMS.CoreBusiness
@using IMS.Plugins.EFCore.Migrations
@using IMS.UseCases.Interfaces.Order
@using IMS.UseCases.Interfaces.OrderDetail
@using System.Globalization


@inject NavigationManager NavigationManager
@inject IViewAllOrdersUseCase ViewAllOrdersUseCase
@inject IAddOrderUseCase AddOrderUseCase
@inject IEditOrderUseCase EditOrderUseCase
@inject IAddOrderDetailUseCase AddOrderDetailUseCase
@inject IEditOrderDetailUseCase EditOrderDetailUseCase
<style>
    #wrapper { overflow: auto; }

    #c1 { float: right; }

    #c2 { float: right; }
</style>

<h1>Orders</h1>
<RadzenButton Icon="add_circle_outline" style="margin-bottom: 10px" Text="Add New Order" Click="@InsertRow" Disabled="@(_orderToInsert != null)"/>
<RadzenDataGrid @ref="_grid" AllowFiltering="true" AllowPaging="true" PageSize="7" AllowSorting="true" RowClick="RowClick" ExpandMode="DataGridExpandMode.Single"
                Data="@_orders" TItem="Order" EditMode="DataGridEditMode.Single" RowUpdate="@OnUpdateRow" RowCreate="@OnCreateRow" @bind-Value="@SelectedOrders"
                ShowExpandColumn="true" ShowPagingSummary="true" AllowColumnResize="true">
    <Template Context="order">
        <RadzenCard Style="margin-bottom: 20px">
            Vendor:
            <b>@order?.VendorName</b>
        </RadzenCard>
        <RadzenTabs>
            <Tabs>
                <RadzenTabsItem Text="Order Details">
                    <div id="wrapper">
                        <RadzenButton Icon="add_circle_outline" style="margin-bottom: 10px" Text="Add Order Detail" Click="@(() => InsertDetailRow(order.Id))" Disabled="@(_detailToInsert != null)"/>
                        <RadzenButton Icon="save" style="margin-bottom: 10px;" Text="Save Details" id="c2" Click="@(args => SaveRowDetails(SelectedOrders.FirstOrDefault()?.OrderDetails))"/>
                        <RadzenButton Icon="border_color" style="margin-bottom: 10px; margin-right: 10px" Text="Edit Details" id="c1" Click="@(args => EditRowDetails(SelectedOrders.FirstOrDefault()?.OrderDetails))" @onclick:stopPropagation="true"/>
                    </div>
                    <RadzenDataGrid @ref="_gridDetail" AllowFiltering="true" AllowPaging="true" PageSize="5" AllowSorting="true" Data="@order.OrderDetails" 
                    TItem="OrderDetail" EditMode="DataGridEditMode.Multiple" RowUpdate="@OnUpdateRowDetail" RowCreate="@OnCreateRowDetail" AllowColumnResize="true" AllowColumnPicking="true" ShowPagingSummary="true" ColumnWidth="150px">
                        <Columns>

                            <RadzenDataGridColumn TItem="OrderDetail" Property="Id" Title="Product Number"/>
                            <RadzenDataGridColumn TItem="OrderDetail" Property="ProductCode" Title="Code">
                                <EditTemplate Context="orderDetail">
                                    <RadzenTextBox @bind-Value="orderDetail.ProductCode" Style="width: 100%; display: block" Name="ProductCode"/>
                                    <RadzenRequiredValidator Text="Product Code is required" Component="ProductCode" Popup="true" Style="position: absolute"/>
                                </EditTemplate>
                            </RadzenDataGridColumn>
                            <RadzenDataGridColumn TItem="OrderDetail" Property="ProductName" Title="Name">
                                <EditTemplate Context="orderDetail">
                                    <RadzenTextBox @bind-Value="orderDetail.ProductName" Style="width: 100%; display: block" Name="ProductName"/>
                                    <RadzenRequiredValidator Text="Product Name is required" Component="ProductName" Popup="true" Style="position: absolute"/>
                                </EditTemplate>
                            </RadzenDataGridColumn>
                            <RadzenDataGridColumn TItem="OrderDetail" Property="UnitCost" Title="Unit Cost">
                                <EditTemplate Context="orderDetail">
                                    <RadzenNumeric TValue="double" Min="1" @bind-Value="orderDetail.UnitCost" Style="width: 100%; display: block" Name="UnitCost"/>
                                    <RadzenRequiredValidator Text="Unit Cost is required" Component="UnitCost" Popup="true" Style="position: absolute"/>
                                </EditTemplate>
                                <Template Context="detail">
                                    @string.Format(new CultureInfo("en-US"), "{0:C}", detail.UnitCost)
                                </Template>
                                <FooterTemplate>
                                    <b>@string.Format(new CultureInfo("en-US"), "{0:C}", SelectedOrders?.FirstOrDefault()?.OrderDetails.Sum(o => o.UnitCost))</b>
                                </FooterTemplate>
                            </RadzenDataGridColumn>
                            <RadzenDataGridColumn TItem="OrderDetail" Property="BuyQuantity" Title="Buy Qty">
                                <EditTemplate Context="orderDetail">
                                    <RadzenNumeric TValue="int" Min="1" @bind-Value="orderDetail.BuyQuantity" Style="width: 100%; display: block" Name="BuyQuantity"/>
                                    <RadzenRequiredValidator Text="Buy Quantity is required" Component="BuyQuantity" Popup="true" Style="position: absolute"/>
                                </EditTemplate>
                                <FooterTemplate>
                                    <b>@string.Format(new CultureInfo("tr-TR"), "{0:G}", SelectedOrders?.FirstOrDefault()?.OrderDetails.Sum(o => o.BuyQuantity))</b>
                                </FooterTemplate>
                            </RadzenDataGridColumn>
                            <RadzenDataGridColumn TItem="OrderDetail" Property="SellQuantity" Title="Sell Qty">
                                <EditTemplate Context="orderDetail">
                                    <RadzenNumeric TValue="int" Min="1" @bind-Value="orderDetail.SellQuantity" Style="width: 100%; display: block" Name="SellQuantity"/>
                                    <RadzenRequiredValidator Text="Sell Quantity is required" Component="SellQuantity" Popup="true" Style="position: absolute"/>
                                </EditTemplate>
                                <FooterTemplate>
                                    <b>@string.Format(new CultureInfo("tr-TR"), "{0:G}", SelectedOrders?.FirstOrDefault()?.OrderDetails.Sum(o => o.SellQuantity))</b>
                                </FooterTemplate>
                            </RadzenDataGridColumn>
                            <RadzenDataGridColumn TItem="OrderDetail" Property="TotalBuyPrice" Title="Total Buy">
                                <EditTemplate Context="orderDetail">
                                    <RadzenNumeric TValue="double" Min="1" @bind-Value="orderDetail.TotalBuyPrice" Style="width: 100%; display: block" Name="TotalBuyPrice"/>
                                    <RadzenRequiredValidator Text="Total Buy Price is required" Component="TotalBuyPrice" Popup="true" Style="position: absolute"/>
                                </EditTemplate>
                                <FooterTemplate>
                                    <b>@string.Format(new CultureInfo("en-US"), "{0:C}", SelectedOrders?.FirstOrDefault()?.OrderDetails.Sum(o => o.TotalBuyPrice))</b>
                                </FooterTemplate>
                            </RadzenDataGridColumn>
                            <RadzenDataGridColumn TItem="OrderDetail" Property="TotalSellPrice" Title="Total Sell">
                                <EditTemplate Context="orderDetail">
                                    <RadzenNumeric TValue="double" Min="1" @bind-Value="orderDetail.TotalSellPrice" Style="width: 100%; display: block" Name="TotalSellPrice"/>
                                    <RadzenRequiredValidator Text="Total Sell Price is required" Component="TotalSellPrice" Popup="true" Style="position: absolute"/>
                                </EditTemplate>
                                <FooterTemplate>
                                    <b>@string.Format(new CultureInfo("en-US"), "{0:C}", SelectedOrders?.FirstOrDefault()?.OrderDetails.Sum(o => o.TotalSellPrice))</b>
                                </FooterTemplate>
                            </RadzenDataGridColumn>
                            <RadzenDataGridColumn TItem="OrderDetail" Property="ShippingNumber" Title="Shipment">
                                <EditTemplate Context="orderDetail">
                                    <RadzenTextBox @bind-Value="orderDetail.ShippingNumber" Style="width: 100%; display: block" Name="ShippingNumber"/>
                                    <RadzenRequiredValidator Text="Shipping Number is required" Component="ShippingNumber" Popup="true" Style="position: absolute"/>
                                </EditTemplate>
                            </RadzenDataGridColumn>
                            <RadzenDataGridColumn TItem="OrderDetail" Property="TrackingNumber" Title="Tracking Number">
                                <EditTemplate Context="orderDetail">
                                    <RadzenTextBox @bind-Value="orderDetail.TrackingNumber" Style="width: 100%; display: block" Name="TrackingNumber"/>
                                    <RadzenRequiredValidator Text="Tracking Number is required" Component="TrackingNumber" Popup="true" Style="position: absolute"/>
                                </EditTemplate>
                            </RadzenDataGridColumn>
                            <RadzenDataGridColumn TItem="OrderDetail" Property="Description" Title="Description">
                                <EditTemplate Context="orderDetail">
                                    <RadzenTextBox @bind-Value="orderDetail.Description" Style="width: 100%; display: block" Name="Description"/>
                                    <RadzenRequiredValidator Text="Description is required" Component="Description" Popup="true" Style="position: absolute"/>
                                </EditTemplate>
                            </RadzenDataGridColumn>
                            <RadzenDataGridColumn TItem="OrderDetail" Property="Status" Title="Status">
                                <EditTemplate Context="orderDetail">
                                    @*<RadzenTextBox @bind-Value="orderDetail.Status" Style="width: 100%; display: block" Name="Status"/>*@
                                    <RadzenDropDown AllowClear="true" TValue="string" Class="w-100" Data=@detailStatusList @bind-Value="orderDetail.Status" Name="Status"/>
                                    <RadzenRequiredValidator Text="Status is required" Component="Status" Popup="true" Style="position: absolute"/>
                                </EditTemplate>
                            </RadzenDataGridColumn>
                            <RadzenDataGridColumn TItem="OrderDetail" Property="OrderId" Title="Order Id" />
                            <RadzenDataGridColumn TItem="OrderDetail" Context="orderDetail" Filterable="false" Sortable="false" TextAlign="TextAlign.Center" Width="120px">
                                <Template Context="detail">
                                    <RadzenButton Icon="edit" ButtonStyle="ButtonStyle.Primary" Class="m-1" Click="@(args => EditRowDetail(detail))" @onclick:stopPropagation="true">
                                    </RadzenButton>
                                </Template>
                                <EditTemplate Context="detail">
                                    <RadzenButton Icon="check" ButtonStyle="ButtonStyle.Primary" Class="m-1" Click="@(args => SaveRowDetail(detail))">
                                    </RadzenButton>
                                    <RadzenButton Icon="close" ButtonStyle="ButtonStyle.Light" Class="m-1" Click="@(args => CancelEditDetail(detail))">
                                    </RadzenButton>
                                </EditTemplate>
                            </RadzenDataGridColumn>
                        </Columns>
                    </RadzenDataGrid>
                </RadzenTabsItem>

            </Tabs>
        </RadzenTabs>
    </Template>
    <Columns>
        <RadzenDataGridColumn TItem="Order" Property="Id" Title="Order ID" Width="120px"/>
        <RadzenDataGridColumn TItem="Order" Property="CustomerName" Title="Customer" Width="200px">
            <EditTemplate Context="order">
                <RadzenTextBox @bind-Value="order.CustomerName" Style="width: 100%; display: block" Name="CustomerName"/>
                <RadzenRequiredValidator Text="Customer Name is required" Component="CustomerName" Popup="true" Style="position: absolute"/>
            </EditTemplate>
        </RadzenDataGridColumn>
        <RadzenDataGridColumn TItem="Order" Property="VendorName" Title="Vendor" Width="200px">
            <EditTemplate Context="order">
                <RadzenTextBox @bind-Value="order.VendorName" Style="width: 100%; display: block" Name="VendorName"/>
                <RadzenRequiredValidator Text="Vendor Name is required" Component="VendorName" Popup="true" Style="position: absolute"/>
            </EditTemplate>
        </RadzenDataGridColumn>
        <RadzenDataGridColumn TItem="Order" Property="OrderDateTime" Title="Order Date" Width="200px">
            <Template Context="order">
                @($"{order.OrderDateTime:dd/MM/yyyy}")
            </Template>
            <EditTemplate Context="order">
                <RadzenDatePicker @bind-Value="order.OrderDateTime" DateFormat="dd/MM/yyyy HH:mm" Class="w-100"/>
            </EditTemplate>
        </RadzenDataGridColumn>
        <RadzenDataGridColumn TItem="Order" Property="Status" Title="Status" Width="100px">
            <EditTemplate Context="order">
                @*<RadzenTextBox @bind-Value="order.Status" Style="width: 100%; display: block" Name="Status"/>*@
                <RadzenDropDown AllowClear="true" TValue="string" Class="w-150" Data=@orderStatusList Name="Status" @bind-Value="order.Status"/>
                <RadzenRequiredValidator Text="Status is required" Component="Status" Popup="true" Style="position: absolute"/>
            </EditTemplate>
        </RadzenDataGridColumn>
        <RadzenDataGridColumn TItem="Order" Property="DoneBy" Title="Employee">
            <EditTemplate Context="order">
                <RadzenTextBox @bind-Value="order.DoneBy" Style="width: 100%; display: block" Name="DoneBy"/>
                <RadzenRequiredValidator Text="DoneBy is required" Component="DoneBy" Popup="true" Style="position: absolute"/>
            </EditTemplate>
        </RadzenDataGridColumn>
        <RadzenDataGridColumn TItem="Order" Context="order" Filterable="false" Sortable="false" TextAlign="TextAlign.Center" Width="120px">
            <Template Context="order">
                <RadzenButton Icon="edit" ButtonStyle="ButtonStyle.Primary" Class="m-1" Click="@(args => EditRow(order))" @onclick:stopPropagation="true">
                </RadzenButton>
            </Template>
            <EditTemplate Context="order">
                <RadzenButton Icon="check" ButtonStyle="ButtonStyle.Primary" Class="m-1" Click="@(args => SaveRow(order))">
                </RadzenButton>
                <RadzenButton Icon="close" ButtonStyle="ButtonStyle.Light" Class="m-1" Click="@(args => CancelEdit(order))">
                </RadzenButton>
            </EditTemplate>
        </RadzenDataGridColumn>

    </Columns>
</RadzenDataGrid>

@code {
    // Options to display in the roles dropdown when editing a user
    readonly List<string> detailStatusList = new() { "Getting ready", "Being supplied", "Shipped", "At customs", "In warehouse", "Sent to customer" };
    readonly List<string> orderStatusList = new() { "Completed", "Cancelled", "Continues"};

    IList<Order?> SelectedOrders { get; set; }
    //IList<OrderDetail> _selectedDetails;
    //Order order { get; set; }

    IEnumerable<Order?> _orders = new List<Order?>();

    RadzenDataGrid<Order?> _grid;
    RadzenDataGrid<OrderDetail> _gridDetail;

    Order? _orderToInsert;
    OrderDetail? _detailToInsert;

    protected override async Task OnInitializedAsync()
    {
        _orders = await ViewAllOrdersUseCase.ExecuteAsync();
        SelectedOrders = new List<Order?> { _orders.FirstOrDefault() };

    }

    private async Task RowClick(DataGridRowMouseEventArgs<Order> mouseClick) {
        //order.Id = mouseClick.Data.Id;
        await _grid!.ExpandRow(mouseClick.Data);
    }
    //void RowRender(RowRenderEventArgs<Order> args)
    //{
    //    if (args.Data.OrderDetails != null)
    //        args.Expandable = args.Data.OrderDetails.Count > 0;
    //    else
    //    {
    //        args.Data.OrderDetails = new List<OrderDetail>();
    //    }
    //}


    //protected override void OnAfterRender(bool firstRender)
    //{
    //    if (firstRender)
    //    {
    //        _grid.ExpandRow(_orders.FirstOrDefault());
    //        StateHasChanged();
    //    }

    //    base.OnAfterRender(firstRender);
    //}


    private async Task InsertRow()
    {
        _orderToInsert = new Order
        {
            OrderDateTime = DateTime.Now,
            OrderDetails = new List<OrderDetail>()
        };
        await _grid.InsertRow(_orderToInsert);
    }

    private async Task InsertDetailRow(int id)
    {
        _detailToInsert = new OrderDetail
        {
            OrderId = id
        };
        await _gridDetail.InsertRow(_detailToInsert);
    }

    private async Task OnCreateRow(Order? order)
    {
        if (order != null)
        {
            await AddOrderUseCase.ExecuteAsync(order);
        }
    }

    private async Task OnCreateRowDetail(OrderDetail? orderDetail)
    {
        if (orderDetail != null)
        {
            await AddOrderDetailUseCase.ExecuteAsync(orderDetail);
        }
    }

    private async Task OnUpdateRow(Order order)
    {
        if (order == _orderToInsert)
        {
            _orderToInsert = null;
        }

        if (order != null)
        {
            await EditOrderUseCase.ExecuteAsync(order);
        }
    }

    private async Task OnUpdateRowDetail(OrderDetail orderDetail)
    {
        if (orderDetail == _detailToInsert)
        {
            _detailToInsert = null;
        }
        if (orderDetail != null)
        {
            await EditOrderDetailUseCase.ExecuteAsync(orderDetail);
        }
    }

    private void CancelEdit(Order? order)
    {
        if (order == _orderToInsert)
        {
            _orderToInsert = null;
        }

        _grid.CancelEditRow(order);
    }

    private void CancelEditDetail(OrderDetail orderDetail)
    {
        if (orderDetail == _detailToInsert)
        {
            _detailToInsert = null;
        }

        _gridDetail.CancelEditRow(orderDetail);
    }


    async Task EditRow(Order? order)
    {
        await _grid.EditRow(order);
    }

    async Task EditRowDetail(OrderDetail orderDetail)
    {
        await _gridDetail.EditRow(orderDetail);
    }

    async Task EditRowDetails(IList<OrderDetail?> SelectedOrders)
    {
        foreach (var detail in SelectedOrders)
        {
            await _gridDetail.EditRow(detail);
        }
    }

    async Task SaveRow(Order? order)
    {
        if (order == _orderToInsert)
        {
            _orderToInsert = null;
        }

        await _grid.UpdateRow(order);

    }

   
    async Task SaveRowDetail(OrderDetail orderDetail)
    {
        if (orderDetail == _detailToInsert)
        {
            _detailToInsert = null;
        }

        await _gridDetail.UpdateRow(orderDetail);
    }

    async Task SaveRowDetails(IList<OrderDetail?> SelectedOrders)
    {
        foreach (var detail in SelectedOrders)
        {
            if (detail == _detailToInsert)
            {
                _detailToInsert = null;
            }

            await _gridDetail.UpdateRow(detail);
        }
    }
}

Edit:

Adding this to SaveRow did the trick, someone may need it.

_orders = await ViewAllOrdersUseCase.ExecuteAsync(user);
StateHasChanged();

Solution

  • On the first question, your button is controlled in the top level component by whether _orderToInsert is null. The click event inside the data grid is restricted to the data grid. What sets _orderToInsert to null and tells the RadzenButton to re-render? I'm unfamiliar with Radzen, so I don't know if there's and event raised that you can hook into (on a quick peek it looks like the only suitable event is LoadData).

    On the second question, you populate _orders in OnInitializedAsyc. Your save routines call back into the service to add the record, but you don't refresh _orders. Your save routines need to refresh the displayed list once they have completed.