3

Hot on the heels of my previous question the example I am working on in "Elm in Action" (and trying to port to Fable-Elmish) has a custom event from a custom element. In the html file I have the following:

<link rel="stylesheet" href="http://elm-in-action.com/range-slider.css">
<script src="http://elm-in-action.com/range-slider.js"></script>
<script>
  class RangeSlider extends HTMLElement {
    connectedCallback() {
      var input = document.createElement("input");
      this.appendChild(input);

      var jsr = new JSR(input, {
        max: this.max,
        values: [this.val],
        sliders: 1,
        grid: false
      });

      var rangeSliderNode = this;

      jsr.addEventListener("update", function(elem, value) {
        var event = new CustomEvent("slide", {
          detail: {userSlidTo: value}
        });

        rangeSliderNode.dispatchEvent(event);
      });
    }
  }

  window.customElements.define("range-slider", RangeSlider);
</script>

In the example in the book (in Elm, of course) the first step in receiving the events is to do something like the following:

onSlide : (Int -> msg) -> Attribute msg
onSlide toMsg =
  let
    detailUserSlidTo : Decoder Int
    detailUserSlidTo =
        at [ "detail", "userSlidTo" ] int

    msgDecoder : Decoder msg
    msgDecoder =
        Json.Decode.map toMsg detailUserSlidTo
in
    on "slide" msgDecoder

which can be simplified to:

onSlide : (Int -> msg) -> Attribute msg
onSlide toMsg =
  at [ "detail", "userSlidTo" ] int
    |> Json.Decode.map toMsg
    |> on "slide"

In Elmish, however, there is no equivalent that I can find to on. I have come up with:

let onSlide (toMsg: int -> Msg) =
  Decode.at ["detail", userSlidTo"] Decode.int
  |> Decode.map toMsg
  |> ... // Now what!?

I have looked through the sources in everything I can think of that might apply but can't find a way to listen to custom events. And, again, the documentation doesn't provide any examples or explanations of how to do this that I have found.

There has to be a way to connect to custom events in Elmish, but I just can't find it anywhere. Is the approach to doing the same thing is different in the two environments?

Community
  • 1
  • 1
melston
  • 2,198
  • 22
  • 39

1 Answers1

2

So, to answer my own question, it appears that Elmish doesn't work the same way that Elm does in this case. The mechanism would appear to be to set up a subscription in Elmish something along the lines of:

let sliderSub  (initial: model) =
    let sub dispatch =
        window.addEventListener ("slide, fun evt ->
            let detail = <decode event details>
            match detail with
            | Ok slidEvt -> <dispatch a Cmd based on the details>
            | _ -> ()
        )
    Cmd.ofSub sub

Program.mkProgram init update view
|> Program.withSubscription sliderSub
...

I haven't gotten this to work yet as there are other issues still to be dealt with but this appears to be the approach needed in Elmish.

melston
  • 2,198
  • 22
  • 39