Moving out of the sandbox
Up until now we have been relying on Elm's sandbox. The sandbox allows for a user to interact with the component in a limited way. For example, it is not possible to make an HTTP call.
We would like to do just that, so it is time to move out of the sandbox.
Browser.element
The next step up on the Elm ladder is Browser.element
. From the
element documentation we learn
Unlike a sandbox, an element can talk to the outside world in a couple ways
We will give a brief description of those ways, paying attention which are relevant for us.
Commands
Commands are a way to request the Elm runtime to do a task. Making an HTTP call is an example.
Commands are a way to describe a certain action. This keeps your program pure, i.e. function always return the same value when called with similar arguments. The Elm runtime will respond by performing the command you specified.
The Elm runtime notifies you of the result by calling the update function.
Subscriptions
Sometimes you are interested in something your component is not responsible for. E.g. ticking of time, or mouse clicks. If you are interested in these things you can subscribe to these events.
Again, Elm runtime notifies you of an event from a subscription by calling the update function.
Flags
Let's we are creating our app and our customers want there name embossed on the flash card. The functionality would not change, besides that our model would keep track of the customer name.
One way to configure our application is by sending flags. This allows an application to change behavior right from the start. E.g. one could pass in via a flag the address one should retrieve flash cards from.
Ports
If you want even more communications with the outside world, ports allow you to send and receive messages. They are the defacto way of communicating with anything outside the control of the Elm runtime.
For example if you want to make use of a JavaScript library that does not have an native Elm counterpart one should use ports to establish a bridge
Updating update
The update
function needs to be updated because it needs to be able to fire of
commands. This dual responsibility is reflected in the signature. For
completeness we show the current signature.
update : Message -> Model -> Model
Besides updating the model, We could potentially also create a command, to be executed by the Elm runtime. The new signature is
update : Message -> Model -> ( Model, Cmd Message )
This will break the implementation. For now it is enough to create a tuple with
as second component Cmd.none
.
Flip ->
( Maybe.map flip model, Cmd.none )
Default subscriptions
At the moment we don't want to subscribe to anything. We can tell Elm that by
configuring Sub.none
, similar to Cmd.none
.
In order to prepare for future extension we will be creating a subscriptions
definition that we will reference when we are creating a Browser.element
.
subscriptions : Model -> Sub Message
subscriptions _ =
Sub.none
Updating init
When we will introduce a Browser.element
our current init
field from the
Browser.sandbox
does not suffice anymore. Again. We could kick off our entire
process by doing a request. Furthermore, our initial model could depend on some
flags.
For now we want to ignore the flags, and don't want to send a command. It suffices to change our init to.
init = \_ -> ( model, Cmd.none )
Replace Browser.sandbox
with Browser.element
Now we can replace Browser.sandbox
with Browser.element
. It will still
complain, because it is missing a subscriptions
field. But we prepared for
that.
All in all our program definition looks like
Browser.element
{ init = \_ -> ( Nothing, cmd )
, view = view
, update = update
, subscriptions = subscriptions
}
Verification
Building the app and opening the application would still allow you to learn the
translation of Wettervorhersage
.