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:

View.fs

  23: 
let index container =

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

View.fs

  30: 
  31: 
  32: 
  33: 
  34: 
  35: 
  36: 
  37: 
body [] [ div ["id", "header"] [ tag "h1" [] [ a Path.home [] [Text "F# Suave Music Store"] ] ] div ["id", "main"] container

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

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 following function:

App.fs

  10: 
  11: 
let html container = OK (View.index container)

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

View.fs

   7: 
   8: 
   9: 
let home = [ Text "Home" ]

For now it will only contain plain "Home" text.

Next, containers for rest of valid routes in our application can be defined in View module:

View.fs

  11: 
  12: 
  13: 
let store = [ Text "Store" ]

View.fs

  15: 
  16: 
  17: 
let browse genre = [ Text (sprintf "Genre: %s" genre) ]

View.fs

  19: 
  20: 
  21: 
let details id = [ Text (sprintf "Details %d" id) ]

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:

App.fs

  13: 
  14: 
  15: 
  16: 
  17: 
let browse = request (fun r -> match r.queryParam "genre" with | Choice1Of2 genre -> html (View.browse genre) | Choice2Of2 msg -> BAD_REQUEST msg)

App.fs

  19: 
  20: 
  21: 
  22: 
  23: 
  24: 
  25: 
  26: 
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 ]
type IntPath = PrintfFormat<(int -> string),unit,string,string,int>

Full name: SuaveMusicStore.Path.IntPath
Multiple items
type PrintfFormat<'Printer,'State,'Residue,'Result> =
new : value:string -> PrintfFormat<'Printer,'State,'Residue,'Result>
member Value : string

Full name: Microsoft.FSharp.Core.PrintfFormat<_,_,_,_>

--------------------
type PrintfFormat<'Printer,'State,'Residue,'Result,'Tuple> =
inherit PrintfFormat<'Printer,'State,'Residue,'Result>
new : value:string -> PrintfFormat<'Printer,'State,'Residue,'Result,'Tuple>

Full name: Microsoft.FSharp.Core.PrintfFormat<_,_,_,_,_>

--------------------
new : value:string -> PrintfFormat<'Printer,'State,'Residue,'Result>

--------------------
new : value:string -> PrintfFormat<'Printer,'State,'Residue,'Result,'Tuple>
Multiple items
val int : value:'T -> int (requires member op_Explicit)

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

--------------------
type int = int32

Full name: Microsoft.FSharp.Core.int

--------------------
type int<'Measure> = int

Full name: Microsoft.FSharp.Core.int<_>
Multiple items
val string : value:'T -> string

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

--------------------
type string = System.String

Full name: Microsoft.FSharp.Core.string
type unit = Unit

Full name: Microsoft.FSharp.Core.unit
val home : string

Full name: SuaveMusicStore.Path.home
module Store

from SuaveMusicStore.Path
val overview : string

Full name: SuaveMusicStore.Path.Store.overview
val browse : string

Full name: SuaveMusicStore.Path.Store.browse
val details : IntPath

Full name: SuaveMusicStore.Path.Store.details
namespace Suave
module Html

from Suave
val cssLink : href:string -> Node

Full name: SuaveMusicStore.View.cssLink
val href : string
val link : attr:Attribute list -> Node

Full name: Suave.Html.link
val home : Node list

Full name: SuaveMusicStore.View.home
union case Node.Text: string -> Node
val store : Node list

Full name: SuaveMusicStore.View.store
val browse : genre:string -> Node list

Full name: SuaveMusicStore.View.browse
val genre : string
val sprintf : format:Printf.StringFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.sprintf
val details : id:int -> Node list

Full name: SuaveMusicStore.View.details
val id : int
val index : container:Node list -> string

Full name: SuaveMusicStore.View.index
val container : Node list
val html : (Attribute list -> Node list -> Node)

Full name: Suave.Html.html
val head : (Attribute list -> Node list -> Node)

Full name: Suave.Html.head
val title : attr:Attribute list -> s:string -> Node

Full name: Suave.Html.title
val body : (Attribute list -> Node list -> Node)

Full name: Suave.Html.body
val div : (Attribute list -> Node list -> Node)

Full name: Suave.Html.div
val tag : tag:string -> attr:Attribute list -> contents:Node list -> Node

Full name: Suave.Html.tag
val a : href:string -> attr:Attribute list -> (Node list -> Node)

Full name: Suave.Html.a
module Path

from SuaveMusicStore
val htmlToString : node:Node -> string

Full name: Suave.Html.htmlToString
module App

from SuaveMusicStore
module Filters

from Suave
module Operators

from Suave
module RequestErrors

from Suave
module Successful

from Suave
module Web

from Suave
val html : container:Html.Node list -> WebPart

Full name: SuaveMusicStore.App.html
val container : Html.Node list
val OK : body:string -> WebPart

Full name: Suave.Successful.OK
module View

from SuaveMusicStore
val index : container:Html.Node list -> string

Full name: SuaveMusicStore.View.index
val browse : (HttpContext -> Async<HttpContext option>)

Full name: SuaveMusicStore.App.browse
val request : apply:(HttpRequest -> HttpContext -> 'a) -> context:HttpContext -> 'a

Full name: Suave.Http.request
val r : HttpRequest
member HttpRequest.queryParam : key:string -> Choice<string,string>
union case Choice.Choice1Of2: 'T1 -> Choice<'T1,'T2>
val browse : genre:string -> Html.Node list

Full name: SuaveMusicStore.View.browse
union case Choice.Choice2Of2: 'T2 -> Choice<'T1,'T2>
val msg : string
val BAD_REQUEST : body:string -> WebPart

Full name: Suave.RequestErrors.BAD_REQUEST
val webPart : WebPart<HttpContext>

Full name: SuaveMusicStore.App.webPart
val choose : options:WebPart<'a> list -> WebPart<'a>

Full name: Suave.WebPart.choose
val path : pathAfterDomain:string -> WebPart

Full name: Suave.Filters.path
val home : Html.Node list

Full name: SuaveMusicStore.View.home
val store : Html.Node list

Full name: SuaveMusicStore.View.store
val pathScan : pf:PrintfFormat<'a,'b,'c,'d,'t> -> h:('t -> WebPart) -> WebPart

Full name: Suave.Filters.pathScan
val details : Path.IntPath

Full name: SuaveMusicStore.Path.Store.details
val details : id:int -> Html.Node list

Full name: SuaveMusicStore.View.details
val pathRegex : pathAfterDomainRegex:string -> WebPart

Full name: Suave.Filters.pathRegex
module Files

from Suave
val browseHome : WebPart

Full name: Suave.Files.browseHome
val startWebServer : config:SuaveConfig -> webpart:WebPart -> unit

Full name: Suave.Web.startWebServer
val defaultConfig : SuaveConfig

Full name: Suave.Web.defaultConfig

Show code from this section on GitHub

results matching ""

    No results matching ""