I am iterating through a LARGE list of objects all of which will open the same modal window that will be loaded with dynamic information. To make this work, I create a counter called MenuCounter that I know increments just fine.
That said, I am attempting to wrap a hyperlink around the icons I need to use and the injection of the method keeps pointing to the last value of the MenuCounter.
I first tried this:
<a href="#" onclick="@(() => SetupChangeName(MenuCounter))" class="menuButton">...</a>
When I ran into the issue, I tried reducing the code to the following but then the page somehow activates the hyperlink and the modal window appears and will not go away.
<a href="#" onclick="SetupChangeName(MenuCounter)" class="menuButton">...</a>
Can somebody please help me out?
Thank you!
CodePudding user response:
I'm not a fan of onclick
attributes, but if you're set on this method, I believe you just need to santize the C# and JS in the same line like this:
<a href="#" onclick="SetupChangeName('@MenuCounter')" class="menuButton">...</a>
Adding the quotes will ensure at least an empty string is present for JS, and then you can process it.
Alternative method
Since mixing languages like that is quite frustrating, I find it easier to use data tags, for example
<a href="#" data-menu-counter="@MenuCounter" class="menuButton">...</a>
And then in your JS file:
var links = document.querySelectorAll('[data-menu-counter]');
links.forEach(x => x.addEventListener('click', /* your function code here */);
CodePudding user response:
and the injection of the method keeps pointing to the last value of the MenuCounter.
I assume that SetupChangeName() is a C# (not JS) method. And that the @
in @onclick
was lost in posting the question.
In that case, it should look like
@for(int i = 1; i < ...; i )
{
int MenuCounter = i; // local copy
<a href="#" @onclick="@(() => SetupChangeName(MenuCounter))" class="menuButton">...</a>
}
Search for "lambda captures loop var".
CodePudding user response:
You should apply a lambda expression to the Blazor @onclick
directive instead of using the onclick
Html attribute, in which case it should call a JS function, which you did not mean.
Note that I've introduced a new directive to prevent the default action of the anchor element: @onclick:preventDefault
Test this code:
@page "/"
<a href="#" @onclick:preventDefault @onclick="@(() => SetupChangeName(MenuCounter))" >Click me...</a>
<div>Counter is @output</div>
@code
{
private int MenuCounter = 10;
private int output;
private void SetupChangeName (int counter)
{
output = counter;
}
}
Note: If you use a for loop to render a list of anchor elements, you must define a variable local to the loop, and provide it as the input to your lambda expression, something like this:
@for(int MenuCounter = 0; MenuCounter < 10; MenuCounter )
{
int local= MenuCounter;
<a href="#" @onclick:preventDefault @onclick="@(() =>
SetupChangeName(local))" >Click me...</a>
}
otherwise, all the lambda expressions will have the the same value for MenuCounter
, which is the value incremented for the last iteration. See For loop not returning expected value - C# - Blazor explaining the issue.