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

Posted 3 years 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 3 years ago by nogood Edited 3 years 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 3 years ago by selliott Edited 3 years 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 3 years 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 3 years 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 3 years 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 3 years ago by selliott
Someone is typing...

Post a Reply

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