Sarahrb
Sarahrb

Reputation: 669

Call Blazor method from JS without button click

How do I initiate call to DotNet method from JS.

My code:

Index.razor:
protected override async Task OnAfterRenderAsync(bool firstRender)
{
        await JSRuntime.InvokeVoidAsync("Create", fileName);
}


JS:
function Create(fileName) {
  $.getJSON(fileName, function (data) {
     data.forEach((eachline, i) => {
     if (data[i].name === "something") {
     window.sendName= () => {
            var val = "Abc";
            return val;
     }
     }
     }
  }
}
  

NavBar.Razor:
<a href="" @onclick=getName>GetName</a>

 public string? Name { get; set; }   
 [JSInvokable]
        private async Task getName()
        {
            Name= await JSRuntime.InvokeAsync<string>("sendName");
      
        }

I tried using example in below link. But doesn't seem to work as I expect. https://learn.microsoft.com/en-us/aspnet/core/blazor/javascript-interoperability/call-dotnet-from-javascript?view=aspnetcore-6.0#class-instance-examples

Upvotes: 1

Views: 747

Answers (1)

Dimitris Maragkos
Dimitris Maragkos

Reputation: 11392

First, you need to create a helper class. The class should have a JSInvokable method that raises an event when called.

SendNameHelper.cs:

public class SendNameHelper
{
    public event Action<string>? OnNameSent;

    [JSInvokable]
    public Task SendNameAsync(string name) 
    {
        OnNameSent?.Invoke(name);

        return Task.CompletedTask;
    }
}

Register this class as a service in Program.cs. Blazor components are now able to inject the service and subscribe to the event.

Program.cs:

// for blazor wasm
builder.Services.AddSingleton<SendNameHelper>();

// if blazor server add as scoped
builder.Services.AddScoped<SendNameHelper>();

Index.razor should use IJSRuntime to call the create JS function and pass to the function a reference to the SendNameHelper service.

Index.razor:

@inject IJSRuntime JS
@inject SendNameHelper SendNameHelper

...

@code {
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            var sendNameHelperReference = DotNetObjectReference.Create(SendNameHelper);

            await JS.InvokeVoidAsync("create", fileName, sendNameHelperReference);
        }
    }
}

NavBar.razor should simply inject the SendNameHelper service and subscribe to the OnNameSent event.

NavBar.razor:

@inject SendNameHelper SendNameHelper
@implements IDisposable

...

@code {
    protected override void OnInitialized()
    {
        SendNameHelper.OnNameSent += HandleNameSent;
    }

    private void HandleNameSent(string name)
    {
        // do stuff with name
        Console.WriteLine(name);
    }

    public void Dispose()
    {
        SendNameHelper.OnNameSent -= HandleNameSent;
    }
}

And finally create function should use the SendNameHelper reference to invoke the SendName method:

JS:

window.create = (fileName, dotNetHelper) => {    
    $.getJSON(fileName, function (data) {
        data.forEach((eachline, i) => {
            if (data[i].name === 'something') {
                dotNetHelper.invokeMethodAsync('SendNameAsync', 'something');             
            }
        });

        dotNetHelper.dispose();
    });
};

Upvotes: 3

Related Questions