Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Missing Stylesheet after navigating in .NET 8 #2642

Open
UweKeim opened this issue Dec 10, 2023 · 17 comments
Open

Missing Stylesheet after navigating in .NET 8 #2642

UweKeim opened this issue Dec 10, 2023 · 17 comments

Comments

@UweKeim
Copy link

UweKeim commented Dec 10, 2023

Issue

After navigating away and back to a page, a call to Swal.FireAsync() shows an alert that has CSS missing.

Steps

I've created a new Blazor Web App with these configuration settings:

image

I then added

<PackageReference Include="CurrieTechnologies.Razor.SweetAlert2" Version="5.5.0" />

to my project's CSPROJ file, added

<script src="_content/CurrieTechnologies.Razor.SweetAlert2/sweetAlert2.min.js"></script>

right to the end before the </body> tag:

image

and added this to my "Program.cs":

builder.Services.AddSweetAlert2(options =>
{
	options.Theme = SweetAlertTheme.Dark;
	options.SetThemeForColorSchemePreference(ColorScheme.Light, SweetAlertTheme.Default);
	options.SetThemeForColorSchemePreference(ColorScheme.Dark, SweetAlertTheme.Dark);
});

Next, I created a simple button in "Home.razor":

<button @onclick="@(async ()=>await Swal.FireAsync("Test!"))">Test, klick!</button>

I've also changed @rendermode InteractiveServer on that page. The full source code of the page looks like this:

@page "/"
@rendermode InteractiveServer
@inject SweetAlertService Swal

<PageTitle>Home</PageTitle>

<h1>Hello, world!</h1>

Welcome to your new app.

<button @onclick="@(async ()=>await Swal.FireAsync("Test!"))">Test, klick!</button>

This results in this:

image

When I click the button, it shows this alert:

image

I can do this multiple times successfully.

Next, I navigate to another page:

image

And then I navigate back to the home page:

image

When I then click the button, the alert appears, but it seems to have no styling:

image

It is shown that the bottom left of the page.

It seems to work correctly (i.e. I can click the OK button to close the alert), but it looks wrong.

Expected behavior

I would expect that Razor.SweetAlert2 works every time, not just when I do not navigate.

Desktop

  • OS: Windows 11 German, 64 bit
  • Browser: Google Chrome Version 120.0.6099.71 (Offizieller Build) (64-Bit)
@Pvxtotal
Copy link

Any workaround? Same problem here...

@UweKeim
Copy link
Author

UweKeim commented Dec 15, 2023

It seems, that all my favorite Blazor library developers have shifted priorities away from .NET 8 Blazor 😭.

@filipe-augusto
Copy link

I have the same problem.

filipe-augusto added a commit to filipe-augusto/IBGE-Blazor that referenced this issue Dec 18, 2023
@Pvxtotal
Copy link

Pvxtotal commented Dec 18, 2023

I found a workaround. This is because of the new Blazor SSR, it changes the way that JS is rendered.

You need to use PageScript: https://github.com/MackinnonBuck/blazor-page-script

Import the SweetAlert2 Script in the MainLayout like this: <PageScript Src="./_content/CurrieTechnologies.Razor.SweetAlert2/sweetAlert2.min.js" />

Set a RenderMode for HeadOutlet like this: <HeadOutlet @rendermode="new InteractiveAutoRenderMode(prerender: false)" />

With this trick everything should be working just fine.

This trick solved issues with all JS-based libraries I've imported.

Source: https://learn.microsoft.com/en-us/aspnet/core/blazor/javascript-interoperability/static-server-rendering?view=aspnetcore-8.0

@UweKeim
Copy link
Author

UweKeim commented Dec 18, 2023

In case anyone wonders: The NuGet package of PageScript is named "BlazorPageScript".

And you have to add this to "_Imports.razor":

...
@using BlazorPageScript
...

@UweKeim
Copy link
Author

UweKeim commented Dec 18, 2023

@Pvxtotal When doing your steps, I get an error:

InvalidOperationException: A component of type 'Microsoft.AspNetCore.Components.Web.HeadOutlet' has render mode 'InteractiveAutoRenderMode', but the required endpoints are not mapped on the server. When calling 'MapRazorComponents', add a call to 'AddInteractiveWebAssemblyRenderMode'. For example, 'builder.MapRazorComponents<...>.AddInteractiveWebAssemblyRenderMode()'

Could you please share some more code of your solution?

@Pvxtotal
Copy link

@UweKeim in your case use HeadOutlet like this: <HeadOutlet @rendermode="new InteractiveServerRenderMode(prerender: false)" />

@UweKeim
Copy link
Author

UweKeim commented Dec 18, 2023

Thanks, @Pvxtotal, I've already tried that, too, without success.

I've changed the <HeadOutlet /> in mit "App.razor" to:

<HeadOutlet @rendermode="new InteractiveServerRenderMode(prerender: false)" />

I removed this from the "App.razor":

<script src="_content/CurrieTechnologies.Razor.SweetAlert2/sweetAlert2.min.js"></script>

And then I've added this to "MainLayout.razor":

<HeadContent>
	<PageScript Src="_content/CurrieTechnologies.Razor.SweetAlert2/sweetAlert2.min.js" />
</HeadContent>

When clicking the button to show a SweetAlert2 dialog, I get this error:

Error: Microsoft.JSInterop.JSException: Could not find 'CurrieTechnologies.Razor.SweetAlert2.Fire' ('CurrieTechnologies' was undefined).

With this call stack:

Error: Could not find 'CurrieTechnologies.Razor.SweetAlert2.Fire' ('CurrieTechnologies' was undefined).
    at https://localhost:7133/_framework/blazor.web.js:1:734
    at Array.forEach (<anonymous>)
    at l.findFunction (https://localhost:7133/_framework/blazor.web.js:1:702)
    at b (https://localhost:7133/_framework/blazor.web.js:1:5445)
    at https://localhost:7133/_framework/blazor.web.js:1:3238
    at new Promise (<anonymous>)
    at y.beginInvokeJSFromDotNet (https://localhost:7133/_framework/blazor.web.js:1:3201)
    at fn._invokeClientMethod (https://localhost:7133/_framework/blazor.web.js:1:62541)
    at fn._processIncomingData (https://localhost:7133/_framework/blazor.web.js:1:60016)
    at connection.onreceive (https://localhost:7133/_framework/blazor.web.js:1:53657)
   at Microsoft.JSInterop.JSRuntime.InvokeAsync[TValue](Int64 targetInstanceId, String identifier, Object[] args)
   at CurrieTechnologies.Razor.SweetAlert2.SweetAlertService.FireAsync(String title, String message, SweetAlertIcon icon)
   at BlazorApp6.Components.Pages.Home.<BuildRenderTree>b__0_1() in C:\Users\ukeim\Documents\Visual Studio 2022\Projects\BlazorApp6\Components\Pages\Home.razor:line 11
   at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)

Probably I'm missing something but can't figure out what.

@Pvxtotal
Copy link

@UweKeim  Change it to: <PageScript Src="./_content/CurrieTechnologies.Razor.SweetAlert2/sweetAlert2.min.js" />

./ at the start

@UweKeim
Copy link
Author

UweKeim commented Dec 18, 2023

Thanks again, @Pvxtotal, I've also tried this without success.

@UweKeim
Copy link
Author

UweKeim commented Dec 18, 2023

It seems that I solved it by not placing the <PageScript... component into the <HeadContent> tags, but simply at the very end of the "MainLayout.razor" page:

<PageScript Src="/_content/CurrieTechnologies.Razor.SweetAlert2/sweetAlert2.min.js" />

I still have to have this in the "App.razor":

<HeadOutlet @rendermode="new InteractiveServerRenderMode(prerender: false)" />

But all after all, it seems to work.

@Basaingeal
Copy link
Owner

Sorry for my absence. I'll be looking into this, but .NET 8 runtime support has been added. That may aleviate this issue, but if there is a breaking change in .NET 8 I'll need to work out a fix.

@Pvxtotal
Copy link

@Basaingeal This is related to how Blazor SSR load scripts when enhanced navigation is on. If you disable enhanced navigation everything works fine. I still don't know any workaround besides disabling enhanced navigation or turning the entire app into Interactive.

Source: dotnet/aspnetcore#52273

@muadyb
Copy link

muadyb commented Mar 28, 2024

Work for me adding only this line @rendermode="@RenderMode.InteractiveServer" on app.razor in HeadOutlet and Routes also works fine with @rendermode="@(new InteractiveServerRenderMode(false))"

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <base href="/" />
    <link rel="stylesheet" href="bootstrap/bootstrap.min.css" />
    <link rel="stylesheet" href="app.css" />
    <link rel="stylesheet" href="Biblioteca.Server.styles.css" />
    <link rel="icon" type="image/png" href="favicon.png" />
    <HeadOutlet @rendermode="@RenderMode.InteractiveServer"/>
</head>

<body>    
    <Routes @rendermode="@RenderMode.InteractiveServer" />
    <script src="_framework/blazor.web.js"></script>
    <Script src="_content/CurrieTechnologies.Razor.SweetAlert2/sweetAlert2.min.js"></Script>
</body>

@jdiazc2000
Copy link

Hi muadyb, your solution worked fine for me, Thanks four you help :)!

@jdiazc2000
Copy link

Work for me adding only this line @rendermode="@RenderMode.InteractiveServer" on app.razor in HeadOutlet and Routes also works fine with @rendermode="@(new InteractiveServerRenderMode(false))"

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <base href="/" />
    <link rel="stylesheet" href="bootstrap/bootstrap.min.css" />
    <link rel="stylesheet" href="app.css" />
    <link rel="stylesheet" href="Biblioteca.Server.styles.css" />
    <link rel="icon" type="image/png" href="favicon.png" />
    <HeadOutlet @rendermode="@RenderMode.InteractiveServer"/>
</head>

<body>    
    <Routes @rendermode="@RenderMode.InteractiveServer" />
    <script src="_framework/blazor.web.js"></script>
    <Script src="_content/CurrieTechnologies.Razor.SweetAlert2/sweetAlert2.min.js"></Script>
</body>

Hi muadyb, your solution worked fine for me, Thanks four you help :)!

@Pvxtotal
Copy link

Pvxtotal commented May 19, 2024

    <Routes />
    <script src="_framework/blazor.web.js"></script>
    <script src="_content/CurrieTechnologies.Razor.SweetAlert2/sweetAlert2.min.js"></script>

    <script>
        function injectScript(url) {
            const script = document.createElement('script');
            script.src = url;
            document.head.appendChild(script);
        }

        Blazor.addEventListener('enhancedload', () => {
            const oldScript = document.querySelector('script[src="_content/CurrieTechnologies.Razor.SweetAlert2/sweetAlert2.min.js"]');
            if (oldScript) {
                oldScript.remove();
            }

            injectScript('_content/CurrieTechnologies.Razor.SweetAlert2/sweetAlert2.min.js');
        });

    </script>
i've found another workaround to make it work with Blazor SSR. Just remove and insert the script on each navigation. This applies to every JS interaction with Blazor SSR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants