elm-lang / elm-reactor

Interactive development tool that makes it easy to develop and debug Elm programs.
BSD 3-Clause "New" or "Revised" License
428 stars 63 forks source link

Using the reactor with `programWithFlags` #199

Closed zacclark closed 8 years ago

zacclark commented 8 years ago

If I have a main like the following:

type alias Config =
  { baseUrl : String }

main : Program (Config)
main =
  Html.App.programWithFlags
    { init = init
    , view = view
    , update = update
    , subscriptions = always Sub.none
    }

init : (Config) -> (Model, Cmd Msg)

And I try to access it with elm reactor, there does not appear to be a way to pass the necessary flags to the program, so it crashes on .fullscreen.

The js error is:

Uncaught Error: You are trying to initialize module `Search` with an unexpected argument.
When trying to convert it to a usable Elm value, I run into this problem:

Expecting an object with a field named `baseUrl` but instead got: undefined

I know I could switch to another workflow where I compile my elm app externally and embed it myself, but the auto-rebuild and nicely formatted errors in the browser would be annoying to lose. Is there a different pattern I should be using?

process-bot commented 8 years ago

Thanks for the issue! Make sure it satisfies this checklist. My human colleagues will appreciate it!

Here is what to expect next, and if anyone wants to comment, keep these things in mind.

zacclark commented 8 years ago

Updating with a complete example:

module ExampleReactorFlagsProblem exposing (..)

import Html exposing (div, Html)
import Html.App

type alias Config =
  { baseUrl : String }

type alias Model =
  { config : Config }

type Msg
  = Nothing

main : Program (Config)
main =
  Html.App.programWithFlags
    { init = init
    , view = view
    , update = update
    , subscriptions = always Sub.none
    }

init : Config -> (Model, Cmd Msg)
init config =
  (Model config, Cmd.none)

view : Model -> Html Msg
view _ =
  div [] []

update : Msg -> Model -> (Model, Cmd Msg)
update _ model
  = (model, Cmd.none)

Running that in the reactor will show the problem.

evancz commented 8 years ago

Unfortunately, elm-reactor can't handle that scenario well right now. A revamp of elm-reactor is on the relatively short-term roadmap, so I'll add this to the list of feature requests. That said, using programWithFlags necessarily implies that you'd like to embed it in a custom way, so I'm not sure if it totally aligned with elm-reactor's goals. We'll see when the time comes to work on it!

evancz commented 8 years ago

I think the "compile to JS endpoint" idea in #193 would cover this case, so I added this issue there.

focusaurus commented 7 years ago

Is there any way I can code my application such that Flags is a Maybe or otherwise optional to get elm-reactor compatibility?

update

I was able to make my app work with both program and programWithFlags by defining both an initFlags (used for real deployments) and init (used with elm-reactor).

init: ( Model, Cmd Msg)
init =
  let flags = Flags Nothing Nothing
  in
    initFlags flags

I have to do a small amount of commenting out/in code to switch between the 2 modes, but it's workable.

zacclark commented 7 years ago

@focusaurus I got something working similar to your original idea (making it a Maybe). It didn't need changes between a real embed and the reactor. Unfortunately, I don't remember exactly how I did it, and its in a repo I no longer have access to. But it is 100% possible (at least in 0.17), so at least you know you're not working towards something impossible :)

Sorry I can't remember exactly how I did it.

zeddidragon commented 7 years ago

In the meantime, I use a workaround.

My Main.elm is located at ./src/Main.elm I copied my index.html to ./src/debug.html

The script tag looks like so:

<script type="text/javascript" src="../_compile/src/Main.elm"></script>

The script tag that runs your program looks something like so:

  if(Elm.Main) {
    Elm.Main.fullscreen({your: "flags go here"})
  } else {
    runElmProgram()
  }

Instead of looking at localhost:8000/src/Main.elm, you look at localhost:8000/src/debug.html

jweir commented 7 years ago

What I have been doing is using a separate Reactor.elm file that initializes my model and program with static values in place of flags. This way I can develop with reactor, and and leave the production code in App.elm alone.

example https://gist.github.com/jweir/79af678adf6bce4be3bd91fec2f471fa

radix commented 7 years ago

It'd be really nice if elm reactor took flags on the command line.