elm-rails icon indicating copy to clipboard operation
elm-rails copied to clipboard

Working with Turbolinks

Open ghivert opened this issue 8 years ago • 3 comments

Hello !

I'm trying to use elm-rails to render elm on a rails server using turbolinks. However, turbolinks badly handle elm-embed tags. On first load, the javascript is correctly loaded, but if I load the page through turbolinks, the javascript is not executed (and it's rather bad because all HTML is written in Elm).

Any idea to fix this ?

ghivert avatar Apr 18 '17 15:04 ghivert

I think, when using turbolinks, rather then adding an event listener for DOMContentLoaded , you have to use the events provided by turbolinks (here is a list). So the js loading your elm app should look sth like this:

document.addEventListener('turbolinks:load', () => {
  const node = document.getElementById('elm-container');

  Elm.Main.embed(node);
});

You still could run into the problem that your elm app is loaded several times on revisits to the page containing this javascript. (Not on hard reloads using the browser.)

kirchner avatar Jul 13 '17 07:07 kirchner

@kirchner Are there suggestions on how to avoid the problem of the Elm app loading several times? I've tried the following approach but I'm wondering whether there are saner solutions:

document.addEventListener('turbolinks:load', () => {

  // Only load if Elm hasn't previously loaded
  if (document.getElementsByClassName('elm-already-run').length == 0) {

    // Use global state to mark as already having run-- eww!
    let marker = document.createElement('div');
    marker.className = 'elm-already-run';
    document.body.appendChild(marker);
    
    const node = document.getElementById('elm-container');
    Elm.Main.embed(node);
  }
})

aaronshim avatar Aug 25 '17 17:08 aaronshim

@aaronshim we ended up doing sth like this

// app/javascript/packs/elm_app.js

import Elm from ‘ElmApp/Main’

$(“#elm-container”).empty();

const container = $(“#elm-container”)
const flags = JSON.parse($(“#elm-flags”).data(“data-flags”))

var app = Elm.ElmApp.Main.embed(container, flags)

where the html template looks like this

// app/views/foos/show.html.slim

#elm-container
#elm-flags([email protected]_json)

= javascript_pack_tag “elm_app”

probably not so much better i think =)

kirchner avatar Aug 25 '17 17:08 kirchner