I'm trying with the Html.App.beginnerProgram
and I want to add event handlers (onKeyDown
, etc.) to the <body>
element.
Unfortunately everything I put in view
becomes the children of <body>
. Returning Html.body
from view
doesn't do the trick. This code:
main = beginnerProgram { model = 0, view = view, update = update }
view model = body [] []
update _ model = model
will generate:
<html>
<head>...</head>
<body>
<body></body>
</body>
</html>
So, how do I get the control of the <body>
element?
Since Elm renders as a descendant of <body/>
, you cannot bind event handling to it in the normal Elm way (e.g. button [ onClick SomeMsg ] []
). Instead you'll have to use ports. And because you're using ports and subscriptions, you will need to use Html.App.program
rather than beginnerProgram
.
You'll need a port function inside your port module:
port bodyKeyPress : (String -> msg) -> Sub msg
And then you'll be able to send key presses to that port from javascript:
app.ports.bodyKeyPress.send(...);
Here's a full example:
port module Main exposing (main)
import Html.App as App
import Html exposing (..)
main = App.program
{ init = init
, update = update
, view = view
, subscriptions = subscriptions
}
type alias Model = { message : String }
type Msg = BodyKeyPress String
init = { message = "Press some keys: " } ! []
update msg model =
case msg of
BodyKeyPress c ->
{ model | message = model.message ++ c } ! []
view model = text model.message
subscriptions _ =
bodyKeyPress BodyKeyPress
port bodyKeyPress : (String -> msg) -> Sub msg
And the html behind the scenes (assuming you built using elm make Main.elm --output=Main.js
):
<html>
<body>
<script src="Main.js"></script>
<script>
var app = Elm.Main.fullscreen();
document.body.onkeypress = function(e) {
app.ports.bodyKeyPress.send(String.fromCharCode(e.keyCode));
};
</script>
</body>
</html>
You will need to create and handle a port function for every body event you want to send.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With