elm / virtual-dom

The foundation of HTML and SVG in Elm.
https://package.elm-lang.org/packages/elm/virtual-dom/latest
BSD 3-Clause "New" or "Revised" License
209 stars 80 forks source link

`--debug` changes behavior of `Elm.Main.embed` #123

Closed elliotdickison closed 6 years ago

elliotdickison commented 6 years ago

Using Elm 0.18.0:

If you compile with --debug then Elm.Main.embed(targetElement) appends your program to targetElement. If you compile without --debug then embed replaces the entire contents of the target element. This nuanced change in behavior can be frustrating if you're following standard SPA best-practices and putting pre-JS placeholder content in the target element (example below). I'm not sure which behavior is correct (I prefer "replace" over "append", again see below) but I think that the behavior should at least be consistent.

Example

You might send your initial html down the pipe with a loading spinner in the target element to indicate to the user that the app is loading:

<div id="main">
    <span class="loading">Loading...</span>
</div>
<script src="elm.js"></script>

Once elm.js is fetched, parsed, and executed you can then replace the loading spinner with your Elm app:

// elm.js
Elm.Main.embed(document.getElementById("main"))

Without debug mode this works as expected, "Loading..." is shown until your Elm app is ready at which point the contents of #main is replaced with your app:

<div id="main">
   (elm app here)
</div>
<script src="elm.js"></script>

However, if you compile with --debug then your app stacks up below the existing content in #main (along with the elm debug controls):

<div id="main">
    <span class="loading">Loading...</span>
    (elm app here)
    <div class="elm-overlay">(elm debug controls here)</div>
</div>
<script src="elm.js"></script>
process-bot commented 6 years ago

Thanks for the issue! Make sure it satisfies this checklist. My human colleagues will appreciate it!

Here is what to expect next, and if anyone wants to comment, keep these things in mind.

elliotdickison commented 6 years ago

Apologies if this is the wrong repo to open this issue on, I just put it here because this seems like something that should be rolled up into #98 .

rtfeldman commented 6 years ago

Is this still reproducible in Elm 0.19?

elliotdickison commented 6 years ago

Seems to be fixed! Although the behavior is still note quite what I would expect. Now calling Elm.Main.init replaces the element entirely (not just its children) regardless of whether you are in debug mode or not. The solves the issue I outlined above, but introduces some other potential problems. For example I tried to embed an Elm app in a <section /> tag with an id attribute and a data-my-custom-attribute, and Elm.Main.init blew away the section tag and its attributes and replaced it with a <div />. I can see why this might be necessary for Elm to own the DOM entirely, but I don't see it documented anywhere and it could make it a little tricky for users trying to embed mini Elm apps within a larger html page.

Anyway, I'll close this issue since 0.19 does fix it. Thanks!