Grid Columns order not working with foreach statement

3 Answers 88 Views
Grid
Leonardo
Top achievements
Rank 1
Iron
Leonardo asked on 14 May 2021, 04:48 AM

Hi,

 

I have created a grid where I have some fixed columns at the being, then I have a list interaction to create some columns, and then I have more two columns which I would like to keep at the end of the grid. But, it is rendering all columns insert in the "foreach" loop in the end.

 

Here is my grid:

<TelerikGrid Data=@TenantBillingList
                         Sortable="true"
                         Groupable="true"
                         FilterMode="@GridFilterMode.FilterMenu"
                         Pageable="true" PageSize="50"
                         ShowColumnMenu="true">
                <GridColumns>
                    <GridColumn Field="@nameof(TenantBillingDto.TenantName)" FieldType="@(typeof(string))" Title="@L["TenantBilling.TenantName"]">
                        <Template>
                            <b>@((context as ExpandoObject).GetOrDefault(nameof(TenantBillingDto.TenantName)))</b>
                        </Template>
                    </GridColumn>
                    <GridColumn Field="@nameof(TenantBillingDto.EditionName)" FieldType="@(typeof(string))" Title="@L["TenantBilling.EditionName"]" />
                    <GridColumn Field="@nameof(TenantBillingDto.CountryCode)" FieldType="@(typeof(string))" Title="@L["TenantBilling.CountryCode"]" />
                    <GridColumn Field="@nameof(TenantBillingDto.Currency)" FieldType="@(typeof(string))" Title="@L["TenantBilling.Currency"]" />
                    <GridColumn Field="@nameof(TenantBillingDto.EditionCost)" FieldType="@(typeof(double))" Title="@L["TenantBilling.EditionCost"]">
                        <Template>
                            @(((context as ExpandoObject).GetOrDefault(nameof(TenantBillingDto.EditionCost)) as int?).GetValueOrDefault().ToString("N2"))
                        </Template>
                    </GridColumn>

                    @foreach (var consumable in ConsumableList)
                    {
                        <GridColumn Field="@(nameof(TenantBillingConsumablesDetailsDto.ConsumableQty) + "_" + consumable.Name)" FieldType="@(typeof(int))" Title="@(consumable.Name + " #")" />
                        <GridColumn Field="@(nameof(TenantBillingConsumablesDetailsDto.ConsumableCost) + "_" + consumable.Name)" FieldType="@(typeof(double))" Title="@(consumable.Name + " $")">
                            <Template>
                                @(((context as ExpandoObject).GetOrDefault(nameof(TenantBillingConsumablesDetailsDto.ConsumableCost) + "_" + consumable.Name) as double?).GetValueOrDefault().ToString("N2"))
                            </Template>
                        </GridColumn>
                    }

                    <GridColumn Field="@nameof(TenantBillingDto.ConsumableTotalCost)" FieldType="@(typeof(double))" Title="@L["TenantBilling.ConsumableTotalCost"]">
                        <Template>
                            @(((context as ExpandoObject).GetOrDefault(nameof(TenantBillingDto.BillTotalCost)) as double?).GetValueOrDefault().ToString("N2"))
                        </Template>
                    </GridColumn>

                    <GridColumn Field="@nameof(TenantBillingDto.BillTotalCost)" FieldType="@(typeof(double))" Title="@L["TenantBilling.BillTotalCost"]">
                        <Template>
                            <b>@(((context as ExpandoObject).GetOrDefault(nameof(TenantBillingDto.BillTotalCost)) as double?).GetValueOrDefault().ToString("N2"))</b>
                        </Template>
                    </GridColumn>
                </GridColumns>
            </TelerikGrid>

 

Here is the grid result. As you can see, the columns "Total Consumables" and "Total $" should be at the end, and not before my dynamic columns.

3 Answers, 1 is accepted

Sort by
0
Accepted
Hristian Stefanov
Telerik team
answered on 18 May 2021, 04:51 PM

Hi Leonardo,

We have this knowledge base article for specifying grid columns position, with a detailed description of the scenario, and the ways to get the desired result. Thanks to your question we have extended it a little bit and anyone interested can get more information now.

In short, this is the expected behavior because of the order in which the framework initializes components. All the parent components are initialized before their child components. Because of this framework behavior, the foreach loop inserts the columns at the end of your application.

I hope this helps and if you have any other questions, please let me know.

Regards,
Hristian Stefanov
Progress Telerik

Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.

0
Leonardo
Top achievements
Rank 1
Iron
answered on 18 May 2021, 11:07 PM

Hi Hristian,

 

Thank you for your answer. I managed to resolve the issue using the GetState and SetState methods. However, I was not able to do that in the events onStateInit and onStateChanged, I had to do that in the event onAfterRender when it is called after all columns are already added.

Below my code to be able to change the order of the two columns.

bool FirstReorder = true;

        protected override void OnAfterRender(bool firstRender)
        {
            var state = MainGrid.GetState();
            if (state.ColumnStates.Count > 7 && FirstReorder)
            {
                FirstReorder = false;
                state.ColumnStates.Where(x => x.Index == 5).First().Index = 998;
                state.ColumnStates.Where(x => x.Index == 6).First().Index = 999;
                MainGrid.SetState(state);
            }
        }

 

Could you please update the article to add an example for this scenario? It took me too much time to figured out a solution and I am not sure if it will work properly.

0
Hristian Stefanov
Telerik team
answered on 21 May 2021, 03:35 PM

Hi Leonardo,

There is an open feature request for Adding a Field property to the Grid's ColumnState. I have already given your vote there on your behalf, this way, the priority of the requested feature is increased, and we are tracking this interest. You can also click the "Follow" button to get notifications via email about the request status changes.

The workaround for getting the field and position of the grid column is by using ColumnState object.

Your example with the OnAfterRender method is good for a workaround too, and will do the work for you if you want to maintain it. Yes, it is a valid approach, and by maintaining it, I mean that I find it a little bit hard in some scenarios. For example, if you are adding new columns to the Grid, their indexes will change. After that, you will always need to change the indexes in the method. On every SaveState will break and will need changing. In case that you are not using the scenarios that I described, this approach will be even better for your app.

I hope this helps and if you have any other questions, please let me know.

Regards,
Hristian Stefanov
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

Tags
Grid
Asked by
Leonardo
Top achievements
Rank 1
Iron
Answers by
Hristian Stefanov
Telerik team
Leonardo
Top achievements
Rank 1
Iron
Share this question
or