I would like to integrate Elm with a Javascript library in such a way that Elm would dynamically create \"cells\" (html divs), and Javascript would be provided with their id
This seems to currently be the cleanest solution in my experience.
var container = document.getElementById('app');
var demoApp = Elm.RenderDemo.embed(container);
var requestAnimationFrame =
window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame; //Cross browser support
var myPerfectlyTimedFunc = function(cellID) {
requestAnimationFrame(function() {
if(document.getElementById('cell:' + cellID) === null) {
window.alert("Cannot find cell " + cellID)
}
})
}
demoApp.ports.onCellAdded.subscribe(myPerfectlyTimedFunc);
See here for an SPA type setup with multiple pages and the need to re-render a JS interop'd graph. Also has the ability to update the data value within the graph. (The console log messages may instructive as well.)
If one is curious how this might be implemented on the Elm side instead of html/js side, see Elm Defer Command library.
As you described, the problem is:
Elm uses requestAnimationFrame (rAF) itself as a way to queue DOM renders, and for good reason. Say Elm makes several DOM manipulations in less than 1/60th of a second, instead of rendering each manipulation individually - which would be quite inefficient - Elm will pass them to the browser's rAF, which will act as a buffer/queue for overall DOM rendering. In other words, view is called on the animation frame after update, so a view call won't always happen after each update.
In the past people would use :
setInterval(someAnimationFunc, 16.6) //16.6ms for 60fps
requestAnimationFrame came about as a way for the browser to keep a queue, which it manages and cycles through at 60fps. This offer a number of improvements:
More info on rAF here, and here, and a video by Google here
My personal story started when I tried to render a Chartist.js graph into a div initially created within Elm. I also wanted to have multiple pages (SPA style) and the chart would need to re-render when the div element was recreated on various page changes.
I wrote the div as straight HTML in the index, but this prevented the SPA functionality I desired. I also used ports and subscriptions with JQuery ala $(window).load(tellElmToReRender), as well as giving Arrive.js a go - but each of these resulted in various bugs and lack of desired functionality. I messed with rAF a bit, but was using it in the wrong place and wrong way. It was after listening to ElmTown - Episode 4 - JS Interop, where I an epiphany hit and realized how it should really be used.