Async ContextMenuService

I'm currently using the ContextMenuService component. All of my service calls and database calls are async and I would like to keep it that way.

Is there a way to make the contextmenu methods async? All the examples I've seen don't seem to be async and when I try to make them async the ContextMenuService.Open(args, contextMenuItems, OnMenuItemClick) call complains.

Any idea or help would be really helpful.

Hi @GingJonesy,

You can try with Task.Run:

Task.Run(async () => 
{
   await Somethign();
});

Thanks, I wasnt sure if there was an async method with the component so just wanted to ask. It now works with Task.Run, however when I update the row that I had right clicked it doesn't cause a re-render even though I've changed the value.

I tried StateHasChanged() and creating an eventcalllback to force the re-render but it never does once the OnMenuItemClick(MenuItemEventArgs args) method has completed and ContextMenuService.Close() is called.

Is there another way to do this after the ContextMenu has completed its operation?

Thanks for the help

You can try InvokeAsync in this case.

InvokeAsync(async () =>
{
});

Yea I've tried so much and it just doesnt seem to refresh with the updated values. After the context item is clicked I update some data which changes the status of that row. I finish it with the UpdateDispatchBoard statement which should cause the page to rerender and show the new updated status for that row on screen but it never updates. Here is the code behind that I'm trying, is there anything that stands out in the context menu code that looks to be wrong? Thanks for your help.

@code {

    [Parameter]
    public string? SelectedCrewMemberId { get; set; }

    [Parameter]
    public string? SelectedCallId { get; set; }

    [Parameter]
    public DateTime FromDate { get; set; }

    [Parameter]
    public DateTime ToDate { get; set; }

    List<AssignedCallDto> assignedCalls = new List<AssignedCallDto>();
    List<string> selectedAssignedCallIds = new List<string>();    
    bool loading = false;        

    protected override async Task OnParametersSetAsync()
    {
        base.OnParametersSetAsync();

        if (loading)
        {
            return;
        }

        if (SelectedCrewMemberId is not null)
        {
            try
            {
                loading = true;                
                assignedWork = await actionCallService.GetAssignedCallsByEmployeeId(SelectedCrewMemberId, FromDate, ToDate);
            }
            finally
            {
                loading = false;
            }
        }        
    }    

    public async Task UpdateDispatchBoard()
    {
        assignedWork = await actionCallService.GetAssignedWorkByEmployeeId(SelectedCrewMemberId, FromDate, ToDate);        
    }    

    void ShowContextMenuWithItems(MouseEventArgs args, string visitId, string status, string nextStatus, string visitType)
    {
        var contextMenuItems = new List<ContextMenuItem>();        

        if (status != ACTION_STATUS.ActionCompleted)
        {                               
            var value = (visitId, status, visitType, nextStatus);
            contextMenuItems.Add(new ContextMenuItem() { Text = nextStatus, Value = value });                        

            ContextMenuService.Open(args, contextMenuItems, OnMenuItemClick);
        }        
    }

    void OnMenuItemClick(MenuItemEventArgs args)
    {
        var param = (string VisitId, string Status, string VisitType, string NextStatus) args.Value;

        Task.Run(async () => 
        {        
            switch (args.Text)
            {
                case "In Progress":                    
                    await actionCallService.InProgressCall(SelectedCrewMemberId, param.VisitId, param.VisitType, param.Status, FromDate, ToDate);
                    break;

                case "Acknowledged":                    
                    await actionCallService.AcknowledgeCall(SelectedCrewMemberId, param.VisitId, param.Status, FromDate, ToDate);
                    break;

                case "Completed":
                    await actionCallService.UpdateActionCallStatus(SelectedCrewMemberId, param.VisitId, param.Status, param.NextStatus, FromDate, ToDate);
                    break;

                case "Rejected":        
                    await actionCallService.UpdateActionCallStatus(SelectedCrewMemberId, param.VisitId, param.Status, param.NextStatus, FromDate, ToDate);
                    break;

                default:
                    break;
            }                
            await UpdateDispatchBoard();
        });

        ContextMenuService.Close();        

        InvokeAsync(StateHasChanged);         
    }
}

Yep. You are not using InvokeAsync as suggested. Replace Task.Run with InvokeAsync.

Apologies, when you said Task.Run earlier I thought that meant i needed to run that within InvokeAsync which didnt work. Replacing Task.Run with InvokeAsync and moving ContextMenuService.Close() and StateHasChanged to within the InvokeAsync fixed my issue. Thanks for your help and guidance!