I have a JavaScript file that embeds a Elm application, and I would like run some JavaScript code after the first rendering of the Elm application. Here’s what I have so far:
var app = Elm.Page.Gadget.embed(content, flags);
window.setTimeout(function() {
...
});
Is that the way to do it? From what I’m seeing, it appears that the code inside the setTimeout function is not executed strictly after the Elm app has rendered itself.
Check out the elm-lang/animation-frame package. You can use the times function to setup a subscription on the initial render (based on a boolean flag in your model, something like isFirstRender) and you will get a message after the view is rendered. Then use a port to run your Javascript code.
Another alternative that doesn’t depend on the sequencing guarantees made or more often not made by Elm’s libraries — for example, animation-frame says that it generates messages in lockstep with the browser rendering but does not say whether your app will get to process the message before or after the corresponding render — is to do all of this in JavaScript. There are a variety of ways from JavaScript, some more skanky but possibly more performant than others, of watching for when DOM elements are created and triggering code. So, if you can set up something that watches for when your root element is created, you have your hook. Whether you want to deal with Elm sequencing ambiguity or what can feel like hacks in JavaScript is a call you need to make.
Mark
P.S. This is what I use. It feels super skanky since it triggers off of CSS animations but it works. It would be nice to know that such tricks aren’t needed in 2018 (this was written in 2012), but I haven’t see a reference to a definitive, performant method of catching DOM node creation in modern browsers. https://davidwalsh.name/detect-node-insertion