Grid.razor:
@foreach (var row in Rows)
{
<tr @onclick="@(() => OnRowClick(row))">
@GridBody(row)
</tr>
}
Grid.razor.cs
namespace MyApp.Web.Components.Grid
{
public class GridRow<TItem>
{
public TItem Item { get; set; } = default!;
public int Id { get; set; } = default!;
public bool Active = false;
}
public partial class Grid<TItem>
{
[Parameter]
public int PageSize { get; set; } = 100;
[Parameter]
public RenderFragment GridHeader { get; set; } = default!;
[Parameter]
public RenderFragment<GridRow<TItem>> GridBody { get; set; } = default!;
public async Task OnRowClick(GridRow<TItem> row)
{
//...
}
}
}
Everything works as expected. However the following line of code in Grid.razor is not clear to me:
<tr @onclick="@(() => OnRowClick(row))">
The above works, but initially I had attempted the following:
<tr @onclick="@(OnRowClick(row))">
Without the lambda expression the compiler produces the following error:
Argument 2: cannot convert from 'System.Threading.Tasks.Task' to 'Microsoft.AspNetCore.Components.EventCallback'
Why is a lamda function necessay here?
CodePudding user response:
When you use OnRowClick(row)
, you're directly invoking the OnRowClick
function and assigning the result to onclick
. Using () => OnRowClick(row)
is assigning the lambda function to onclick
, such that it can be called later (thus calling OnRowClick
).
Thinking of onclick
as a variable, here's the difference you'd see in C#:
Task<SomeType> onclick = OnRowClick(row); // Invoked now, onclick contains the result
vs.
Func<Task<SomeType>> onclick = () => OnRowClick(row); // Can be invoked later
You could shorthand things if row
wasn't required as a parameter, e.g. @onclick=@OnRowClick
, since you'd be passing a function that can be invoked later instead of invoking it now.