custom-elements-router
v1.1.2
Published
Router for custom elements. The same like react-router
Downloads
3
Maintainers
Readme
Router for custom elements
The router is very similar to react-router.
Contents
How to install
First of all you need to install custom-elements-jsx
module and configure it. Here is the library. You must configure babel like it is described in the README.md of the custom-elements-jsx
.
Then you can install custom-elements-router
:
$ npm install --save custom-elements-router
or
$ yarn add custom-elements-router
Usage
You need to import custom-elements-router
once to get access to all custom elements from the library. For example, you can import it in your root index.js file:
import jsx from "custom-elements-jsx";
import "custom-elements-router";
import createHistory from "history/createBrowserHistory";
const browserHistory = createHistory();
const app = (
<custom-router history={browserHistory}>
<custom-switch>
<custom-route path="/" component="main-page" />
</custom-switch>
</custom-router>
);
const root = document.getElementById("root");
root.appendChild(app);
Or you can wrap your custom element by the custom-router
:
import jsx from "custom-elements-jsx";
import "custom-elements-router";
import createHistory from "history/createBrowserHistory";
import "./app.js";
const browserHistory = createHistory();
const app = (
<custom-router history={browserHistory}>
<app-page />
</custom-router>
);
const root = document.getElementById("root");
root.appendChild(app);
Inside of <app-page />
you will get context
object that you must pass to other custom elements from custom-elements-router
:
import jsx, { Component } from "custom-elements-jsx";
class AppPage extends Component {
render() {
const { context } = this.props;
return (
<custom-switch context={context}>
<custom-route path="/" component="main-page" />
<custom-route path="/users" exact component="users-page" />
</custom-switch>
);
}
}
if (!window.customElements.get("app-page"))
window.customElements.define("app-page", AppPage);
<custom-switch>
chooses one of his children with correct path
property. Other children will not be rendered.
If you use custom-route
outside of custom-switch
then all routes will be rendered, but only one custom-route
will have children. Other routes will be empty.
<custom-route>
receives the same props as <Route>
from react-router
library: path
, exact
, component
, render
. Also it receives context
prop. You should remember about this if you user <coustom-route>
outside of <custom-switch>
or <custom-router>
.
In the path
property you should specify full path. Also you can specify variable, for example userId
:
<custom-route path="/users/:userId" component="user-page" />
Then you will get userId
from context
object inside of <user-page>
:
import jsx, { Component } from "custom-elements-jsx";
class UserPage extends Component {
render() {
const { context } = this.props;
const { userId } = context.match.params;
return null;
}
}
The context
object has following props: history
, match
, location
, staticContext
. The same props as in react-router
library.
You can find pathname
from this.props.context.location.pathname
.
If you specify the exact
property then exact match will be found for this route. Otherwise entry will be found. It can be usefull if you want to use <custom-route>
inside of your custom element.
import jsx, { Component } from 'custom-elements-jsx'
// root index.js
cosnt app = (
<custom-router history={browserHistory}>
<custom-route path="/" component="home-page" />
</custom-router>
)
// homePage.js
class HomePage extends Component {
render() {
const { context } = this.props
return (
<custom-switch context={context}>
<custom-route path="/users" exact component="users-page" />
<custom-route path="/settings" exact component="settings-page" />
</custom-switch>
)
}
}
In the component
property you should specify name of your custom element. You should define this element before using in the component
. Type of component
property is string.
Also you can specify render
property. This is a function that receives props as first argument. This function must return HTMLElement:
import jsx, { Component } from "custom-elements-jsx";
const app = (
<custom-router history={browserHistory}>
<custom-route
path="/"
name="John"
render={props => <div>{props.name}</div>}
/>
</custom-router>
);
You will get:
<custom-router>
<custom-route>
<div>John</div>
</custom-route>
</custom-router>
If you specify both props component
and render
then render
will be used.
You have 2 links in the <custom-elements-router
: <custom-link>
and <custom-nav-link>
. You must pass the context
object to both of it. This links receive the same props as links in react-router
library.
You can use <custom-redirect>
this way:
import jsx from "custom-elements-jsx";
import "custom-elements-router";
import createHistory from "history/createBrowserHistory";
const browserHistory = createHistory();
const element = (
<custom-router history={history}>
<custom-switch>
<custom-route path="/" exact component="page-home" />
<custom-route path="/users" exact component="page-users" />
<custom-redirect from="/" to="/users" />
</custom-switch>
</custom-router>
);
This application understands only 2 routes: /
and /users
. Other routes will be redirected to the /users
route, cause <custom-redirect>
doesn't have exact
property. But you can specify this property you need.
Features
There is an another way to use <custom-router>
without <custom-switch>
and <custom-route>
. You can pass array of routes as a property routes
to the <custom-router>
.
// root index.js
import jsx, { Component } from "custom-elements-jsx";
import "custom-elements-router";
import createHistory from "history/createBrowserHistory";
const browserHistory = createHistory();
const routes = [
{
path: "/",
component: "root-page",
routes: [
{
path: "/users",
component: "users-page",
exact: true
},
{
path: "/settings",
component: "settings-page",
exact: true
}
]
}
];
const app = <custom-router history={browserHistory} routes={routes} />;
const root = document.getElementById("root");
root.appendChild(app);
Each component (root-page
, users-page
, etc) will get 2 props: context
and route
. route
is an object from routes
array. For example, component root-page
will get following object as route
property:
{
path: "/",
component: "root-page",
routes: [
{
path: "/users",
component: "users-page",
exact: true
},
{
path: "/settings",
component: "settings-page",
exact: true
}
]
}
But users-page
will get:
{
path: "/users",
component: "users-page",
exact: true
}
You can render nested routes inside of root-page
using function renderRoutes()
:
import jsx, { Component } from "custom-elements-jsx";
import { renderRoutes } from "custom-elements-router";
class RootPage extends Component {
render() {
const { route, context } = this.props;
return renderRoutes(route.routes, context);
}
}
if (!window.customElements.get("root-page"))
window.customElements.define("root-page", RootPage);
You must pass the context
object to the renderRoutes()
function.
Also you have matchRoutes()
function. This is the same function like in the react-router
library.
You can use custom-redirect
in the array of routes:
import jsx from "custom-elements-jsx";
import "custom-elements-router";
import createHistory from "history/createBrowserHistory";
const browserHistory = createHistory();
const routes = [
{
path: "/",
component: "page-home",
exact: true
},
{
path: "/users",
component: "page-users",
exact: true
},
{
from: "/",
component: "custom-redirect",
to: "/users"
}
];
const element = <custom-router history={browserHistory} routes={routes} />;
It works like It was described above.
If you don't want to pass history to the <custom-router>
element you can use <custom-browser-router>
. Browser history will be created inside of this element.
Also you have <custom-hash-router>
and <custom-memory-router>
. They are the same like in react-router
library. All of it receive the same props as <custom-router>
element.
How to test
To test this library you need to install Chrome browser if you still don`t have. Then you need to run:
npm install && npm run test
or
yarn && yarn test
If you want to run tests in watching mode you need to use test:watch
except test
command.