module MountableProgram exposing (Mountable, Msg, mountableProgram) import Html exposing (Html, program) import Html.Events exposing (on) import Json.Decode as Decode type alias Mountable a = { model : a , isMounted : Bool } type Msg msg = Unmounted | AppMsg msg mountableProgram : { init : ( model, Cmd msg ) , update : msg -> model -> ( model, Cmd msg ) , view : model -> Html msg , subscriptions : model -> Sub msg } -> Program Never (Mountable model) (Msg msg) mountableProgram stuff = let init = let ( model, cmd ) = stuff.init in ( { model = model, isMounted = True }, Cmd.map AppMsg cmd ) update msg model = case msg of Unmounted -> Debug.log "unmounted" { model | isMounted = False } ! [] AppMsg msg -> let ( newModel, cmd ) = stuff.update msg model.model in ( { model = newModel, isMounted = model.isMounted }, Cmd.map AppMsg cmd ) view model = Html.section [] [ Html.node "mountable-watcher" [ on "unmounted" (Decode.succeed Unmounted) ] [], Html.map AppMsg (stuff.view model.model) ] subscriptions model = Sub.batch [ if model.isMounted then Sub.map AppMsg (stuff.subscriptions model.model) else Sub.none ] in program { init = init , update = update , view = view , subscriptions = subscriptions }