Preservation of attributes and elements in "Enhanced navigation"
See original GitHub issueIs there an existing issue for this?
- I have searched the existing issues
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:
- The
data-bs-theme
is set onhtml
to whatever mode is preferred by the user: e.g. dark. - The theme indicator in the navbar gets updated to reflect the active theme.
This breaks due to how “enhanced navigation” works.
Problem description
Upon navigating to page by clicking a link:
- The script is not executed.
- The
data-bs-theme
is removed in the diff. Causing the theme to be reset, - The theme indicator in the navbar is reset, when it should be preserved.
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/
Issue Analytics
- State:
- Created 2 months ago
- Comments:7 (4 by maintainers)
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.
We do already have a way to turn it off: