Javascript functions not working in my blazor server project!

Hamed Vaziri 136 Reputation points
2023-04-17T22:18:09.22+00:00

Hi everyone! I have a viewer webPage which contains some css & javascript files as references. Now to import it into my blazor-server project, after create new project, make some changes to add my given web-page functionality into my blazor server project as follow : Add these reference into _Host.cshtml > head tag (& place it inside wwwroot folders) :


<link rel="stylesheet" href="css/style.css" />
    <link rel="stylesheet" href="css/all.min.css" />
    <script src="js/bootstrap.bundle.min.js" defer></script>
    <script src="js/jquery-3.6.min.js"></script>
    <script src="js/wheel-zoom.min.js"></script>
    <script src="js/app.js"></script>

Add this code to index.razor page :

<div style="height: 100vh;" class="d-flex flex-column justify-content-between">

    <!-- Tools Panel Section -->
    <section>
        <div class="col-12 d-flex justify-content-center mt-md-2 mt-lg-2">
            <!-- Tools -->
            <div class="tools d-flex flex-wrap flex-sm-wrap flex-md-wrap flex-lg-wrap">
                <span id="magnifier" class="d-none d-lg-inline" data-bs-toggle="tooltip" data-bs-placement="bottom"
                      title="ذره بین"><i class="fas fa-magnifying-glass"></i></span>
                <span id="zoom-in" data-bs-toggle="tooltip" data-bs-placement="bottom" title="بزرگ نمایی">
                    <i class="fas fa-magnifying-glass-plus"></i>
                </span>
                <span id="zoom-out" data-bs-toggle="tooltip" data-bs-placement="bottom" title="کوچک نمایی">
                    <i class="fas fa-magnifying-glass-minus"></i>
                </span>
                <span id="fit-size" data-bs-toggle="tooltip" data-bs-placement="bottom" title="اندازه استاندارد">
                    <i class="fas fa-expand"></i>
                </span>
                <div class="seprator-line"></div>
                <span id="rotate-r" data-bs-toggle="tooltip" data-bs-placement="bottom" title="چرخش به راست">
                    <i class="fas fa-solid fa-rotate-right"></i>
                </span>
                <span id="rotate-l" data-bs-toggle="tooltip" data-bs-placement="bottom" title="چرخش به چپ">
                    <i class="fas fa-solid fa-rotate-left"></i>
                </span>
                <span id="flip-v" data-bs-toggle="tooltip" data-bs-placement="bottom" title="چرخش عمودی">
                    <i class="fas fa-grip-lines-vertical"></i>
                </span>
                <span id="flip-h" data-bs-toggle="tooltip" data-bs-placement="bottom" title="چرخش افقی">
                    <i class="fas fa-grip-lines"></i>
                </span>
                <div class="seprator-line"></div>
                <span id="invert" data-bs-toggle="tooltip" data-bs-placement="bottom" title="رنگ معکوس">
                    <i class="fa-solid fa-fill"></i>
                </span>

                <span id="reset" data-bs-toggle="tooltip" data-bs-placement="bottom" title="بازگردانی">
                    <i class="fa-solid fa-rotate"></i>
                </span>
                <span id="info" data-bs-toggle="tooltip" data-bs-placement="bottom" title="اطلاعات">
                    <i class="fa-solid fa-info-circle"></i>
                </span>
                <span id="mobileContrast" class="d-flex flex-column justify-content-center">
                    <i class="fa-solid fa-circle-half-stroke"></i>
                    <div style="margin-top: -5px;" class="contrast-count">-</div>
                </span>
                <span id="mobileBrightness" class="d-flex flex-column justify-content-center">
                    <i class="fa-solid fa-sun"></i>
                    <div style="margin-top: -5px;" class="brightness-count">-</div>
                </span>
                <!-- Range Sliders -->
                <div class="ranges d-flex flex-row ms-5 flex-sm-wrap d-none d-md-none d-lg-block">
                    <label for="contrastRange" class="form-label position-absolute mt-3">
                        Contrast
                        <span id="contrastPercent">-</span>
                        <i id="resetContrast" class="fa-solid fa-rotate ms-1"></i>
                    </label>
                    <input type="range" class="form-range" id="contrastRange" value="100" min="0" max="200">
                </div>
                <div class="ranges d-flex flex-row ms-3 d-none d-md-none d-lg-block">
                    <label for="brightnessRange" class="form-label position-absolute mt-3">
                        Brightness
                        <span id="brightnessPercent">-</span>
                        <i id="resetBrightness" class="fa-solid fa-rotate ms-1"></i>
                    </label>
                    <input type="range" class="form-range" id="brightnessRange" min="0" max="200">
                </div>
            </div>
        </div>
    </section>

    <!-- Image View Section -->
    <section>
        <div id="myWindow" style="width:100%;height:60vh;border: 1px solid #000;" class="d-flex flex-column">
            <div id="myContent" class="position-relative">
                <div class="my-badge" id="myBadge"
                     style="left:20px;top:20px;font-size: 1.1rem; color: white;position: absolute;">
                    <div class="info-box d-flex flex-row justify-content-around mt-2 mb-2 align-content-center text-white fw-bold">
                        <span class="doctor-info text-white">
                            <span class="doc-name">دکتر بهرامی</span>
                            <span class="ingo-sep">-</span>
                            <span class="clinic-name">رادیولوژی مهر</span>
                        </span>
                    </div>
                </div>
                <div class="my-badge" id="myBadge"
                     style="right:20px;top:20px;font-size: 1.1rem; color: white;position: absolute;">
                    <span class="user-info text-white">
                        <span class="name-family">علی کمالی</span>
                        <span class="ingo-sep">-</span>
                        <span class="user-age">25 سال</span>
                    </span>
                </div>
                <div class="img-magnifier-glass"></div>
                <img class="myImage" style="" id="myImage" src="/img/img-1.jpg" alt="image" />
            </div>
        </div>
    </section>

</div>

In my sample web-page it works perfectly, but in my blazor-server project, buttons does not works. What's the problem & how to solve it? I'm using VS 2022 & .Net 7.0 Thanks in advance

Developer technologies | ASP.NET | ASP.NET Core
Developer technologies | .NET | Blazor
0 comments No comments
{count} votes

6 answers

Sort by: Most helpful
  1. Hamed Vaziri 136 Reputation points
    2023-04-19T08:32:16.9166667+00:00

    Thanks all My problem has solved. I've placed "jquery-3.6.min.js" import line on top of "bootstrap.bundle.min.js" as follow :

    protected override async Task OnAfterRenderAsync(bool firstRender)
        {
            if (firstRender)
            {            
                await _jsRunTime.InvokeAsync<IJSObjectReference>("import", "./js/jquery-3.6.min.js");
                await _jsRunTime.InvokeAsync<IJSObjectReference>("import", "./js/bootstrap.bundle.min.js");
                await _jsRunTime.InvokeAsync<IJSObjectReference>("import", "./js/wheel-zoom.min.js");
                await _jsRunTime.InvokeAsync<IJSObjectReference>("import", "./js/app.js");
            }
        }
    

    And it works fine! Thanks for your help. Best regards

    3 people found this answer helpful.
    0 comments No comments

  2. Anonymous
    2023-04-18T02:42:27.6833333+00:00

    Hi @Hamed Vaziri

    Blazor maintains representations of the DOM and interacts directly with DOM objects. If an element rendered by Blazor is modified externally using JS directly or via JS Interop, the DOM may no longer match Blazor's internal representation, which can result in undefined behavior. Undefined behavior may merely interfere with the presentation of elements or their functions but may also introduce security risks to the app or server.

    So, in Asp.net core Blazor application, to call into JS from .NET, we need to inject the IJSRuntime abstraction and call one of the following methods:

    For example: in this sample, after clicking the button, it will use the IJSRuntime.InvokeAsync method to call the JavaScript function.

    User's image

    More detail information about ASP.NET Core Blazor JavaScript interoperability (JS interop), see:
    Call JavaScript functions from .NET methods in ASP.NET Core Blazor
    Call .NET methods from JavaScript functions in ASP.NET Core Blazor


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.
    Best regards,
    Dillion

    1 person found this answer helpful.

  3. Bruce (SqlWork.com) 77,686 Reputation points Volunteer Moderator
    2023-04-17T23:16:51.2833333+00:00

    as Blazor uses a virtual dom, you should not use javascript to change the dom without Blazor's knowledge or you may have issues. You should remove the jquery and bootstrap js files (bootstrap css is fine). then recode the bootstrap toggles in blazor (the toggle just adds/removes class names to an element).

    generally you need to wrap the javascript component with a blazer component. this is easier if the javascript component only adds events, and create dom elements outside the <app> element. beware of javascript component that move elements of the dom (like most modals).

    0 comments No comments

  4. Hamed Vaziri 136 Reputation points
    2023-04-18T15:01:10.0866667+00:00

    Hi again! My problem is almost solved! I've changed js file path with add "./" at first of each file and works :

    protected override async Task OnAfterRenderAsync(bool firstRender)
        {
            if (firstRender)
            {
                await _jsRunTime.InvokeAsync<IJSObjectReference>("import", "./js/bootstrap.bundle.min.js");
                await _jsRunTime.InvokeAsync<IJSObjectReference>("import", "./js/jquery-3.6.min.js");
                await _jsRunTime.InvokeAsync<IJSObjectReference>("import", "./js/wheel-zoom.min.js");
                await _jsRunTime.InvokeAsync<IJSObjectReference>("import", "./js/app.js");
            }
        }
    

    But i have another problem, after my webpage loaded, i'm facing this error in browser console :

    jquery-3.6.min.js:2  jQuery.Deferred exception: $(...).tooltip is not a function TypeError: $(...).tooltip is not a function
        at HTMLDocument.<anonymous> (http://localhost:5231/js/app.js:3:37)
        at e (http://localhost:5231/js/jquery-3.6.min.js:2:30038)
        at t (http://localhost:5231/js/jquery-3.6.min.js:2:30340) undefined
    S.Deferred.exceptionHook @ jquery-3.6.min.js:2
    t @ jquery-3.6.min.js:2
    setTimeout (async)
    (anonymous) @ jquery-3.6.min.js:2
    c @ jquery-3.6.min.js:2
    add @ jquery-3.6.min.js:2
    (anonymous) @ jquery-3.6.min.js:2
    Deferred @ jquery-3.6.min.js:2
    then @ jquery-3.6.min.js:2
    S.fn.ready @ jquery-3.6.min.js:2
    S.fn.init @ jquery-3.6.min.js:2
    S @ jquery-3.6.min.js:2
    (anonymous) @ app.js:2
    jquery-3.6.min.js:2  Uncaught TypeError: $(...).tooltip is not a function
        at HTMLDocument.<anonymous> (app.js:3:37)
        at e (jquery-3.6.min.js:2:30038)
        at t (jquery-3.6.min.js:2:30340)
    

    What's the problem & how to solve it? Note : In my main web-page (outside of my blazor project which works correctly), the file (bootstrap.bundle.min.js) imported with defer attribute whereas i did not set defer attribute in my blazor project. Is my problem is related to this issue? If yes, how to add defer attribute in my blazor project when importing js file via IJSRuntime.InvokeAsync? Thanks in advance

    0 comments No comments

  5. Bruce (SqlWork.com) 77,686 Reputation points Volunteer Moderator
    2023-04-18T16:01:55.48+00:00

    again, its not supported to use bootstrap js code inside the blazor section of the dom.

    you should not need to async load the script files via blazor, just place in the <head> as previous. the bootstrap code uses the $.ready() to know when to auto attach events. but the $.ready() will run before blazor has rendered its html, so you will need to manually attach the bootstrap events.

    you should attach events at the body and use selectors else you will create memory leaks, as the blazor render engine will delete elements without telling jquery, which will hold a reference to the element.

    if you need to attach an event directly to an element, you will need to use the blazor component events and dom reference to attach/detach events.

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.