Container

With styles in place, let's get our hands on extracting a shared layout for all future views to come. Start by adding container parameter to index in View:

let index container = html [ head [ title "Suave Music Store" cssLink "/Site.css" ]
val index : container:'a -> 'b

Full name: CDocument.index
val container : 'a

and div with id "container" just after the div "header":

body [ divId "header" [ h1 (aHref Path.home (text "F# Suave Music Store")) ] divId "container" container

index previously was a constant value, but it has now become a function taking container as parameter.

We can now define the actual container for the "home" page:

let home = [ text "Home" ]
val home : obj list

Full name: CDocument.home

For now it will only contain plain "Home" text. Let's also extract a common function for creating the WebPart, parametrized with the container itself. Add to App module, just before the browse WebPart the following:

let html container = OK (View.index container)
val html : container:'a -> 'b

Full name: CDocument.html
val container : 'a

Usage for the home page looks like this:

choose [ path Path.home >=> html View.home

Next, containers for each valid route in our application can be defined in View module:

let home = [ text "Home" ] let store = [ text "Store" ] let browse genre = [ text (sprintf "Genre: %s" genre) ] let details id = [ text (sprintf "Details %d" id) ]
val home : obj list

Full name: CDocument.home
val store : obj list

Full name: CDocument.store
val browse : genre:'a -> 'b list

Full name: CDocument.browse
val genre : 'a
val sprintf : format:Printf.StringFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.sprintf
val details : id:'a -> 'b list

Full name: CDocument.details
val id : 'a

Note that both home and store are constant values, while browse and details are parametrized with genre and id respectively.

html can be now reused for all 4 views:

let browse = request (fun r -> match r.queryParam "genre" with | Choice1Of2 genre -> html (View.browse genre) | Choice2Of2 msg -> BAD_REQUEST msg) let webPart = choose [ path Path.home >=> html View.home path Path.Store.overview >=> html View.store path Path.Store.browse >=> browse pathScan Path.Store.details (fun id -> html (View.details id)) pathRegex "(.*)\.(css|png)" >=> Files.browseHome ]
val browse : obj

Full name: CDocument.browse
union case Choice.Choice1Of2: 'T1 -> Choice<'T1,'T2>
union case Choice.Choice2Of2: 'T2 -> Choice<'T1,'T2>
val webPart : obj

Full name: CDocument.webPart
val id : x:'T -> 'T

Full name: Microsoft.FSharp.Core.Operators.id


GitHub commit: e8499a0e5f47635b6045a749e3dce32fd8c08c41

Files changed:

  • App.fs (modified)
  • View.fs (modified)

results matching ""

    No results matching ""