110

I'd want to make button onclick function that takes some input.

<button onclick="@test(123, 456)">Check</button>

@functions
{
    public void test(int a, int b)
    {
        Console.WriteLine(a + b);
    }
}

But for some reason it throws an error:

Argument "1": Cannot convert from void to string

Later I'd want to create those buttons in for loop like

@for (int i = 0; i < 10; i++)
{
    <button onclick="@test(i, 5 * i)">Check</button>
}

How can I achieve that?

Axelly
  • 589
  • 3
  • 7
  • 26
  • 1
    it looks like you need to have a return type on you function, try changing void to string – DalTron Jan 21 '19 at 21:08
  • @DalTron I changed void to string and added "return a" - now onClick buttons show on console ``ReferenceError: a is not define`` and after refreshing page it shows ``579`` which is 123+456 But Why? – Axelly Jan 21 '19 at 21:15
  • Does it work with a lambda? @for (int i = 0; i < 10; i++) { } – bcwhims Jan 21 '19 at 21:24
  • @bcwhims Perfectly! Please write it as an answer! – Axelly Jan 21 '19 at 21:26
  • 3
    Related: [`@onclick=“(() => SomeMethod(parameter))”`](https://stackoverflow.com/questions/58609923/onclick-somemethodparameter) – dani herrera Sep 13 '20 at 10:30

6 Answers6

179

Try it with a lambda. You're binding the onclick to the result of the function rather than the function itself.

@for (int i = 0; i < 10; i++)
{
    var buttonNumber = i;
    <button @onclick="@(e => test(buttonNumber, 5 * buttonNumber))">Check</button>
}
Jason Honingford
  • 540
  • 5
  • 17
bcwhims
  • 2,655
  • 2
  • 15
  • 15
  • 8
    Thanks and I also found the Blazor docs helpful on this. https://learn.microsoft.com/en-us/aspnet/core/blazor/event-handling?view=aspnetcore-3.1 – Jason Honingford Mar 13 '20 at 21:31
  • 1
    I've tried this but keep getting the error `Cannot convert lambda expression to type 'object' because it is not a delegate type` – ataraxia Aug 24 '20 at 21:02
  • When that happens you need to explicitly create the `EventCallback` using the `EventCallback.Factory`. Documentation here: https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.components.eventcallbackfactory?view=aspnetcore-3.1 – Nechemia Hoffmann Sep 01 '20 at 02:56
63

I try this and worked

@onclick="(() => FunctionName(argument))"

like

@onclick="(() => GetDetail(item.UserId))"

Got idea from https://github.com/aspnet/AspNetCore/issues/15956 .

Nick Kovalsky
  • 5,378
  • 2
  • 23
  • 50
sami ullah
  • 925
  • 1
  • 9
  • 15
14

At Sign on onclick specifies it's a C# function:

@onclick = "@(() => test(i, 5*i))"
JayCOS
  • 57
  • 3
  • 9
MrCalico
  • 301
  • 3
  • 8
2
<input type="button" @onclick="@(() => functionname(paramvalue))" class="....." value="DoSomething" />
Coursal
  • 1,387
  • 4
  • 17
  • 32
Abbas Hadavandi
  • 111
  • 1
  • 2
2

The following both input as well as button typed worked for me.

<td>
    <input type="button" class="btn btn-primary" value="Delete"
    @onclick="(() => this.DeleteTodoItem(todoItem.Id))"  />
</td>
<td>
    <button class="btn btn-primary" 
    @onclick="(() => this.DeleteTodoItem(todoItem.Id))">Delete</button>
</td>
VivekDev
  • 20,868
  • 27
  • 132
  • 202
1

Here is full syntax which contains:

  1. Asynchronous method.
  2. MouseEventArgs passed.
  3. Custom parameter.
<button @onclick="@(async (args) => await ButtonEvent(args, 5))">My Button</button>

@code {
   async Task ButtonEvent(MouseEventArgs args, int CustomParameter)
   {
            
   }
}
Alt-WN
  • 81
  • 6
  • 1
    Correct but inefficient. You can remove the async and await from the lambda. That makes it a tiny bit smaller and faster. – H H Mar 08 '23 at 17:48
  • But when your ButtonEvent needs asynchronous handling (e.g. it calls async methods), then it is the simplest solution (without creating Task objects). – Alt-WN Mar 08 '23 at 18:41
  • Without those 2 keywords it does exactly the same (async) thing. Search for "eliding async await". – H H Mar 08 '23 at 19:57