Home > OS >  How Do I Dynamically Add onclick on a Razor page?
How Do I Dynamically Add onclick on a Razor page?

Time:11-16

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.

  • Related