-
Notifications
You must be signed in to change notification settings - Fork 10.1k
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
Preservation of attributes and elements in "Enhanced navigation" #49613
Comments
Is it possible to turn "enhanced navigation" off? |
@marinasundstrom thanks for contacting us. Modifying the DOM outside of the scope of Blazor is problematic, as we will silently override your changes (as it's happening). It looks like we don't have a way to turn off enhanced navigation, so we should add one. In addition to that, we don't have a way to specify that something needs to be preserved. There are a couple of ways you could go about it.
On our side, we could potentially have a way to let other frameworks/code play nice with enhance navigation by giving them a way to specify attributes/elements that must be preserved. |
Keeping in RC1 to see if we can add a way to |
We do already have a way to turn it off: Blazor.start({
ssr: { disableDomPreservation: true }
}); |
I have come to like DOM preservation. It really is more like a SPA - when it works. Especially when interactive components are present. But you need to get used to it and design you apps to fit it. I'm trying to build an e-shop site. A server-side rendered app with several Blazor WebAssembly components: A cart display icon living in the navbar, and an off-canvas for the cart. They are not pre-rendered and pretty much lives on the site as long as the DOM is preserved. There are some other problems, like with the buffer stuff. Turning of pre-rendering for non-essential WASM components help with that. And I even had a case of manipulating the DOM - moving the Cart display (Blazor WASM component) in the navbar to be displayed correctly on small screens and vice versa. That required timeouts to be set to wait for the component to be initialized, and then to set up the necessary event handlers for window resizing. The problem with the attribute being removed is of course a problem for me - but right now it is not urgent for my work. |
My main problems with the enhanced navigation in SSR is:
Other frameworks (JS)Fireship recently posted a video about View Transitions in Astro. It provides APIs to deal with transition in "soft navigation".
More about View Transitions in the Astro docs. SuggestionPerhaps the Astro way is the way to go for Blazor as well.
document.addEventListener('blazor:beforeload', () => { console.log('loaded'); })
<div>
<span>Foo</span>
<div @preserveNode>
Text
</div>
</div> <html @preserveAttributes="data-bs-theme" data-bs-theme="dark">
<head>
</head>
<body>
</body>
</html> |
I anticipate this will be a very popular feature request. It's common for Blazor apps and libraries to dynamically modify statically rendered DOM. For example, libraries frequently use JS initializers to dynamically add required scripts or stylesheets to the page. Even Blazor's default reconnection UI relies on dynamically modifying the DOM, and it currently breaks after an enhanced navigation occurs because it assumes that once it's added to the DOM, it stays there. It will be unfortunate if so many apps need to disable one of Blazor's major features in .NET 8 in order to work correctly. Rather than making the preservation of DOM elements opt-in, I wonder if we could update our DOM sync logic to add some metadata to all server-rendered DOM elements to mark them as candidates for removal/replacement during an enhanced update. We could even go further and have each element hold some metadata tracking which attributes are server-rendered. Then during synchronization, any DOM element that doesn't include such metadata will be preserved. This should allow existing apps to continue working without having to go through and manually mark elements or attributes as preserved. Of course, the main downside is that this complicates the DOM synchronization algorithm further. And if the metadata was represented by invisible properties on each DOM node (similar to how Blazor's "logical elements" work), we would have to ensure that the entire initial DOM gets populated with that metadata before other library/app JS code has the chance to dynamically mutate the DOM. Otherwise, DOM mutations happening immediately upon page load would get reverted when the first enhanced update happens. The alternative is to have the server embed the metadata as HTML attributes, but that adds a lot of clutter to the DOM. |
@MackinnonBuck This (#50268) seems to be another issue with enhanced navigation and DOM preservation not doing as expected. It is unable to apply the |
Is there an existing issue for this?
Is your feature request related to a problem? Please describe the problem.
Background
I have a pre-rendered server-side rendered site which is using Bootstrap, and it has got some scripts to apply color modes (Dark mode, Light mode etc).
The scripts are supposed run every time a page loads to make sure that:
data-bs-theme
is set onhtml
to whatever mode is preferred by the user: e.g. dark.This breaks due to how "enhanced navigation" works.
Problem description
Upon navigating to page by clicking a link:
data-bs-theme
is removed in the diff. Causing the theme to be reset,I would be OK with the script only executing once if the important elements were preserved.
Describe the solution you'd like
My suggestion is to implement:
a way to exclude certain elements and attributes from changing due to the diff being applied as part of enhanced navigation. E.g. the
data-bs-theme
attribute in thehtml
element.a way to mark a component or element so that it is not affected by the diff. Use case: In order to preserve the state of the theme indicator.
Unless there are other ways to deal with this.
Additional context
Try using the theme selector here and navigation back and forth:
https://blazor8app.graypebble-0c46426e.westus2.azurecontainerapps.io/
The text was updated successfully, but these errors were encountered: