Why doesn't Blazor show js-alert after .onload?

Posted 61 days ago by nogood
0

Hi,

finaly a Forum just for Blazor :) Thank you!!! 

 

Blazor Serverside

I do have a question that my be someone could answere. I do want to check if a iframe is finished loading. I tried and searched, but I think at the moment it is not possible to pass a Event happenig (in my case the js: .onload) in Js to Blazor.

I did come up with a workaround I thought.

 

I did the following 

js.file:

var loaded = false;

function ResetLoadingFlag() {
    loaded = false;
}

document.getElementById('myFrame').onload = function () { LoadingFinished() };

function LoadingFinished() {
    loaded=true;
}

function JSGetMyIsLoadedFlag() {
    return loaded;
}

and in in Blazor page:

@page "/"
@inject IJSRuntime jsRuntime

<div>
    <div class="col-md-6">
        <button type="button" class="btn btn-info" @onclick="GetMyFlagCSharp">Has iFrame Loaded</button>
    </div>
    @myBool
</div>

<div>
    @*<iframe id="myFrame" src="/MyExternalHtmlPages/test.html"></iframe>*@
    <iframe  id="myFrame" src="https://www.spiegel.de"></iframe>
</div>


@code{
    bool myBool;
    private async Task GetMyFlagCSharp()
    {
        myBool = await jsRuntime.InvokeAsync<bool>("JSGetMyIsLoadedFlag");
    }
}

I thought this way I could atleast check in Blazor the state of DOM element iFrame, but it is not working.

 

My observation is that the problem is somewhere around this line in the js-file: 

document.getElementById('myFrame').onload = function () { LoadingFinished() }; 

The debugger gets to this line but the js function LoadingFinished() is never called.

 

I did make it even more simpler with

document.getElementById('myFrame').onload = function () { alert('yesLoaded') };

no callback etc. but that alert is never shown in Blazor.

BUT

If I check the same js in a  normal Html-Page everthing works: Flag is set and/or Alert is shown.

Why cant Blazor show that alert? How can I achieve this behavior?

Thanks for help... and lets make Blazor happening (my only way to do some FrontEnd (because I do have no clue about js):)

 

 

 

  • 0

    Solution from Stackoverflow:

    The trick is to prefix the event's with @, like @onload in your example, which then takes an EventCallback / Method as a parameter.

     

    <div>
        <iframe id="myFrame" src="https://www.spiegel.de" @onload="IFrameLoaded"></iframe>
    </div>
    @code
    
       string antwort="";
    
       private void IFrameLoaded(ProgressEventArgs e)
    
       {
    
           Console.WriteLine("IFrame loaded");
    
           antwort = "Loaded";
    
       }

    Why the alert is not show still ?

    Posted 61 days ago by nogood Edited 61 days ago
  • 0

    I don't think your JavaScript method is being called by Blazor. Try this to show that your iframe has loaded. Once Blazor is loaded, it invokes JS, then it loads a JS function which calls back to a JSInvokable method in the component. From there, it can invoke an Action that updates the bool value to show the iframe has loaded.

    JS

    var iframe = document.getElementById('myFrame');
    var iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
    
    function NotifyFrameLoaded() {
        if (iframeDoc.readyState == 'complete') {
            console.log('loaded');
            DotNet.invokeMethodAsync('YourProjectNameHere', 'DisplayLoaded'); //Update this to add your project name
        }
    }
    
    window.jsFunctions = {
        JSGetMyIsLoadedFlag: function () {
            NotifyFrameLoaded();
        }
    }

    Component

    <iframe id="myFrame" src="https://www.spiegel.de" @onload="IFrameLoaded"></iframe>
    
    @myBool
        
    @code {
        bool myBool;
        static Action showLoaded;
        
        protected override void OnInitialized()
        {
            showLoaded = ShowLoaded;
        }
        	
        async void IFrameLoaded()
        {
            await jsRuntime.InvokeVoidAsync("jsFunctions.JSGetMyIsLoadedFlag");
        }
    
        async void ShowLoaded()
        {
            myBool = true;
            await InvokeAsync(() => StateHasChanged());
        }
    
        [JSInvokable]
        public static void DisplayLoaded()
        {
            showLoaded.Invoke();
        }
    }

    For more about calling .Net methods in a Blazor component from JavaScript, see: https://docs.microsoft.com/en-us/aspnet/core/blazor/call-dotnet-from-javascript?view=aspnetcore-5.0 

    For more about calling JavaScript functions from Blazor, see: https://docs.microsoft.com/en-us/aspnet/core/blazor/call-javascript-from-dotnet?view=aspnetcore-5.0

    Posted 61 days ago by selliott Edited 61 days ago
  • 0

    Hi selliott, thanks for your repley. Unfortunatly I could not get your example to work. I got the following Error:

    Microsoft.JSInterop.JSException: 'Could not find 'jsFunctions.JSGetMyIsLoadedFlag' ('jsFunctions' was undefined).

    Error: Could not find 'jsFunctions.JSGetMyIsLoadedFlag' ('jsFunctions' was undefined). ...

     

    I'am sorry if that is because of a minor mistake but I'am not able to get it to run properly. It looks like this line 

    window.jsFunctions = {
        JSGetMyIsLoadedFlag: function () {
            NotifyFrameLoaded();
        }
    }

    Is not working as aspected. I'am pretty limited when it comes to Js :(

    For clearefication I do post my complet code again. Not that I manage to make a mistake by Copy/Paste

    Few minor changes "iFrame Id" is now "mySecondFrame" and I do have the test button show alert to make sure js-file is loaded.

    js:

    function ShowAlert(message) {
        alert(message);
    }
    
    //Forums Try Js Start
    var iframe = document.getElementById('mySecondFrame');
    var iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
    
    function NotifyFrameLoaded() {
        if (iframeDoc.readyState == 'complete') {
            console.log('loaded');
            DotNet.invokeMethodAsync('BZ_CheckJSEvents', 'DisplayLoaded'); //Update this to add your project name
        }
    }
    
    window.jsFunctions = {
        JSGetMyIsLoadedFlag: function () {
            NotifyFrameLoaded();
        }
    }

    blazor:

    @page "/iframeloaded"
    @inject IJSRuntime jsRuntime
    
    <h3>IframeLoaded</h3>
    
    <h1>Check if myjs is loaded</h1>
    <br />
    <div class="col-md-6">
        <button type="button" class="btn btn-info" @onclick="ShowAlertWindow">Show Alert Window</button>
    </div>
    <br />
    
    <iframe id="mySecondFrame" src="https://www.spiegel.de" @onload="IFrameLoaded"></iframe>
    
    @myBool
    
    @code {
        private async Task ShowAlertWindow()
        {
            await jsRuntime.InvokeVoidAsync("ShowAlert", "myjs is Loaded");
        }
    
        bool myBool;
        static Action showLoaded;
    
        protected override void OnInitialized()
        {
            showLoaded = ShowLoaded;
        }
    
        async void IFrameLoaded()
        {
            await jsRuntime.InvokeVoidAsync("jsFunctions.JSGetMyIsLoadedFlag");
        }
    
        async void ShowLoaded()
        {
            myBool = true;
            await InvokeAsync(() => StateHasChanged());
        }
    
        [JSInvokable]
        public static void DisplayLoaded()
        {
            showLoaded.Invoke();
        }
    }

     

    thank your for your support and time. I do appriciate it much  :)

     

    Posted 60 days ago by nogood
  • 0

    Where are you referencing your JavaScript file? Have you added it to the _Host.cshtml file (if you're using Blazor Server) or Index.html if you're using WebAssembly? The first thing I'd do is add alert('test'); to your JavaScript file, to make sure you have it hooked up correctly and that it loads an alert when the page loads.

    Posted 60 days ago by selliott
  • 0

    Hi,

    I use Blazor Server for that testproject. My js is loaded in _Host.cshtml like this

     <script src="/myScripts/myjs.js"></script>

    I do the test/tipp that you wrote about checking if js is sucsessfuly loaded/setup I did that and it is working, that should not be the problem. Can you reproduce my error with the last code is posted. That is exactly what I did 

    Posted 60 days ago by nogood
  • 0

    Your code seems to be working for me. I had also tested the code I provided. Are you possibly using an old outdated browser, like IE? If so, please try the latest Microsoft Edge or Firefox and see if it works then.

    Posted 60 days ago by selliott
Someone is typing...

Post a Reply

You must be logged in to add a new post.
Number of online users: 0
An error has occurred. This application may no longer respond until reloaded. Reload 🗙