Embedding Elm App in Page

In this post, we will take a look at how to embed an Elm application into any page. This way we can improve existing pages with Elm apps without rewriting them completely. It also allows us to use additional assets on a page, such as custom CSS styles and JavaScript libraries.

So far, we’ve been using elm-reactor to build and run our app. This is a great way to quickly start developing in Elm, but it has its own limitations. The page that hosts our Elm application is generated by elm-reactor, so we don’t control it. For example, we cannot add our CSS file to style our components.

To get a full control over the application, we need to embed our Elm application into an HTML file.

The source code for this post is available in the 04-embedding-elm-in-html folder in the elm-proofreading repository.

Creating HTML to Host Elm App

We’ll start by creating a simple HTML page that will host our application. I’ve created index.html file with the following content:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>Elm App Embedding Demo</title>
</head>

<body>
    <div id="app"></div>
</body>

</html>

It’s a simple HTML document with a div element with the app id. We will use this div to embed our application.

Building Elm App with elm-make

It’s time to build our application. We write the app in Elm language, and later it got compiled into JavaScript. Previously elm-reactor did this for us under the hood. This time we will use elm-make for this.

To build the application you need to navigate to the folder with the source code and call elm-make from the console:

elm-make Main.elm --output main.js

This command tells elm-make to compile the Main.elm file and all its dependencies and save the final build into the main.js file.

This main.js file contains required Elm framework pieces, additional packages that we used, and the code of the application. It’s everything we need to run our application.

Note 1: For the first run elm-make would ask to download packages that are needed for your application. They will be downloaded and saved into the elm-stuff folder.

Note 2: If you’ll run elm-make Main.elm, without passing the --output main.js parameter, the result will be an index.html file. It will contain the basic HTML code and all the JavaScript code for the application in it. While it makes easier to start working with your app, I recommend dividing HTML and JavaScript parts into separate files.

Embedding Elm App in HTML

All we need to do is to include our compiled file in the HTML file and embed our app. Here’s the code for that:

<body>
    <div id="app"></div>

    <script src="main.js"></script>
    <script>
        var node = document.getElementById("app");
        var app = Elm.Main.embed(node);
    </script>
</body>

We added script tag with our main.js file, and added script to embed our app into the div with app id.

If we open index.html (we can still use elm-reactor as a local server), we’ll see our app. It looks the same as when running it directly from the elm-reactor.

The last step for today would be to add some styles to our app.

Applying CSS to Elm App

Now let’s add some styling to our application. I’ve created the main.css file that will contain all the styles for the app. Adding it to HTML is straightforward:

<head>
    ...
    <link rel="stylesheet" href="main.css">
    ...
</head>

And here’s the code for the view function that applies CSS classes to elements. Note the class attributes passed to textarea and div functions.

view : Model -> Html.Html Msg
view model =
    div []
        [ textarea [ onInput SetText, value model.text, class "text-editor" ] []
        , div
            [ class "proofread-panel" ]
            [ text model.text ]
        ]

Compiling our Elm code to JavaScript and embedding it into the HTML document gives us flexibility. We can reuse existing HTML files, add CSS files, mix Elm and JavaScript components on a single page.

Getting and Showing Text in Elm
Calling Web Service in Elm