Note that the type of the init
function has changed - it will now receive the intial URL passed to our SPA!
Handling URL
Handling URL updates in your application
Using elmish-urlParser let us define the type that's going to represent our routes and the parser to convert the browser URLs into instances of this type.
type Route =
| Blog of int
| Search of string
let route =
oneOf
[ map Blog (s "blog" </> i32)
map Search (s "search" </> str) ]
To execute the parser we've defined and pass the route as a nice data structure into the update loop we'll define urlUpdate
function that takes the current state and the parsed output, for example:
type Model =
{
route : Route
query : string
}
open Elmish.Navigation
let urlUpdate (result:Option<Route>) model =
match result with
| Some (Search query) ->
{ model with
route = result.Value
query = query
}
, Cmd.none
| Some page ->
{ model with
route = page
query = ""
}
, Cmd.none
| None ->
model
, Navigation.modifyUrl "#" // no matching route - go home
It looks like update
function but instead of the message it handles the route changes. If the URL is valid, we just update our model or issue a command, otherwise we modify the URL to whatever makes sense.
Now we augument our program instance with Navigation capabilities, passing the parser and urlUpdate
:
open Elmish
Program.mkProgram init update view
|> Program.toNavigable (parseHash route) urlUpdate
|> Program.run
Working with full (HTML5) and hash-based URLs
parseHash
function works with "hashbang" URLs, i.e. everything after the '#' symbol, while parsePath
works with the entire location.
The query for a hashbang URL never leaves the browser and can appear in traditional tags like <a>
.
Working with full URL on the other hand means you have to be careful about which requests you want forwarded to the server and which ones should be handled locally.
To keep the request local you have to use Navigation
module for all the URL transitions.
Make sure you understand which one you need.