aspnetcore icon indicating copy to clipboard operation
aspnetcore copied to clipboard

force full render / avoid differential render flag

Open omuleanu opened this issue 3 years ago • 6 comments

Is there an existing issue for this?

  • [X] I have searched the existing issues

Is your feature request related to a problem? Please describe the problem.

I'm doing drag-and-drop using js, which does manipulate the DOM, and after StateHasChanged() it won't render correctly.

I can avoid DOM manipulations (revert some necessary DOM changes) but this will create a blink effect after Drop.

Describe the solution you'd like

<div @ForceFullRender="@boolValue"></div>

Additional context

my current drag-and-drop where I avoid manipulating DOM, and getting Blink https://imgur.com/d0DX1A7

omuleanu avatar Sep 20 '22 12:09 omuleanu

Thank you for filing this issue. In order for us to investigate this issue, please provide a minimalistic repro project (ideally a GitHub repo) that illustrates the problem.

mkArtakMSFT avatar Sep 20 '22 16:09 mkArtakMSFT

Hi @omuleanu. We have added the "Needs: Author Feedback" label to this issue, which indicates that we have an open question for you before we can take further action. This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.

ghost avatar Sep 20 '22 16:09 ghost

@mkArtakMSFT you can see a repro here: https://blazorfiddle.com/s/050odzst

omuleanu avatar Sep 20 '22 17:09 omuleanu

@omuleanu There is a way to control whether or not DOM subtrees are retained - it's the @key directive attribute. If you use this, and change the associated value, then Blazor will be forced to discard and recreate the subtree.

Example:

<div @key="refreshIndex">
    Here is any subtree
</div>

<button @onclick="DoSomething">Recreate</button>

@code {
   int refreshIndex = 0;

   void DoSomething()
   {
       refreshIndex++;
   }
}

Hopefully that meets your needs.

SteveSandersonMS avatar Sep 22 '22 16:09 SteveSandersonMS

Hi @omuleanu. We have added the "Needs: Author Feedback" label to this issue, which indicates that we have an open question for you before we can take further action. This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.

ghost avatar Sep 22 '22 16:09 ghost

@SteveSandersonMS that seems to work, except now I loose all my js binding after @key refresh, I suppose that's a different problem

omuleanu avatar Sep 22 '22 19:09 omuleanu

@SteveSandersonMS does Blazor have any client ( JS ) BeforeRender events, this way I could revert my DOM changes right before Blazor.js is doing its thing.

omuleanu avatar Sep 23 '22 09:09 omuleanu

No it doesn't. It's not been a common feature request. Generally it's not safe to mutate the DOM from JS because Blazor might expect it to be consistent with the previous render at any moment.

SteveSandersonMS avatar Sep 23 '22 09:09 SteveSandersonMS

@SteveSandersonMS if there was a js event that will inform that Blazor is about to do some work, I could do something like: $('#div1').on('blazorBeforeRenderCheck', reverMyDomChanges);

omuleanu avatar Sep 23 '22 09:09 omuleanu

I understand, however couldn't reasonably guarantee that Blazor will always notify you before everything it will do as we add more features in the future.

What you're doing with mutating the DOM outside Blazor is definitely unsupported. However while you're doing unsupported things, you could go further and patch Blazor._internal.renderBatch. For example:

<script src="blazor.webassembly.js" autostart="false"></script>
<script>
    // This is *very* unsupported and might not work in future versions
    const origRender = Blazor._internal.renderBatch;
    Blazor._internal.renderBatch = function() {
        console.log('Rendering now...');
        return origRender.apply(this, arguments);
    };
    Blazor.start();
</script>

Note that you have to use autostart=false like this to be able to patch the internals. At least I think this will work, but haven't tested it.

SteveSandersonMS avatar Sep 23 '22 09:09 SteveSandersonMS

@SteveSandersonMS think I'll have to stick to supported methods and let my drag and drop blink. btw I tried your code with blazor.server.js and it doesn't execute, I presume blazor.server.js has different _internal

omuleanu avatar Sep 23 '22 10:09 omuleanu

@SteveSandersonMS I managed to get refreshIndex method working, so no more blinking, now I'm binding the js from outside the refreshed div, kind of like $(document).on(event, selector, instead of $(selector).on(event The only problem now is that all the scrollbars go back to 0 after refresh, so I have to choose now between, blink and scrollbars reset.

omuleanu avatar Sep 24 '22 14:09 omuleanu