Home > Back-end >  Javascript click eventlistener not working in blazor
Javascript click eventlistener not working in blazor

Time:10-25

I'm relatively new to all of this so hopefully this is a reasonably simple question! I have the following code that was working perfectly previously with pure HTML/CSS. It changes the CSS Class of an element when you click another element:

<script>
    const menu = document.querySelector('.menu')
    const close = document.querySelector('.close')
    const nav = document.querySelector('nav')
    
    menu.addEventListener('click',() =>{
        nav.classList.add('open-nav')
    })
    
    close.addEventListener('click',() =>{
        nav.classList.remove('open-nav')
    })
    </script>

However, I'm working with a friend and we're trying to convert the site to use the Microsoft Blazor framework. We've done that largely successfully and re-structured the site slightly so that the header and footer of the site are loaded from a shared "layout" page, and an @body tag in the middle pulls in that particular pages main content. The stylesheet links and the script above are stored in another, separate layout file.

I'm reasonably certain its all linking together properly as the stylesheets are getting applied properly, and the javascript is in the same place as the stylesheet definitions.

However, the Javascript no longer works with everything in Blazor. There are no errors in my browser dev tools, but the style of the nav element simply does not change when I click the .menu element any more.

Is there anything specific to be done in Blazor to allow running of Javascript? How would I even begin to debug if the Javascript is trying to do anything?

Thanks in advance!

CodePudding user response:

In general you should not be manipulating the Browser DOM outside of Blazor. You quickly get the Browser DOM and Blazor DOM out of sync which causes unexpected render results.

There are several ways to hide/show elements in Blazor. As you've provided little context as to what Nav is, here are a couple of ways of showing/hiding a typical component/code block:

@page "/"

<PageTitle>Index</PageTitle>

<h1>Hello, world!</h1>
<div >

    <div >
        <button  type="button" @onclick=OpenMenu1>
            Dropdown button
        </button>
        @if (this.DropdownOpen1)
        {
            <ul >
                <li><a  href="#">Action</a></li>
                <li><a  href="#">Another action</a></li>
                <li><a  href="#">Something else here</a></li>
            </ul>
        }
    </div>

    <div >
        <button  type="button" @onclick=OpenMenu2>
            Dropdown button
        </button>
        <ul >
            <li><a  href="#">Action</a></li>
            <li><a  href="#">Another action</a></li>
            <li><a  href="#">Something else here</a></li>
        </ul>
    </div>
</div>

@code {
    private bool DropdownOpen1;
    private bool DropdownOpen2;

    private string ShowMenu
        => this.DropdownOpen2
            ? "show"
            : string.Empty;

    private void OpenMenu1()
        => DropdownOpen1 = !DropdownOpen1;

    private void OpenMenu2()
        => DropdownOpen2 = !DropdownOpen2;
}

CodePudding user response:

First, if you use Blazor server then you should put all scripts before the below line in the <body> tag in end of _Host.cshtml or _Layout.cshtml according to the version that you use:

<script src="_framework/blazor.server.js"></script>

Second, you have to call the javascripts method in the OnAfterRender or OnAfterRenderAsync such as below:

protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            await jsRuntime.InvokeVoidAsync("YourJavascriptMethodName");
        }
    }

OnAfterRender and OnAfterRenderAsync are called after a component has finished rendering. Element and component references are populated at this point. Use this stage to perform additional initialization steps with the rendered content, such as JS interop calls that interact with the rendered DOM elements.

For more info you can refer to Call JavaScript functions from .NET methods in ASP.NET Core Blazor and After component render (OnAfterRender{Async})

  • Related