Blazor onclick event passing in counter from loop
Asked Answered
S

2

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?

Serve answered 28/12, 2018 at 21:38 Comment(0)
H
25

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>
}
Hitoshi answered 28/12, 2018 at 21:49 Comment(0)
U
7

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...

Unpolitic answered 28/12, 2018 at 22:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.