Once a PageDispatchController
has been configured and the server is serving a route, the frontend needs to be configured to mount something there.
From here the frontend router will attempt to handle as much routing as possible, until it it navigates to a route outside of its current section. Generally this is caused by a subcommunity or language change.
Overview
We're going to build on the server side example of a custom resource with an "add" and "edit" route.
We will be making routes for /my-prefix/resource/{id}/editor
and /my-prefix/resource/add
.
Making your page component
The first step is to create our page. In our case we'll make a minimal form with a text area inside of a modal.
Because add & edit actions often use the same UI, we will be using a single Add/Edit component for both.
src/scripts/pages/ResourceAddEditPage.tsx
import React from "react";
import { TitleBar } from "@vanilla/library/src/scripts/headers/TitleBar";
import { useParams } from "react-router-dom";
export function ResourceAddEditPage() {
const { id } = useParams();
useEffect(() => {
if (id != null) {
// Go fetch information about the ID from somewhere.
// Don't forget to validate it.
requestDataFromWhere();
}
}, [id]);
const data = useDataFromSomewhere()
return (
<Modal isFullPage={true} size={ModalSizes.FULL_SCREEN}>
<h1>{id == null ? "Add" : "Edit"}</h1>
<form>
<textarea name="body" placeholder="Hello world"></textarea>
<button type="submit">Submit</button>
</form>
</Moadl>
);
}
The ID passed here will be the one from our URL. If there is on ID we know this is the Add page instead of edit, and don't fetch any initial data.
Creating the RouteHandler
Now that we have the component we have to create a route handler to handle the routing for it.
A RouteHandler
handles forwards and reverse routing so it needs the following information:
- A loadable instance of your page component. This should a by a dynamic webpack import so the page contents can be code-split into their chunk.
- Any valid URL path or array of paths that
path-to-regexp@^1.7.0
understands. - A function to generate a URL to this page from a set of parameters.
- Optionally a special loader while the page's code is fetched. There are currently 2 built in loaders:
<Loader />
- A standard circular loader, with a titlebar at the top.<ModalLoader />
- A standard circular loader inside of a fullscreen white overlay. This will block out all background contents including header, titlebar, footer, etc.
src/scripts/pages/ResourceAddEditRoute.tsx
export const ResourceAddEditRoute = new RouteHandler(
() => import(
/* webpackChunkName: "pages/resourceAddEdit" */ "../ResourceAddEditPage.tsx"
),
["/my-prefix/resource/add", "/my-prefix/resource/:id(\\d+)/edit"],
(id?: number) => (
id !== null
? `/my-prefix/resource/${id}/edit`
: `/my-prefix/resource/add`
),
ModalLoader
);
Here we've:
- imported our page dynamically and gave it a chunk name for easier debugging.
- Defined 2 URLs patterns for our page. Note that name
:id
means our param in the page will be named id
. - Created a function generate the URLs.
- Defined that these pages are contained in a full page modal, so the loader will appear similarly and prevent a flashing when the page finally loads.
Registering the Route
Now that we've created the route we can register it. We need to create an entry file that matches the entry declared in our server controller's getAssetSection()
.
The example there was admin
, so we are going to create the following file to register our route.
src/scripts/entries/admin.tsx
import { Router } from "@library/Router";
import { ResourceAddEditRoute } from "../pages/ResourceAddEditRoute.tsx";
Router.addRoutes([
ResourceAddEditRoute.route
]);
With that done we should be able to navigate to /my-prefix/resource/add
and see our page loaded!
Navigating to the Page
There a multiple ways to link to our page, they'll be listed here in order of preference.
Using the generated link component
<ResourceAddEditRoute.Link data={undefined} />
<ResourceAddEditRoute.Link data={5} />
- Does dynamic navigation to the route.
- Type-checks the data to ensure a well-formed URL.
- Automatically preloads the dynamic import on hover of the link.
Use the generated URL function
ResourceAddEditRoute.preload(); // Manually Preload the route if possilbe..
ResourceAddEditRoute.url(undefined);
ResourceAddEditRoute.url(5);
- Does dynamic navigation to the route.
- Type-checks the data to ensure a well-formed URL.
- Possible to manually preload the route.
Use SmartLink
<SmartLink to={resourceFromApi.url} />
<SmartLink to="/my-prefix/resource/add" />
<SmartLink to="/my-prefix/resource/5/edit" />
- Does dynamic navigation to the route when possible.
- Doesn't have type checking when manually constructing a string.
- Ideal for API based resources.
Normal link
<a href="/my-prefix/resource/add" />
<a href="/my-prefix/resource/5/edit" />
- Does a full page reload and navigation.
- Doesn't have type checking when manually constructing a string.
Additional Resources
Vanilla's router is built on top of react-router, so any resources related to that may be useful.