elm-mdl
elm-mdl copied to clipboard
Trouble embedding elm-mdl section into existing MDL page
I've got an existing MDL-based page (i.e. not using elm), and I'd like to embed an elm-mdl element into it. But if I follow the standard approach for embedding elm code into HTML - create a div, include the compiled js, and attach to the div - something seems to go wrong with my event processing. I wish I could describe it more concretely, but what I see is this:
- I know a click handler is functioning properly, because I see the subsequent network traffic it produces
- The subsequent processing of events caused by the receipt of HTTP responses is broken, at least insofar as I don't see the new elements I should see created in the page.
- In the dev console I see this message repeated a lot:
Uncaught TypeError: Cannot read property 'childNodes' of undefined
(this seems like a big clue, but only for someone who knows elm's internals better than me.)
I assume that I've either a) missed a step in wiring things up or b) this is not supported right now.
So, is this supported? If so, is there a demo or some documentation showing how to do it properly? I've done some searching but haven't turned anything up.
FWIW, I have an "all elm" version of the page that works just fine, so I'm pretty confident that the problem lies in how I'm embedding elm-mdl-based stuff into HTML.
Could it be that material.js is trying to seize control of your elm-mdl elements? Elements created by elm-mdl have the appropriate classes that material.js could target them to initialize components. So, if material.js is executed after first render, that could be your problem.
The <script>
call for material.js is almost the first thing in my HTML, while I don't pull in the compiled elm until the end. I'm no great expert in these things (e.g. I don't know what leeway browsers have for reordering things or whatever), but this seems like it ought to finish executing material.js before the elm code is in the picture.
Is there anyway you know that I could test this?
As long as you are not specifying async
or defer
on the material.js' script
tag, the browser should execute it in the order given.
You could further test it, by wrapping your call to Elm.embed
in a timeout, say 5 seconds, so that you are sure material.js has finished initializing, ie.
setTimeout(function() {
// call Elm.embed here
}, 5000);
Thanks! I'm travelling right now, so I'll try this on Monday.
More fundamentally, though: should I expect this to work? Is it a supported or anticipated use case for elm-mdl? I don't want to waste anyone's time on it if it's just not allowed.
I think we will want to support it in the future, because I am not seeing any reason why we wouldn't. My understanding is that as long as we set data-upgraded
on elm-mdl components, material.js will not touch them.
As of now, I do not know whether we are setting data-upgraded
on all elm-mdl components that would require it. As, besides this particular use case, data-upgraded
is unnecessary, it could easily be the case that it is missing in some components or in some configurations of components.
I've finally had some time to look into this. It appears that you're correct: if I add a 5 second delay around the embed call, then everything appears to work as normal. In fact, if I add a 0 second delay around the embed call, it works. So there's some bad interaction between MDL loading and embedding.
For my part, the zero-second delay is sufficient to let me continue. But it feels a bit unsatisfactory from the elm-mdl point of view. Should I keep this issue open so that the project remembers to look into it, or would you prefer that I close it?
This can stay open. This should should be investigated if it is possible to resolve this issue by attaching the data-upgraded
attribute to elm-mdl components as @aforemny suggested.
Agree with @vipentti.