Small post for who wants to use the more advanced functionalities of Startapp. Startapp allows you to hook into the signals of your application, where as Startapp.Simple hides this from you. Below you can find the before and after of Main.elm and after that i talk about the most important changes. Note that this is not the complete Main.elm but just the parts that changed.

Before

import StartApp.Simple exposing (start)

main =
  start
    { model = initModel
    , update = update
    , view = view
    }

After

import StartApp exposing (start)
import Effects

app = start
        { init = (initModel, Effects.none)
        , update = (\x y -> (update x y, Effects.none))
        , view = view
        , inputs = []
        }

main = app.html

This assumes you use a function called initModel of type initModel : Model. You can also specify your model there literally.

One big change is that the new init function together with the existing update function now also return Effects. I'm not going to cover Effects in this post, but if you need to use them .. now you can.

Another big change is that rather than your start function returning back the Html directly (which feeds into your main function), it does now return a record. I'm not sure why it's called model in the Startapp code because it's actually more than your model and app seems a more appropriate name.

With these changes you now have the abilities to send signals into your application using the inputs and you can get signals from your application using app. The app record only consists out of Signals (html, model and tasks). You can use the app.model signal to respond to changes in your model.

Suppose you don't want to specifically signal on a data change, but on a general event that doesn't actually change your model (this is more like an edge case, but still). You will have to reserve parts in your model to signal this. That means this piece of data will just be used to "forward" the signaling and does not have any direct relevance to your view. If you want to have either greater control over your signals you've pretty much reached the limits of Startapp and you are probably ready to design your app as you want from the ground up. Both Startapp and Startapp.Simple are not that many lines of codes so this is not a lot of work.

Let's say you do want to listen to some specific data. And your model is:

model =
  { levelOne =
    { levelTwo =
      { fieldOne = "hello"
      , fieldTwo = "world"
      }
    }
  }

Now to listen to a change in fieldTwo you would write

Signal.map (.levelOne >> .levelTwo >> fieldTwo) app.model

Where .levelOne is short for (\m -> m.levelOne) and >> is a shorthand notation to chain function calls.

This will respond to ANY change in this particular piece of data. If you want your signal to activate on a certain value then use Signal.filter instead.