Solid Router
Bindings for @solidjs/router. They live in the Partas.Solid.Router namespace, which ships inside the Partas.Solid package.
open Partas.Solid
open Partas.Solid.Router
Partas.Solid does not install the npm package:
npm install @solidjs/router
An example
[<SolidComponent>]
let Home () = h1 () { "Home" }
[<SolidComponent>]
let About () = h1 () { "About" }
[<Erase>]
type Layout() =
inherit div()
[<SolidTypeComponent>]
member props.View =
div () {
nav () {
A(href = "/") { "Home" }
A(href = "/about", activeClass = "active") { "About" }
}
props.children
}
[<SolidComponent>]
let App () =
Router(root = !@Layout) {
Route(path = "/", component' = !@Home)
Route(path = "/about", component' = !@About)
}
A Route can hold nested Routes. component' and root take a TagValue: use !@Component to pass a component rather than call it. The router passes the matched route to root as children, which is why Layout is a type component that inherits div. Like every [<SolidTypeComponent>], Layout must be declared in a namespace or module whose name starts with Partas.Solid (see SolidTypeComponent).
What the plugin emits for Router () { Route () }:
import { Route, Router } from "@solidjs/router";
<Router>
<Route />
</Router>
Components
Router
type Router() = interface HtmlElement
| Property | Type |
|---|---|
root | TagValue |
base' | string |
actionBase | string |
preload | bool |
explicitLinks | bool |
url | string |
The body accepts Route children, or a RootConfig[] for config-based routing.
HashRouter
type HashRouter() = inherit Router()
Same properties as Router.
MemoryRouter
type MemoryRouter() = inherit Router()
Adds history: MemoryHistory. Create one with createMemoryHistory ().
MemoryHistory
member get(): string
member set(value: string, ?scroll: bool, ?replace: bool): unit // emitted as one options object
member back()
member forward()
member go(n: int): unit
member listen(listener: string -> unit): unit -> unit
listen returns the function that removes the listener.
Route
type Route() = interface HtmlElement
| Property | Type | Notes |
|---|---|---|
path | string | |
paths | string array | Sets path to an array of paths. |
component' | TagValue | |
matchFilters | obj | |
preload | RoutePreloadFunc |
RootConfig
[<Pojo>]
type RootConfig(path: string, ``component``: HtmlElement)
component' is an alias for ``component``.
A
type A() = interface RegularNode
| Property | Type |
|---|---|
href | string |
noScroll | bool |
replace | bool |
state | obj |
activeClass | string |
inactiveClass | string |
end' | bool |
Navigate
type Navigate() = interface RegularNode
Properties: href: string, state: obj.
Navigation
useNavigate
useNavigate(): Navigator
Navigator has three ways to call it:
abstract Invoke: ``to``: string * ?options: NavigateOptions -> unit
abstract InvokeOptions: ``to``: string * ?resolve: bool * ?replace: bool * ?scroll: bool * ?state: obj -> unit
abstract Invoke: delta: float -> unit
InvokeOptions builds the options object for you, so you do not need a NavigateOptions:
let navigate = useNavigate ()
navigate.InvokeOptions ("/login", replace = true)
navigate.Invoke(-1.)
NavigateOptions is a [<Pojo>] with the optional arguments resolve, replace, scroll and state.
useLocation
useLocation(): Location
type Path =
abstract pathname: string
abstract search: string
abstract hash: string
type Location =
inherit Path
abstract query: obj
abstract state: obj option
abstract key: string
useParams
useParams(): obj
useSearchParams
useSearchParams(): Signal<obj>
See Solid-js for Signal<'T>.
useIsRouting
useIsRouting(): unit -> bool
useMatch
useMatch(fn: unit -> string, ?matchFilters: obj): unit -> bool
useBeforeLeave
useBeforeLeave(listener: BeforeLeaveEventArgs -> unit): unit
type BeforeLeaveEventArgs =
abstract from: Location
abstract ``to``: U2<string, float>
abstract options: NavigateOptions option
abstract defaultPrevented: bool
abstract preventDefault: unit -> unit
abstract retry: ?force: bool -> unit
useCurrentMatches
useCurrentMatches(): unit -> RouteMatch[]
type PathMatch =
abstract ``params``: obj
abstract path: string
type RouteMatch =
inherit PathMatch
abstract route: RouteDescription
type RouteDescription =
abstract key: obj
abstract originalPath: string
abstract pattern: string
abstract preload: RoutePreloadFunc option
abstract matcher: (string -> PathMatch option)
abstract matchFilters: obj option
abstract info: obj option
usePreloadRoute
usePreloadRoute(): (string -> PreloadData) -> unit
PreloadData is a [<Pojo>] with one field, preloadData: bool.
Preloading
type RoutePreloadFunc = RoutePreloadFuncArgs -> unit
type RoutePreloadFuncArgs =
abstract ``params``: obj
abstract location: Location
abstract intent: Intent
Intent is a [<StringEnum>] with [<RequireQualifiedAccess>]: Intent.Initial, Intent.Native, Intent.Navigate, Intent.Preload.
Data
query
query<'Input, 'Output>(fn: 'Input -> 'Output, ?name: string): 'Input -> 'Output
query'<'Input, 'Output>(fn: 'Input -> 'Output, ?name: string): Query<'Input, 'Output>
query hands back a plain F# function. query' hands back a Query, which exposes the cache key:
type Query<'Input, 'Output> =
abstract Invoke: 'Input -> 'Output
abstract key: string
abstract keyFor: 'Input -> string
If you used query, the extension members .key and .keyFor value on the returned function do the same thing.
revalidate
revalidate(key: string, ?force: bool): unit
createAsync
createAsync<'T>(
fn: 'T option -> Promise<'T>,
?name: string,
?initialValue: 'T,
?deferStream: bool,
?onHydrated: unit -> unit,
?ssrLoadFrom: string,
?storage: unit -> Signal<'T>
): Accessor<'T>
createAsyncWithLatest takes the same arguments and returns an AsyncAccessor<'T>, which adds latest: 'T. On a plain accessor the .latest extension member reads the same field.
createAsyncStore
createAsyncStore<'T>(
fn: 'T option -> Promise<'T>,
?name: string,
?initialValue: 'T,
?deferStream: bool,
?reconcile: obj,
?onHydrated: unit -> unit,
?ssrLoadFrom: string
): Accessor<'T>
createAsyncStoreWithLatest is the AsyncAccessor<'T> form.
Actions
action
Actions only work with POST requests.
action<'Input, 'Output>(
handler: 'Input -> Promise<'Output>,
?name: string,
?onComplete: Submission<'Input, 'Output> -> unit
): SolidAction<'Input, 'Output>
name and onComplete are passed as one options object.
type SolidAction<'Input, 'Result> =
abstract url: string
abstract with': 'Input -> string
useAction
useAction<'Input, 'Result>(action: SolidAction<'Input, 'Result>): 'Input -> 'Result
This avoids FormData, but needs client-side JavaScript, so it is not progressively enhanced the way a form is.
useSubmission, useSubmissions
useSubmission<'Input>(action: SolidAction<'Input, unit>, ?filter: 'Input -> bool): Submission<'Input, unit>
useSubmissions<'Input>(action: SolidAction<'Input, unit>, ?filter: 'Input -> bool): Submission<'Input, unit>[]
type Submission<'Input, 'Result> =
abstract input: 'Input
abstract result: 'Result option
abstract error: obj
abstract pending: bool
abstract url: string
abstract clear: (unit -> unit)
abstract retry: (unit -> unit)
Do not use the .pending extension member on an array of submissions: it has no implementation and always returns undefined. Use Array.exists _.pending.
Not bound
preload, json, redirect and reload are not bound. Import them with Fable.Core.JsInterop.import.
