skip to Main Content

A .razor component file is defined with a "HTML" section, in which you can define the HTML of your component, and a @code {} section in which C# code can be written to add logic to the component.

I know that you can call JS methods from the C# code in the @code {} section, but what I cannot find anywhere is if there’s any way to call those JS functions from the "HTML" part directly like

<button onclick="a_js_function()">click me</button> 

as that would be much nicer to write and read.

Alternatively, I’d like to know if it’s at all possible to somehow refer to regular HTML with JS from a Blazor PWA. Thanks!

"why use Blazor then?" -> I don’t have a choice 🙂

Edit: making globally available JS functions is not desirable either.

Clarifications

Since I’m seeing much criticism, I’m adding an example of how it could look:

@inject IJSRuntime JS

<button @onclick=module.a_js_function>click me<button/>

@code {
    IJSObjectReference module;

    protected override async Task OnAfterRenderAsync(bool firstRender) {
        module = await JS.InvokeAsync<IJSObjectReference>(
                "import", "./Pages/Component.razor.js");

    }
}

I know that this doesn’t work, but since Blazor allows me to call globally available JS and write an isolated JS module that is scoped to my component, I was thinking there might be a way to somehow combine both and call scoped JS from the HTML section of the Blazor component.

I think this is a legitimate interrogation, and the fact that it is not possible is not a reason to have it closed.

3

Answers


  1. You can call every Javascript normally when it’s defined during startup. For Blazor Webassembly this file would be Index.html and for Blazor Server it is _Host.cshtml

    Every function which is included as file or defined here is available within your entire app.

    However I strongly recommened doing it the Blazor way. Since it will make future development much easier. It’s not a lot of work either.

    Inject IJSRuntime. Make an async function and call your Javascript function within.

    @inject IJSRuntime jsRuntime
    
    <button onclick="a_js_function()">click me</button> 
    
    @code {
      private async Task MyButtonClickAsync()
      {
          await jsRuntime.InvokeVoidAsync("a_js_function");
      }
    }
    }
    

    There are a lot of benefits in doing so.

    1. You can work with every C# code easily here
    2. Debugging the SOftware will be much easier since you can hit the breakpoints from Visual Studio and inspect all values
    3. Adding blazor features requires you to use a C# function anyways. You can call C# from Javascript which is IMO much harder than doing it the other way around
    4. You can create extension methods for IJSRuntime to call your Javascript function with nice autocompletion, Intellsense and code documentation

    Also keep in mind that every Javascript state needs to be managed by yourself

    Login or Signup to reply.
  2. Το call scoped JS from the HTML section of the Blazor component you can do the following:

    @inject IJSRuntime JS
    
    <button @onclick="@(() => module.InvokeVoidAsync("a_js_function"))">click me</button>
    
    @code {
        IJSObjectReference module;
    
        protected override async Task OnAfterRenderAsync(bool firstRender)
        {
            if (firstRender)
            {
                module = await JS.InvokeAsync<IJSObjectReference>(
                    "import", "./Pages/Component.razor.js");
            }
        }
    }
    
    Login or Signup to reply.
  3. There’s an article here by Gerald Barre on his blog showing how to do this. I don’t know if he was the original creator or got it from somewhere else.

    The code below demonstrates the techniques described in the article.

    It’s similar to the code in the other answer but only loads the module if it’s needed, and disposes it appropriately.

    A js file wwwroot/js/index.js

    export function sayHello(name) {
        alert(`Hello ${name}!`);
    }
    

    My Index:

    @inject IJSRuntime JSRuntime
    @implements IAsyncDisposable
    
    @page "/"
    
    <PageTitle>Index</PageTitle>
    
    <h1>Hello, world!</h1>
    
    Welcome to your new app.
    
    <SurveyPrompt Title="How is Blazor working for you?" />
    
    <button class="btn btn-primary" @onclick=this.SayHello>Say Hello</button>
    
    @code {
    
        private Task<IJSObjectReference>? _module;
    
        private Task<IJSObjectReference> Module 
            => _module ??= JSRuntime.InvokeAsync<IJSObjectReference>("import", "./js/index.js").AsTask();
    
        private async Task SayHello()
        {
            var module = await this.Module;
            await module.InvokeVoidAsync("sayHello", "Blazor");
        }
    
        public async ValueTask DisposeAsync()
        {
            if (_module != null)
            {
                var module = await _module;
                await module.DisposeAsync();
            }
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search