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

DOM Not Updating On Blazor #54

Open
RoseberryPi opened this issue Sep 28, 2020 · 10 comments
Open

DOM Not Updating On Blazor #54

RoseberryPi opened this issue Sep 28, 2020 · 10 comments
Labels
help wanted Extra attention is needed v1 Version 1.x.x

Comments

@RoseberryPi
Copy link

I'm testing out Halfmoon on Blazor Server Side (an ASP.Net SPA framework) and noticed anything that relies on the pageWrapper and stickyAlerts doesn't get updated correctly.

To fix,

if (!halfmoon.pageWrapper) {
    halfmoon.pageWrapper = document.getElementsByClassName("page-wrapper")[0];
}
if (!halfmoon.stickyAlerts) {
    halfmoon.stickyAlerts = document.getElementsByClassName("sticky-alerts")[0];
}

must be changed to,

halfmoon.pageWrapper = document.getElementsByClassName("page-wrapper")[0];
halfmoon.stickyAlerts = document.getElementsByClassName("sticky-alerts")[0];

in order for the sidebar to toggle (toasts and whatever else relies on those variables). Unfortunately this is just due to the way Blazor functions. I don't have time to dive deep into the issue and what Blazor is doing exactly but the elements stored in the javascript is not the one in the actual DOM.

Not sure if this is an ideal fix for you, since I don't know if it has any consequences I'm not aware of.

@halfmoonui
Copy link
Owner

Unfortunately, I am not familiar with Blazor. Could you explain why the solution you proposed actually fixes the problem? Does Blazor generate the DOM in a novel way or something? And it is not the ideal fix, because the existing code is meant to work with virtual DOMs, ala, Vue, React, etc.

@halfmoonui halfmoonui assigned halfmoonui and unassigned halfmoonui Sep 29, 2020
@halfmoonui halfmoonui added the help wanted Extra attention is needed label Sep 29, 2020
@RoseberryPi
Copy link
Author

I'm still not 100% clear on how Blazor handles the DOM so hopefully I can explain well enough.

To put it simply, halfmoon.pageWrapper and halfmoon.stickyAlerts are set before the DOM is finished rendering (as far as Blazor is concerned).

halfmoonOnDOMContentLoaded is called but since those properties have been set, they're not updated.

So for example, when halfmoon.toggleSidebar is called it updates halfmoon.pageWrapper but it's simply not the same element that is actually in the DOM.

I'm not too familiar with javascript and the DOM (and I don't use Angular, Vue, React, etc.) so maybe I'm not explaining well but regardless, it's an issue with the way Blazor handles DOM manipulation.

Perhaps adding another javascript function that will force those properties to be updated would be the better solution. You keep things the same but Blazor devs still have a work around. Something as simple as:

function forceUpdateDOMContent() {
    halfmoon.pageWrapper = document.getElementsByClassName("page-wrapper")[0];
    halfmoon.stickyAlerts = document.getElementsByClassName("sticky-alerts")[0];
}

Blazor devs would just need to call this through JSInterop after render (using the OnAfterRenderAsync method in razor components) to reset those properties.

Here's some documentation to get more info on Blazor.
Blazor Lifecycle
Blazor JSInterop
Article on Blazor's RenderTree

I can do some more debugging later this week when I'm working on the project again (you can see it here, just a side project).

@halfmoonui
Copy link
Owner

That's interesting. What are they set to, if not the DOM elements? In any case, I have marked this, and I would appreciate input from anyone who is more familiar with Blazor.

@RoseberryPi
Copy link
Author

This is where my knowledge of Blazor's RenderTree and lifecycle fails me. This is just my guess, but I think what may be happening is:

  1. DOM is built on the server

  2. halfmoon.js is loaded

  3. halfmoon.pageWrapper is set (it's set correctly and references the element that contains class="page-wrapper")

  4. Blazor builds the render tree

  5. Blazor sends the render tree and required files, images, etc to the client through SignalR connection

  6. Blazor.server.js manipulates the DOM to replicate the render tree

  7. halfmoon.toggleSidebar is called (sidebar is currently shown)

  8. halfmoon.js adds the data-sidebar-hidden attribute to the pageWrapper element but this is the element from the DOM that is initially built in step 1.

  9. No changes happen to the <div class="page-wrapper"></div> element in the DOM because it was rebuilt from the render tree through blazor.server.js and is actually a different element now than the one is step 1-3

By adding the function in my previous comment and calling it after step 6, the element stored in halfmoon.pageWrapper is updated to the element currently in the DOM.

Now, I may be a little off with that guess or way off. I'm not sure. The whole point of Blazor is being able to manipulate the DOM through C# and so the framework handles the DOM behind the scenes. I've never had to deal with a problem like this.

@halfmoonui
Copy link
Owner

@RoseberryPi Thank you for the details. I am not opposed to adding the method you mentioned, but I would definitely want more validation as to how Blazor actually works under the hood.

@DouglasRiddle
Copy link

I worked around this by calling the Halfmoon js within _Host.cshtml immediately before the blazor js instead of placing it in the <head>. I'm pulling it in from a library so your src url may differ.

<body>
    <app>
        <component type="typeof(App)" render-mode="ServerPrerendered" />
    </app>
    <script type="text/javascript" src="_content/Halfmoon.Blazor/js/halfmoon.js"></script>
    <script src="_framework/blazor.server.js"></script>
</body>

@halfmoonui
Copy link
Owner

@DouglasRiddle Thank you for this solution.

@RoseberryPi Can you please confirm if this works for you or not?

@herorelative
Copy link

herorelative commented Oct 6, 2020

<script src="./js/halfmoon.min.js"></script>
<script src="_framework/blazor.webassembly.js"></script>

When I tried the code sequence like above. Drak Mode perfectly works on blazorwasm (client-side). But not the sidebar. Still digging into it.

@JardineMiller
Copy link

Just to chip in here, this is also a problem in Angular - making the change proposed by the OP fixes the issue there as well.

The issue I was seeing was that toggling the sidebar was not updating the data-sidebar-hidden attribute on the pageWrapper even though the method was executing successfully.

@herorelative
Copy link

herorelative commented Oct 16, 2020

It is working on Blazor wasm. If it works on Blazor wasm, I believe it already works on Server-side Blazor too.
First Import halfmoon.js before blazor.webssembly.js.

<script src="./js/halfmoon.min.js"></script>
<script src="_framework/blazor.webassembly.js"></script>

Second, in index.html inside the app tag use classes as follows.

<app class="page-wrapper with-navbar with-sidebar"
         data-sidebar-type="overlayed-sm-and-down">Loading...</app>

So, the working code will look like.

<body class="with-custom-webkit-scrollbars with-custom-css-scrollbars"
      data-sidebar-shortcut-enabled="true"
      data-dm-shortcut-enabled="true">
    
        <!-- Sticky alerts (toasts), empty container -->
        <app class="page-wrapper with-navbar with-sidebar"
         data-sidebar-type="overlayed-sm-and-down">Loading...</app>


        <div id="blazor-error-ui">
            An unhandled error has occurred.
            <a href="" class="reload">Reload</a>
            <a class="dismiss">🗙</a>
        </div>

        <script src="./js/halfmoon.min.js"></script>
        <script src="_framework/blazor.webassembly.js"></script>
</body>

@halfmoonui halfmoonui added the v1 Version 1.x.x label Aug 23, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed v1 Version 1.x.x
Projects
None yet
Development

No branches or pull requests

5 participants