ryan-haskell/elm-spa/1.0.0

Formerly ryannhg/elm-spa. Search finds this package by either name.

ElmSpa.Page

Pages

type Page shared route effect view model msg

Pages are the building blocks of elm-spa.

Instead of importing this module, your project will have a Page module with a much simpler type:

module Page exposing (Page, ...)


type Page model msg

This makes all the generic route, effect, and view arguments disappear!

static : effect -> { view : view } -> Page shared route effect view () msg

A page that only needs to render a static view.

import Page


page : Page () Never
page =
    Page.static
        { view = view
        }


-- view : View Never
effect
-> { init : model
, update : msg -> model -> model
, view : model -> view
}
-> Page shared route effect view model msg

A page that can keep track of application state.

( Inspired by Browser.sandbox )

import Page


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


-- init : Model
-- update : Msg -> Model -> Model
-- view : Model -> View Msg
(Cmd msg -> effect)
-> { init : ( model, Cmd msg )
, update : msg -> model -> ( model, Cmd msg )
, view : model -> view
, subscriptions : model -> Sub msg
}
-> Page shared route effect view model msg

A page that can handle effects like HTTP requests or subscriptions.

( Inspired by Browser.element )

import Page


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


-- init : ( Model, Cmd Msg )
-- update : Msg -> Model -> ( Model, Cmd Msg )
-- view : Model -> View Msg
-- subscriptions : Model -> Sub Msg
{ init : ( model, effect )
, update : msg -> model -> ( model, effect )
, view : model -> view
, subscriptions : model -> Sub msg
}
-> Page shared route effect view model msg

A page that can handles custom effects like sending a Shared.Msg or other general user-defined effects.

import Effect
import Page


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


-- init : ( Model, Effect Msg )
-- update : Msg -> Model -> ( Model, Effect Msg )
-- view : Model -> View Msg
-- subscriptions : Model -> Sub Msg

User Authentication

type Protected user route
= Provide user
| RedirectTo route

Actions to take when a user visits a protected page

import Gen.Route as Route exposing (Route)


beforeProtectedInit : Shared.Model -> Request () -> Protected User Route
beforeProtectedInit shared _ =
    case shared.user of
        Just user ->
            Provide user


        Nothing ->
            RedirectTo Route.SignIn
{ effectNone : effect
, fromCmd : Cmd msg -> effect
, beforeInit : shared -> Request route () -> Protected user route
}
-> { static :
(user -> { view : view }) -> Page shared route effect view () msg
, sandbox :
( user
-> { init : model
, update : msg -> model -> model
, view : model -> view
}
)
-> Page shared route effect view model msg
, element :
( user
-> { init : ( model, Cmd msg )
, update : msg -> model -> ( model, Cmd msg )
, view : model -> view
, subscriptions : model -> Sub msg
}
)
-> Page shared route effect view model msg
, advanced :
( user
-> { init : ( model, effect )
, update : msg -> model -> ( model, effect )
, view : model -> view
, subscriptions : model -> Sub msg
}
)
-> Page shared route effect view model msg
}

Prefixing any of the four functions above with protected will guarantee that the page has access to a user. Here's an example with sandbox:

-- before
Page.sandbox
    { init = init
    , update = update
    , view = view
    }


-- after
Page.protected.sandbox
    (\user ->
        { init = init
        , update = update
        , view = view
        }
    )


-- other functions have same API
init : Model
update : Msg -> Model -> Model
view : Model -> View Msg

For generated code

type alias Bundle params model msg shared effect pagesModel pagesMsg pagesView =
{ init : params -> shared -> Url -> Key -> ( pagesModel, effect )
, update :
params -> msg -> model -> shared -> Url -> Key -> ( pagesModel, effect )
, view : params -> model -> shared -> Url -> Key -> pagesView
, subscriptions : params -> model -> shared -> Url -> Key -> Sub pagesMsg
}

A convenient function for use within generated code. Makes it easy to handle init, update, view, and subscriptions for each page!

{ redirecting :
{ model : pagesModel
, view : pagesView
}
, toRoute : Url -> route
, toUrl : route -> String
, fromCmd : Cmd any -> pagesEffect
, mapEffect : effect -> pagesEffect
, mapView : view -> pagesView
, page :
shared
-> Request route params
-> Page shared route effect view model msg
, toModel : params -> model -> pagesModel
, toMsg : msg -> pagesMsg
}
-> Bundle
params
model
msg
shared
pagesEffect
pagesModel
pagesMsg
pagesView

This function is used by the generated code to connect your pages together.

It's big, spooky, and makes writing elm-spa pages really nice!