Riley Varga
Riley Varga

Reputation: 720

Why can't I load any js after my blazor.server.js?

So I noticed that in my _Host.cshtml file I have this script before the </body> tag

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

And I also have some scripts that are suppose to load after that which are these

    <script src="assets/plugins/jquery/jquery.min.js"></script>
    <script src="assets/plugins/jquery-ui/jquery-ui.js"></script>
    <script src="assets/plugins/popper/popper.js"></script>
    <script src="assets/plugins/feather/feather.min.js"></script>

    <script src="assets/plugins/bootstrap/js/bootstrap.min.js"></script>
    <script src="assets/plugins/typeahead/typeahead.js"></script>
    <script src="assets/plugins/typeahead/typeahead-active.js"></script>
    <script src="assets/plugins/pace/pace.min.js"></script>
    <script src="assets/plugins/slimscroll/jquery.slimscroll.min.js"></script>
    <script src="assets/plugins/highlight/highlight.min.js"></script>

    <!-- Articles Script -->
    <script src="assets/plugins/dataTable/datatables.min.js"></script>
        <script src="assets/plugins/summernote/summernote.min.js"></script>
        <script src="assets/plugins/bootstrap-tagsinput/bootstrap-tagsinput.js"></script>
    <!-- Required Script -->
    <script src="assets/js/app.js"></script>
    <script src="assets/js/avesta.js"></script>
    <script src="assets/js/avesta-customizer.js"></script>

</body>

However, if I have the blazor.js script at the top, my menu won't act normal, it will stop working and look like this. I'm actually clicking a lot and it's not animating as you can see.

enter image description here

However if I put the blazor.server.js script at the bottom to load last, it works just fine and looks like this

enter image description here

But then if I load it last, I get this in my console

enter image description here

which results in my not being able to do this

<input @bind="@CurrentValue" @oninput="@((e) => { CurrentValue=(string)e.Value;})" @onkeypress="KeyPress" class="form-control" type="text" placeholder="Search" aria-label="Search">

It just doesn't hit the function at all, nothing happens, it doesnt register it.

Upvotes: 7

Views: 8658

Answers (4)

GYAMFI ERIC
GYAMFI ERIC

Reputation: 1

Using .net 7, you can reference the JS inside the OnAfterRenderAsync under the code section of the blazor component you want to use use/call the JS.

Eg: Assuming you want to call the script.js JS under the index component, then you need to add the following code to the @code section of the index component;

@inject IJSRuntime JS

protected override async Task OnAfterRenderAsync(bool firstRender)
{
    if (firstRender)
    {
        var jsModule = await JS.InvokeAsync<IJSObjectReference>("import", "./assets/js/script.js");
        
    }
}

Where assets/js/script.js is the file location inside the wwwroot folder.

Upvotes: 0

Selim Balci
Selim Balci

Reputation: 910

It's not a complete solution (at least for me yet) as it's causing all sorts of racing conditions - but seems like I'm on the correct path of solving this - hopefully some time within the next decade.

Seems like one of the nicer ways of doing this is disabling the autostart on blazor.server|webassembly.js link, and then adding the JS file imports by adding them as elements.

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

After this, create a below your blazor import, and import your elements to the page. You will see them being added to the page after Blazor is loaded. Excuse the dirty code, it's WIP and I'm still experimenting.

<script>
    Blazor.start().then(function () {

        var customScript = document.createElement('script');
        customScript.setAttribute('src', 'assets/plugins/global/plugins.bundle.js');
        document.body.appendChild(customScript);
        
        var anotherScript = document.createElement('script');
        anotherScript.setAttribute('src', 'assets/js/scripts.bundle.js');
        document.body.appendChild(anotherScript);
    });
</script>

If you don't add the autostart="false" attribute, you'll see an error message in console, saying that the Blazor has already started.

My understanding is that await JSRuntime.InvokeAsync<Iblah>("import", "blah.js"); is meant for Razor components, but correct me if I'm wrong. If anyone wonders, I'm using Metronic, not that it matters.

Upvotes: 1

Usman Jalil
Usman Jalil

Reputation: 192

Can you guys if possible share screen shot or show how you added JavaScript Libraries Reference in project to make it work and Where (e.g. MainLayout.razor or _Host.cshtml) also where you guys added blazor.server.js

I tried both ways adding JavaScript references in _Host.cshtml file before tag like following. But it didn't worked.

<script src="~/_framework/blazor.server.js"></script>
<script src="~/plugins/global/plugins.bundle.js"></script>
<script src="~/plugins/custom/prismjs/prismjs.bundle.js"></script>
<script src="~/js/scripts.bundle.js"></script>
<script src="~/plugins/custom/fullcalendar/fullcalendar.bundle.js"></script>
<script src="~/js/custom/widgets.js"></script>
<script src="~/js/pages/custom/wizard/wizard-5.js"></script>

Then I added as you suggested in last comments under MainLayout.razor page even that didn't worked. For MainLayout please see following (In this case If I inspect page element it is not showing any JavaScript References in Page Tags.

@code {
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            await JSRuntime.InvokeAsync<IJSObjectReference>("import", "_framework/blazor.server.js");
            await JSRuntime.InvokeAsync<IJSObjectReference>("import", "/plugins/global/plugins.bundle.js");
            await JSRuntime.InvokeAsync<IJSObjectReference>("import", "/plugins/custom/prismjs/prismjs.bundle.js");
            await JSRuntime.InvokeAsync<IJSObjectReference>("import", "/js/scripts.bundle.js");
            await JSRuntime.InvokeAsync<IJSObjectReference>("import", "/plugins/custom/fullcalendar/fullcalendar.bundle.js");
            await JSRuntime.InvokeAsync<IJSObjectReference>("import", "/js/pages/widgets.js");
            await JSRuntime.InvokeAsync<IJSObjectReference>("import", "/js/pages/custom/wizard/wizard-5.js");
        }
    }
}

Note: I also tried with ~/ or / or ../ just before library path but didn't worked for me.

Upvotes: 1

Barcollin
Barcollin

Reputation: 107

Using the Net5, You can now reference your scripts on the main layout by overriding the OnAfterRenderAsync. Here is an example

You will first inherit IJSRuntime

@inject IJSRuntime JSRuntime 

Then here is the Code:

@code {        
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if(firstRender)
        {
            await JSRuntime.InvokeAsync<IJSObjectReference>("import", "/assets/plugins/jquery/jquery.min.js");
        }
    }
}

Upvotes: 5

Related Questions