Pierre Carbonnelle
Pierre Carbonnelle

Reputation: 2625

how to divide a large Elm program into smaller components

I'd like to separate the View and Update parts of a program into separate source files, but then, how do I share the Message and Subscriptions declarations ?

Upvotes: 5

Views: 2578

Answers (2)

halfzebra
halfzebra

Reputation: 6807

Think twice before splitting your modules, premature code splitting might be harmful to your project.

Here is an example of the project structure I use in my Elm apps.

Messages

Html.App.map allows us to tag a message for child component, so we could pass it to Components.Counter.Update.update function, when keyboard subscription emits a message.

module App.View exposing (..)

import Html.App
import Html exposing (text, div, Html)
import App.Model exposing (Model)
import App.Messages exposing (..)
import Components.Counter.View


view : Model -> Html Msg
view model =
    div []
        [ Html.App.map Counter (Components.Counter.View.view model.counter) ]

Subscriptions

To tag a message from a subscription, we have to use Platform.Sub.map

Please see an example of subscription passing in src/App/Subscriptions.elm

module App.Subscriptions exposing (..)

import App.Model exposing (Model)
import App.Messages exposing (..)
import Components.Counter.Subscriptions


subscriptions : Model -> Sub Msg
subscriptions model =
    let
        counterSub =
            Components.Counter.Subscriptions.subscriptions model.counter
    in
        Sub.batch [ Sub.map Counter counterSub ]

File structure

Main.elm                 -- Entry point, where App is initialized
Utils.elm                -- Utilities
App/
    Messages.elm
    Model.elm
    Subscriptions.elm
    Update.elm
    View.elm
Components/
    StatefulComponent/
        Messages.elm
        Model.elm
        Subscriptions.elm
        Update.elm
        View.elm
    StatefulComponentWithCommands/
        Commands.elm     -- Functions, which return Cmd msg
        Messages.elm
        Model.elm
        Subscriptions.elm
        Update.elm
        View.elm
    StatelessComponent/
        View.elm

Upvotes: 9

Pierre Carbonnelle
Pierre Carbonnelle

Reputation: 2625

An Elm program can be progressively split into several files as follows :

  • extract message declarations and associated types into Messages.elm

    1. Add import Messages exposing (..) in Main.elm.
    2. Compile it and test.
  • extract model declaration and initialisation into Models.elm.

    1. Add import Messages exposing (..) in Models.elm.
    2. Add import Models exposing (..) in Main.elm
    3. Compile it and test
  • extract the view function into View.elm.

    1. Add import Messages exposing (..) in View.elm.
    2. Add import Models exposing (..) in View.elm
    3. Add import View exposing (..) in Main.elm
    4. Compile it and test

A the end, Main.elm still has the subscriptions and update parts. They can be extracted similarly.

See example at github.com/sporto/elm-tutorial-app/tree/master/src, with corresponding tutorial at elm-tutorial.org/en/05-resources/01-intro.html.

Upvotes: 1

Related Questions