3

Inside a Blazor component, I want to call a JS method from the HTML onclick event of an anchor tag, thus:

<a onclick="window.LoadImage();" class="@CssClass">@DisplayName</a> 

My JS method is:

window.LoadImage = () => {
    DotNet.invokeMethodAsync('MyProject', 'FireEvent').then();
}

Inside the JS method, I want to fire a C# static method to trigger an event, thus:

[JSInvokable]
public static void FireEvent()
{
   StateEngine.LoadImage(DisplayName, Target);
}
[Parameter]
public string DisplayName { get; set; }
[Parameter]
public string Target { get; set; }

I can't get the JS method to find the C# method. I've tried multiple name configurations for the first parameter, like

MyProject (the assembly name)
MyProject.FolderName.ComponentName
FolderName.ComponentName
ComponentName

to name a few. I've also tried shuffling names through the second parameter.

How is this supposed to work? What am I missing?

P.S. Please disregard the bit about the instance properties in the static method. I've got a workaround for that, but don't want to clutter up the post.

MadBanana
  • 35
  • 1
  • 6

2 Answers2

1

From the looks of it, you would be better off using the reference JSInterop so you can access the components properties.

Razor

@inject IJSRuntime JS
@implements IDisposable

 <a @onclick=Clicked>Click here</a>

@code
{
  private DotNetObjecctReference ObjRef;

  [JSInvokable]
  public void FireEvent()
  {
     StateEngine.LoadImage(DisplayName, Target);
  }

  private Task Clicked()
  {
    return JS.InvokeVoidAsync("window.LoadImage", ObjRef);
  }

  protected override Task OnInitializedAsync()
  {
    ObjRef = DotNetObjectReference.Create(this);
  }

  void IDisposable.Dispose()
  {
    ObjRef.Dispose();
  }
}

JS

window.LoadImage = (dotNetObject) => {
    dotNetObject.invokeMethod('FireEvent');
}
Peter Morris
  • 20,174
  • 9
  • 81
  • 146
Stellarade
  • 187
  • 3
  • If you create a DotNetObjectReference without disposing it, you app will leak memory - https://blazor-university.com/javascript-interop/calling-dotnet-from-javascript/lifetimes-and-memory-leaks/ – Peter Morris Jun 03 '20 at 07:42
  • @PeterMorris Thanks, edited. For anyone reading this, there are multiple ways you could handle the DotNetObjectReference creation. Creating a new object every js call(and disposing inside the JS) is one method. The link in Peter's above post shows another way using a component property and implementing IDisposable. – Stellarade Jun 03 '20 at 14:15
  • I revised it slightly. I think it's impolite to dispose of objects you didn't create. I hope you don't mind and will accept my modifications - but I don't mind if you revert them :) – Peter Morris Jun 03 '20 at 16:10
  • This gave me enough to go on; but then I had the rug pulled out from under me, and this project is on "eternal hold". – MadBanana Jun 18 '20 at 19:40
0

Your code looks good. May be its unable to find your .Net method. Give it a retry..

JS

window.LoadImage = function () {
DotNet.invokeMethodAsync("MyBlazorProject.UI", "FireEvent").then();}

First Parameter must be AssemblyName of your Blazor component. In my case, it is "MyBlazorProject.UI".
Second Parameter must be method name.

HTML

<a onclick="window.LoadImage()" class="btn btn-primary">Call .Net Method FireEvent</a>

here onclick is JavaScript event, which is good in your case too.

C# Code

[JSInvokable]
public static void FireEvent()
{
    //debugger hits here
    //StateEngine.LoadImage(DisplayName, Target);
}

This is all working for me fine. Debugger gets hit inside FireEvent .Net method after clicking anchor tag.

output

Thanks

Rahul
  • 1,063
  • 2
  • 11
  • 22