ryannhg/elm-spa/4.1.0

NOTE: the latest version is 6.0.0

Renamed to ryan-haskell/elm-spa. It is published under that name, and new versions come out there.

Versions published as ryannhg/elm-spa still install under that name. 13 versions of 13 come from the new location (see their notes).

Rerouted (renamed, verified). The GitHub user or repository was renamed. The tag is still there, at the new name. The Lamdera package server serves a copy recovered from https://github.com/ryan-haskell/elm-spa.

What we checked: The repo moved to github.com/ryan-haskell/elm-spa. Rebuilt with git archive from commit 0e39d0375e33 of https://github.com/ryan-haskell/elm-spa (zip prefix ryannhg-elm-spa-7424f50/, America/Los_Angeles times): the zip is byte-identical to the one package.elm-lang.org recorded, SHA-1 089cd4d51e82160fd9c89219a7a6003338bcee3d.

The Lamdera compiler uses this copy and prints a one-line notice saying so. elm itself fails to download this version.

Details · package.elm-lang.org's zip: https://github.com/ryannhg/elm-spa/zipball/4.1.0/

Spa.Advanced

prefer elm-ui?

If you'd rather use something like elm-ui or have your page's view functions return something besides Html, this module extends the Spa.Page module's API with one additional parameter.

type alias Page flags model msg globalModel globalMsg view_msg =
{ init : globalModel -> flags -> ( model, Cmd msg, Cmd globalMsg )
, update :
globalModel -> msg -> model -> ( model, Cmd msg, Cmd globalMsg )
, view : globalModel -> model -> view_msg
, subscriptions : globalModel -> model -> Sub msg
}

Just like Spa.Page, but the view function returns view_msg instead of enforcing the use of Browser.Document msg

avoid doing this

Instead of having all the pages in your app specify all 6 parameters every time:

import Browser exposing (Document)
import Global
import Spa


page : Spa.Page Flags Model Msg Global.Model Global.Msg (Document Msg)
page =
    Spa.static
        { view = view
        }

try this instead!

It's recommended to create a single src/Page.elm file for your project, just like the one created by elm-spa init.

The Page module exposes type aliases and functions that know which Global.Model and Global.Msg to use, which allow the compiler to provide better error messages.

Additionally, it make your type annotations way easier to read!

import Page exposing (Document, Page)


page : Page Flags Model Msg
page =
    Page.static
        { view = view
        }

(If you're doing things correctly you should only see import Spa or import Spa.Advanced once in your entire project!)

compatible with the cli tool!

Using the technique describe above means the cli tool will be able to work

These links are full src/Page.elm implementations you can drop into your app:

static pages

{ view : view_msg }
-> Page flags () msg globalModel globalMsg view_msg
import Page exposing (Page)


page : Page Flags Model Msg
page =
    Page.static
        { view = view
        }

sandbox pages

{ init : model
, update : msg -> model -> model
, view : model -> view_msg
}
-> Page flags model msg globalModel globalMsg view_msg
import Page exposing (Page)


page : Page Flags Model Msg
page =
    Page.sandbox
        { init = init
        , update = update
        , view = view
        }

element pages

{ init : flags -> ( model, Cmd msg )
, update : msg -> model -> ( model, Cmd msg )
, view : model -> view_msg
, subscriptions : model -> Sub msg
}
-> Page flags model msg globalModel globalMsg view_msg
import Page exposing (Page)


page : Page Flags Model Msg
page =
    Page.element
        { init = init
        , update = update
        , subscriptions = subscriptions
        , view = view
        }

component pages

{ init : globalModel -> flags -> ( model, Cmd msg, Cmd globalMsg )
, update :
globalModel -> msg -> model -> ( model, Cmd msg, Cmd globalMsg )
, view : globalModel -> model -> view_msg
, subscriptions : globalModel -> model -> Sub msg
}
-> Page flags model msg globalModel globalMsg view_msg
import Page exposing (Page)


page : Page Flags Model Msg
page =
    Page.component
        { init = init
        , update = update
        , subscriptions = subscriptions
        , view = view
        }

upgrading pages

The Page module discussed above should also export an upgrade function. This means providing an extra function to map one view to another.

an example with elm/browser

import Browser
import Html


type alias Document msg =
    Browser.Document msg


upgrade =
    Spa.Advanced.upgrade
        (\fn doc ->
            { title = doc.title
            , body = List.map (Html.map fn) doc.body
            }
        )

an example with mdgriffith/elm-ui

import Element exposing (Element)


type alias Document msg =
    { title : String
    , body : List (Element msg)
    }


upgrade =
    Spa.Advanced.upgrade
        (\fn doc ->
            { title = doc.title
            , body = List.map (Element.map fn) doc.body
            }
        )
((pageMsg -> msg) -> view_pageMsg -> view_msg)
-> (pageModel -> model)
-> (pageMsg -> msg)
-> Page
pageFlags
pageModel
pageMsg
globalModel
globalMsg
view_pageMsg
-> { init :
pageFlags -> globalModel -> ( model, Cmd msg, Cmd globalMsg )
, update :
pageMsg
-> pageModel
-> globalModel
-> ( model, Cmd msg, Cmd globalMsg )
, bundle : pageModel -> globalModel -> Bundle msg view_msg
}

Same as Spa.upgrade, but needs an extra map function as the first argument to upgrade one view to another!

type alias Bundle msg view_msg =
{ view : view_msg
, subscriptions : Sub msg
}

Bundle behaves the same as Spa.Bundle, but supports more than just Browser.Document msg for the view's return type!