adamstuller / elm-spa-composition / Alt

Elegant elm single pages composition. Aims at removing boilerplate code generated as byproduct of pages composition in SPAs.

Helper types


type alias Subscription model msg =
model -> Platform.Sub.Sub msg

Subscription function type


type alias Update model msg =
msg -> model -> ( model
, Platform.Cmd.Cmd msg 
}

Update function type


type alias View model msg =
model -> Html msg

View function type


type alias Both a b =
( a, b )

Simple type used for better readability of tuple

Both a b == ( a, b )


type alias Flags =
Json.Decode.Value

Flags type. Should be as much generic as possible so anything can be passed by it and each modules parses the flags alone.


type alias Params =
{ flags : Flags
, url : Url
, urlParams : List String
, key : Browser.Navigation.Key 
}

Params is record that router passes to each Page on initialization.

Url parsing


type alias RouteParser =
Url.Parser.Parser (List String -> List String) (List String)

Parses url and returns list of strings. This is again the most generic approach. In every Page, parser can be defined and exposed along with the function to transform list of strings to required data type.

basicParser : String -> Url.Parser.Parser (List String -> List String) (List String)

Predefined function that takes one string and returns parser that parses this one path and returns empty list.

topParser : Url.Parser.Parser (List String -> List String) (List String)

Predefined parser that parses "/" path and returns empty list.

Composition


type alias PageWidget model msg params =
{ init : Both (params -> ( model
, Platform.Cmd.Cmd msg )) RouteParser
, view : View model msg
, update : Update model msg
, subscriptions : Subscription model msg 
}

Type for widet that represents page. Contains all basic elm architecture functions that need to be implemented in respective page modules.


type alias PageWidgetComposition model msg path params =
{ init : ( path -> params -> ( model
, Platform.Cmd.Cmd msg )
, List.Nonempty.Nonempty path
, List.Nonempty.Nonempty RouteParser )
, view : View model msg
, update : Update model msg
, subscriptions : Subscription model msg 
}

Page composition in progress. Is created by join function.

join : PageWidget model1 msg1 params -> PageWidget model2 msg2 params -> PageWidgetComposition (Either model1 model2) (Either msg1 msg2) (Either () ()) params

Combines first two pages and creates PageWidgetComposition. Is followed by add function.

add : PageWidgetComposition model1 msg1 path params -> PageWidget model2 msg2 params -> PageWidgetComposition (Either model1 model2) (Either msg1 msg2) (Either path ()) params

Adds another PageWidget to PageWidgetComposition.

Header and footer


type alias Header msg =
WindowState -> msg -> Url -> Html msg

Header type. Function that returns view of header.


type alias Footer msg =
Html msg

Footer type. Just view displayed on the bottom of the application.

emptyHeader : WindowState -> msg -> Url -> Html msg

Simplest empty header

emptyFooter : Footer Msg

Simplest empty footer


type alias WindowState =
{ window : Window
, expanded : Basics.Bool 
}

State that navbar expects. When implementing custom navbar, this state can be accessed. Contains window to determine the shape of navbar and information whether it is collapsed or not.

Router

initRouter : String -> Header Msg -> Footer Msg -> PageWidgetComposition model msg path Params -> ApplicationWithRouter (Both model Model) (Either msg Msg) Flags

This function takes PageWidgetComposition and another information about aplications. It attaches router to composition and creates suitable output for application.