elmish-browser


Working with query parameters

In addition to working with routes, the library also defines parser combinators for working with ? queries:

  • <?> combinator for query parameters,
  • stringParam combinator to extract a string,
  • intParam combinator to attempt to parse an int.

Some examples:

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
open Elmish.Browser.UrlParser

type PersonQuery = 
    { name: string
      age: int }

type Route = 
    | Blog of int 
    | Search of string option 
    | Query of PersonQuery option
    with static member FromParams name age = 
        match name,age with
        | Some name, Some age -> Query (Some { name = name; age = age})
        | _ -> Query None


let route : Parser<Route->Route,_>=
    oneOf
        [ map Search (s "blog" <?> stringParam "search")
          map Blog (s "blog" </> i32)
          map (Route.FromParams) (top <?> stringParam "name" <?> intParam "age") ]

Note that unlike route combinators, which fail to match the entire route if some combinator can not be parsed, query param parsers return Option. It's up to you if you decide to accept a query parameter as None.

The parser above will resolve:

blog/              ==>  Some (Search None)
blog?search=cats   ==>  Some (Search (Some "cats"))
blog/42            ==>  Some (Blog 42)
?name=tom&age=42   ==>  Some (Query {name="tom"; age=42})
?name=tom          ==>  Some (Query None)

Full vs hashbang URL queries

Normally, query parameters apply to the full URL and are available via location.search property of the browser, that is where pathParser will look. This doesn't work very well with hashbang URLs and hashParser looks for ? in location.hash instead.

Keep this difference in mind when formatting your routes.

namespace Elmish
namespace Elmish.Browser
module UrlParser

from Elmish.Browser
type PersonQuery =
  {name: string;
   age: int;}

Full name: Queries.PersonQuery
PersonQuery.name: string
Multiple items
val string : value:'T -> string

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

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

Full name: Microsoft.FSharp.Core.string
PersonQuery.age: int
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<_>
type Route =
  | Blog of int
  | Search of string option
  | Query of PersonQuery option
  static member FromParams : name:string option -> age:int option -> Route

Full name: Queries.Route
union case Route.Blog: int -> Route
union case Route.Search: string option -> Route
type 'T option = Option<'T>

Full name: Microsoft.FSharp.Core.option<_>
union case Route.Query: PersonQuery option -> Route
static member Route.FromParams : name:string option -> age:int option -> Route

Full name: Queries.Route.FromParams
val name : string option
val age : int option
union case Option.Some: Value: 'T -> Option<'T>
val name : string
val age : int
union case Option.None: Option<'T>
val route : Parser<(Route -> Route),Route>

Full name: Queries.route
type Parser<'a,'b> = State<'a> -> State<'b> list

Full name: Elmish.Browser.UrlParser.Parser<_,_>
val oneOf : parsers:('a -> 'b list) list -> state:'a -> 'b list

Full name: Elmish.Browser.UrlParser.oneOf
val map : subValue:'a -> parse:Parser<'a,'b> -> Parser<('b -> 'c),'c>

Full name: Elmish.Browser.UrlParser.map
val s : str:string -> Parser<'a,'a>

Full name: Elmish.Browser.UrlParser.s
val stringParam : name:string -> QueryParser<(string option -> 'a),'a>

Full name: Elmish.Browser.UrlParser.stringParam
val i32 : state:State<(int -> 'a)> -> State<'a> list

Full name: Elmish.Browser.UrlParser.i32
static member Route.FromParams : name:string option -> age:int option -> Route
val top : state:'a -> 'a list

Full name: Elmish.Browser.UrlParser.top
val intParam : name:string -> QueryParser<(int option -> 'a),'a>

Full name: Elmish.Browser.UrlParser.intParam