Route Module
The Route module provides functions for working with routes in your Elmish Land application. Routes are automatically generated based on your page structure and provide type-safe navigation and URL formatting.
Where is this defined?
The Route module is automatically generated during the build process:
- Generated Location:
.elmish-land/Base/Routes.fs(in your project) - Generated By: Running
elmish-land restore,elmish-land serverandelmish-land buildcommands - Namespace:
ElmishLandwith[<AutoOpen>] module Routes - Generation Source: Based on your
src/Pages/folder structure
Unlike the other generated modules, the Route types are dynamically created based on your page structure. Each page in src/Pages/ gets its own route type, and folders starting with _ create route parameters. You can customize route parameters using route.json configuration files in your page directories.
The .elmish-land/Base/Routes.fs file is auto-generated and should not be edited directly. Any changes will be overwritten on the next build.
Generated Route Types
Elmish Land automatically generates a discriminated union type for all your routes. Each page in your application gets its own route case.
Example
Given this page structure:
src/Pages/
├── Page.fs # Home page
├── Blog/
├── Page.fs # Blog index
└── _Slug/
└── Page.fs # Individual blog post
Elmish Land generates:
type HomeRoute = unit
type BlogRoute = unit
type Blog_SlugRoute = { Slug: string }
[<RequireQualifiedAccess>]
type Route =
| Home of HomeRoute
| Blog of BlogRoute
| Blog_Slug of Blog_SlugRoute
Route.format
Converts a route to a URL string that can be used in links and navigation.
Signature
Route.format : Route -> string
Parameters
route- The route to format as a URL string
Example
// Simple route
Route.format (Route.Home ())
// Returns: "#/"
// Static route
Route.format (Route.About ())
// Returns: "#/about"
// Dynamic route with parameter
Route.format (Route.Users_Id { Id = "123" })
// Returns: "#/users/123"
// Route with parameter and query parameters
Route.format (Route.Blog_Slug {
Slug = "my-post"
Highlight = Some true
Ref = Some "home"
})
// Returns: "#/blog/my-post?highlight=true&ref=home"
Usage in Links
Use Route.format with anchor elements to create type-safe links:
Html.a [
prop.text "View Profile"
prop.href (Route.format (Route.Users_Id { Id = user.Id }))
]
Route.isEqualWithoutPathAndQuery
Compares two routes for equality, ignoring path parameters and query strings. Useful for determining if the user is on a specific page type regardless of parameters.
Signature
Route.isEqualWithoutPathAndQuery : Route -> Route -> bool
Parameters
route1- First route to compareroute2- Second route to compare
Example
let currentRoute = Route.Users_Id { Id = "123"; Tab = None }
let otherRoute = Route.Users_Id { Id = "456"; Tab = Some "tab" }
// Check if both routes are the same page (ignoring parameters)
Route.isEqualWithoutPathAndQuery currentRoute otherRoute
// Returns: true (both are Users_Id pages)
let homeRoute = Route.Home ()
Route.isEqualWithoutPathAndQuery currentRoute homeRoute
// Returns: false (different page types)
Use Cases
Active Link Styling
Highlight navigation links when on the corresponding page:
let currentRoute = Route.parse (Feliz.Router.Router.currentPath())
let isActive route =
Route.isEqualWithoutPathAndQuery route currentRoute
Html.a [
prop.text "Users"
prop.href (Route.format (Route.Users_Id { Id = "123" }))
if isActive (Route.Users_Id { Id = "123" }) then
prop.className "active"
]
Best Practices
Use Route.format for All Links
Always use Route.format instead of manually constructing URLs. This ensures type safety and prevents broken links:
// Good - Type-safe and refactor-friendly
Html.a [
prop.href (Route.format (Route.About ()))
]
// Avoid - Fragile and error-prone
Html.a [
prop.href "#/about"
]