Router
Before Semicolon offers a routing package built with WebComponent which is built on top of Markup.
<nav>
<page-link path="/">Home</page-link>
<page-link path="/contact">Contact</page-link>
</nav>
<page-route path="/">
Home content
</page-route>
<page-route path="/contact">
Contact content
</page-route>
<page-route path="/404">
404 - Page not found!
</page-route>
<page-redirect to="/404"></page-redirect>
Examples
Installation
via npm:
npm install @beforesemicolon/router
via yarn:
yarn add @beforesemicolon/router
via cdn:
<!-- required WebComponent Markup to be present -->
<script src="https://unpkg.com/@beforesemicolon/web-component/dist/client.js"></script>
<!-- use the latest version -->
<script src="https://unpkg.com/@beforesemicolon/router/dist/client.js"></script>
<!-- use a specific version -->
<script src="https://unpkg.com/@beforesemicolon/router@0.1.0/dist/client.js"></script>
<!-- link you app script after -->
<script>
const { ... } = BFS.ROUTER
</script>
Components
Page route
You can specify the title and the body content to conditionally render.
<page-route path="/" title="Welcome">
Home content
</page-route>
Lazy load html content with fallback content and loading indicator.
<page-route path="/contact" src="/contact.html">
<div slot="loading">Loading...</div>
<div slot="fallback">
Oops - Failed to load content
</div>
</page-route>
Import JavaScript file which must default export:
- Text;
- HTML string;
- DOM Node;
- Markup template;
- Any object with a "render" method that takes an element to render at;
- Function that returns any of the above;
<page-route
path="/greeting"
src="./greeting.page.js"
></page-route>
// greeting.page.js
const { html } = BFS.MARKUP
export default () => {
return html`<p>Hello World</p>`
}
Route nesting by specifying the exact
attribute
with false
value.
<page-route path="/todos" exact="false">
<!-- child page route already knows its inside a page-route
so its parent path already prefixes its own which means
bellow page-route path is actually "/todos/pending" -->
<page-route path="/pending">
...
</page-route>
</page-route>
Page route query
The page-route-query
work exactly like page-route
but reacts to the search query of the url instead. It takes a
key and value attributes instead of a path
.
<page-route-query key="tab" value="sample">
sample tab content
</page-route-query>
Use the default
attribute to tell it to render
content even if the key is not present.
<page-route-query key="tab" value="sample" default="true">
sample tab content
</page-route-query>
Page link
A link that lets you navigate to any page. Works similar to
goToPage
and takes similar options.
<page-link
path="/"
title="Welcome"
data='{"sample": "value"}'
>
Home Info
</page-link>
Paths can also contain search query in the path.
<page-link path="/router/index.html?tab=sample">sample tab</page-link>
Or specify it separately.
<page-link path="/sample" search="tab=info">new tab</page-link>
You can choose to keep current search query and only add your specified search.
<page-link path="/sample" search="tab=info" keep-current-search="true">new tab</page-link>
Similar to
page-route-query
default
attribute, you can mark the specified
search as default to put the link in an active state for styling
purpose.
<page-link path="/todos" search="tab=pending" default="true">Pending Todos</page-link>
<page-link path="/todos" search="tab=in-progress">In Progress Todos</page-link>
<page-link path="/todos" search="tab=completed">Completed Todos</page-link>
The link is context aware and leaving out the
path
attribute defaults to the closest
page-route
path
or /
. You can also refer to the
closed page route path with the $
prefix.
<page-route path="/todos">
<page-link search="tab=pending" default="true">Pending Todos</page-link>
<page-link search="tab=in-progress">In Progress Todos</page-link>
<page-link search="tab=completed">Completed Todos</page-link>
<page-link path="$/create">new tab</page-link>
</page-route>
Styling the page-link
is straight forward allowing
you to even target link states.
/* the actual page-link tag */
page-link {
...
}
page-link.active {
...
}
/* the anchor tag inside */
page-link::part(anchor) {
text-decoration: none;
color: #444;
padding: 10px;
border-bottom: 2px solid transparent;
}
page-link::part(anchor active) {
background: #b4fff8;
border-color: #222;
color: #000;
}
page-link::part(anchor):visited { ... }
page-link::part(anchor):active { ... }
page-link::part(anchor):hover { ... }
Page redirect
The page-redirect
lets you automatically redirect
to a path if not a known one. You should place it after all
page-route rendered on the
page.
<page-route path="/" src="./index.html"></page-route>
<page-route path="/contact" src="./contact.html"></page-route>
<page-route path="/about" src="./about.html"></page-route>
<page-route path="/404"></page-route>
<!-- render it after all page-routes-->
<page-redirect to="/404"></page-redirect>
When placed inside a page-route, it will redirect whenever any unknown route starting with the parent page-route is detected.
<page-route path="/project">
...
<page-redirect to="/project/not-found"></page-redirect>
</page-route>
Sometimes you want to always redirect to a child route when a parent path is matched and for that you can specify the redirect type to be always.
<page-route path="/todos" exact="false">
Todos:
<page-route path="/pending">pending todos</page-route>
<page-route path="/in-progress">in progress todos</page-route>
<page-route path="/completed">completed todos</page-route>
<page-redirect to="/todos/pending" type="always"></page-redirect>
</page-route>
<page-route path="/404"></page-route>
<page-redirect to="/404"></page-redirect>
<page-redirect to="/todos" type="always"></page-redirect>
Additional APIs
You have access to internal APIs that you can use in your JavaScript code to perform any similar actions.
goToPage
Takes you to a new page pathname. It takes the path name, an optional data and a page title.
goToPage('/sample')
goToPage('/test', {sample: "value"}, 'test page')
replacePage
Replaces the current page pathname. It takes the path name, an optional data and a page title.
replacePage('/new', {data: 3000}, 'new page')
nextPage
Takes you to the next page.
nextPage()
previousPage
Takes you to the previous page.
previousPage()
onPageChange
A listener for page changes. Takes a callback function that its called with the path name, a search query object literal, and any data set for the page.
onPageChange((pathName, searchQuery, data) => {
...
})
getSearchQuery
Returns a object literal representation of the search query. Parses any value including JSON strings.
getSearchQuery();
updateSearchQuery
Takes a object literal and updates the search query.
updateSearchQuery({
date: "2020-01-01",
sample: 30
})
getPageData
getPageData();