Search code examples
c#blazorblazor-client-side

Blazor pass and run Task from child component - cannot convert from 'method group' to 'Task<int>'


in my parent component i have Task which i want pass to child component.

Parent component:

    <ChildComponent ChangePageMethod="@ChangePage" />
    @code {
           public async Task ChangePage(int page)
           {
              Console.WriteLine(page);
           }
     }

Child Component:

<a @onclick="prevPage">Prev</a>
<a @onclick="nextPage">Next</a>
@code {
    [Parameter]
    public int Page { get; set; } = 3;

    [Parameter]
    public Task ChangePageMethod { get; set; }

    private void prevPage()
    {
        
    }
    private void _nextPage()
    {
        
    }
}

For now im getting this error: cannot convert from 'method group' to 'Task'

Any tips how to fix it? And how to run task passed from parent with parameter?


Solution

  • The classic pattern for this situation is the following code in ChildComponent

    <a @onclick="(e) => prevPage()">Prev</a>
    <a @onclick="(e) => nextPage()">Next</a>
    

    Use a Lambda expression to sink the mouse event as e and then call your methods.

    [Parameter]
        public EventCallback<int> ChangePageMethod { get; set; }
    
    private void nextPage()
    {
       // increment the page and call the Event CallBack
       Page++;
       ChangePageMethod.InvokeAsync(Page);
    }
    

    nextPage increments the page counter and then invokes the callback event. You don't need to use tasks here. The mouse click event that triggered this is fire-and-forget.

    In ParentComponent the callback ChangePageMethod now passes the page number so ChangePage will handle it correctly.

    public void ChangePage(int page)
    {
        Console.WriteLine(page);
    }
    

    ChangePage is the event handler so under normal circumstances you return a void. If it contains any async code you would label it async. See below where we use the async Task.Delay() to simulate a yielding Task.

    public async void ChangePage(int page)
    {
        await Task.Delay(10);
        Console.WriteLine(page);
    }
    

    ChangePage only needs to be declared to return a Task if you have code below InvokeAsync in nextPage or prevPage that needs to await whatever you do in ChangePage before executing.

    Two example patterns for ChangePage below:

    public async Task ChangePage(int page)
    {
        Console.WriteLine(page);
        return Task.Delay(10);
    }
    
    public Task ChangePage(int page)
    {
        Console.WriteLine(page);
        return Task.Completed;
    }
    

    Example pattern for prevPage

    private async void prevPage()
    {
       // decrement the page and call the Event CallBack
       Page--;
       await ChangePageMethod.InvokeAsync(Page);
       // Dependant code here
    }
    

    PS - I think I've got all this code right, but I haven't tested the code so there may be a typo or two. Check MS Docs here on data binding.