roa765
roa765

Reputation: 295

Radzen Blazor Group Footer Template with Dynamic Data

I am using radzen library within a Blazer app. I have dynamic data and example of code below. My data is stored in IDictionary<string, object>. I am trying to add group footer template to the below code to create an aggregation row for each group on any columns that can be aggregated:

Using this demo: https://blazor.radzen.com/datagrid-group-footer-template

The code states to add:

<GroupFooterTemplate>
                Group amount: <b>@String.Format(context.Data.Items.Cast<IDictionary<string, object>().Sum())</b>
            </GroupFooterTemplate>

However I don’t know how to define the column in the sum()

Example code below to run the whole bit to see the issue. I am unable to aggregate the footer for each column when it’s dynamic code

    @using System.Linq.Dynamic.Core

<RadzenDataGrid @bind-Value=@selectedItems Data="@data" TItem="IDictionary<string, object>" 
AllowGrouping=“true”
ColumnWidth="200px"
                        AllowFiltering="true" FilterPopupRenderMode="PopupRenderMode.OnDemand" FilterMode="FilterMode.Advanced" 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>
                </RadzenDataGridColumn>
            }
    </Columns>
</RadzenDataGrid>

@code {
    IList<IDictionary<string, object>> selectedItems;

    public IEnumerable<IDictionary<string, object>> data { get; set; }

    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) },
        };

        foreach (var i in Enumerable.Range(0, 50))
        {
            columns.Add($"Column{i}", typeof(string));
        }

        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;
        });
    }
}

I tried the following to use a dictionary indexer with column name as a string but can’t seem to get It to work

 <GroupFooterTemplate>
                    Group amount: <b>@String.Format(context.Data.Items.Cast(IDictionary<string, object>)().Sum(x => x[x.Key]))</b>
                </GroupFooterTemplate>

But this doesn’t work.

Upvotes: 0

Views: 1397

Answers (1)

Zuhlek
Zuhlek

Reputation: 3

I also had issue with the Cast<>() part and eventually extracted the sum logic to a separate method. (Note that for me the decimal datatype is the return type.)

decimal SumUp(IEnumerable items)
{
    if (items is null)                      //nullcheck
    {
        throw new ArgumentNullException(nameof(items));
    }

    decimal total = 0;

    foreach (var obj in items)              //loop through group items
    {
        if (obj is YourObjectType item)     //typecheck
        {
            total += item?.DecimalPropertyToBeSummedUp ?? 0;
        }
    }

    return total;
}

Having that method in place, I thought it might be easier to find the issue and eventually called it from my GroupFooterTemplate element like this:

<GroupFooterTemplate>
    Group total: @SumUp(context.Data.Items)
</GroupFooterTemplate>

And like this, it works perfectly fine for me:

screenshot of UI result

Upvotes: 0

Related Questions