Feature to support Blazor Data Enhanced Nav and other features like it #4714
Replies: 1 comment 3 replies
-
|
I'm exactly battling this problem right now, only we don't use Alpine Async. In my main layout, I have a navigation component that is interactive, has an When changing pages, the dom diffing of Blazor "resets" this component. The x-show not only doesn't evaluate once the page is changed, but the menu appears as if the value was "true" (it's not). To be noted: Alpine does interact with it because there's an x-cloak on the element initially and if it gets added, regardless if it's blazor or my custom code, it gets removed instantly. Then, if I change the values of navOpened, it's still reactive and resumes its normal functionality. The menu is wrongly opened after changing page, even if its value is false, but if I set navOpened to true and then false again, it closes and resumes working normally). TL;DR:
|
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
I'm working on a project where most of my pages are Blazor SSR (static) components. For these static pages I've been using Alpine to add light interactivity and AsyncAlpine to split up JS files into components and dynamically load them.
Data enhanced nav is pretty nice for user experience in my opinion, I like the client side routing feel. I've been working on adjusting Alpine and AsyncAlpine to support it and I've made some progress that I'd like to share with the community. I've seen at least a few questions on here related to Blazor Data Enhanced Navigation, HTMX, and Phoenix Liveview and how it interacts with Alpine. My solution so far is not perfect, but it's substantially better than where I started.
I started with this, making a Razor Class Library for my project:
How it works
Step 1
I hook into
onEnhancedNavigationStartand defer Alpine mutations and also observe my own mutations for cleaning up some AsyncAlpine stuffStep 2
Then I hook into
onEnhancedNavigationEnd(onEnhancedLoadwon't have the DOM observations ready yet)Step 3
And finally, I added directly to the Alpine source, in the data directive definition:
directive("data", (el, { expression }, { cleanup: cleanup2 }) => { if (shouldSkipRegisteringDataDuringClone(el)) return; expression = expression === "" ? "{}" : expression; let magicContext = {}; injectMagics(magicContext, el); let dataProviderContext = {}; injectDataProviders(dataProviderContext, magicContext); let data2 = evaluate(el, expression, { scope: dataProviderContext }); if (data2 === void 0 || data2 === true) data2 = {}; injectMagics(data2, el); let reactiveData = reactive(data2); initInterceptors(reactiveData); let undo = addScopeToNode(el, reactiveData); reactiveData["init"] && evaluate(el, reactiveData["init"]); cleanup2(() => { reactiveData["destroy"] && evaluate(el, reactiveData["destroy"]); undo(); + delete el._x_dataStack; }); });Explanation of Steps
delete target._x_asyncbut theundo()function in Alpine's data directive definition depends on it to clean up the data stack. As far as I've tested so far, this doesn't break the library, but I really have no clue how everything in Alpine works under the hood yet. What I ran into is for an element which had it's x-data attribute change from one data definition to another, that elements_x_dataStackfield would be an empty array instead of falsy, which caused theclosestDataStackfunction to fail to properly find a parent with data. Specifically,if (node._x_dataStack)would be true for[]on an element which previous had x-data, but was removed after the nav.Remaining Issues
_x_dataStackon x-data's cleanup, or it has to do with how Alpine reads DOM changes by Blazor, or maybe it's the deferral.Before nav:

After nav:

After nav, after interaction:

Future
I will try to keep improving this when substantial issues pop up. This project is for an internal staff area I'm still working on, So I can tolerate a little bit of weirdness and can't dedicate all my time to fixing this completely. I'd love it if other people could help me dig into this and put together a PR for Alpine and AsyncAlpine that helps support Alpine for frameworks that do live DOM patching.
Beta Was this translation helpful? Give feedback.
All reactions