13

I'm currently implementing table paging via a home grown solution in Blazor and coming across some difficulty. The troublesome piece of code is below (this is for rendering the paging buttons below a grid):

@for (int i = 0; i < vm.TotalPages; i++)
{
    <button id="pg-button-@i" class="btn btn-primary btn-sm" type="button"
        onclick="@(() => GetTablePage(i))">@i</button>
}

Notice in the onclick event, I am calling a function and passing in i, the counter for the current interation of the loop.

The GetTablePage method looks as follows:

protected async Task GetTablePage(int page)
{
    Console.WriteLine("page number: " + page);
}

My issue is that EVERY button will call this function with i set as the length of vm.TotalPages.

Here is an example to try to make this more clear:

View Markup (notice the id of each button is set appropriately):

<button id="pg-button-0" class="btn btn-primary btn-sm" type="button">0</button>
<button id="pg-button-1" class="btn btn-primary btn-sm" type="button">1</button>
<button id="pg-button-2" class="btn btn-primary btn-sm" type="button">2</button>
<button id="pg-button-3" class="btn btn-primary btn-sm" type="button">3</button>
<button id="pg-button-4" class="btn btn-primary btn-sm" type="button">4</button>
<button id="pg-button-5" class="btn btn-primary btn-sm" type="button">5</button>
<button id="pg-button-6" class="btn btn-primary btn-sm" type="button">6</button>

Upon clicking ANY of these buttons, my GetTablePage function is writing 7 to the console which is the length of the vm.TotalPages collection.

Why is this happening and how can I overcome it?

Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188
GregH
  • 5,125
  • 8
  • 55
  • 109

2 Answers2

22

Because i is a variable and the for loop is always finished when you click, it is 7 on that moment

You need to do something like:

@for (int i = 0; i < vm.TotalPages; i++)
{
    var tempint = i;
    <button id="pg-button-@i" class="btn btn-primary btn-sm" type="button"
        onclick="@(() => GetTablePage(tempint))">@i</button>
}
Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188
Flores
  • 8,226
  • 5
  • 49
  • 81
6

This is a standard C# behavior where the lambda expression @(() => GetTablePage(i)) has access to a variable and not to the value of the variable, the result of which is that the lambda expression always calls GetTablePage(i) and i equals 7 at the end of the loop. To solve this you can define a variable scoped locally to the loop like the following:

@for (int i = 0; i < vm.TotalPages; i++)
{
    var temp = i;
    <button id="pg-button-@temp " class="btn btn-primary btn-sm" type="button"
        onclick="@(() => GetTablePage(temp ))">@temp </button>
}

Hope this helps...

Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188
enet
  • 41,195
  • 5
  • 76
  • 113