UniversalRouter Nested Routes

Plain and nested routes example

HTML

<script src="https://unpkg.com/universal-router@3/universal-router.js"></script>
<ul>
  <li><a href="/">/</a></li>
  <li><a href="/about">/about</a></li>
  <li><a href="/users">/users</a></li>
  <li><a href="/users/456">/users/456</a></li>
  <li><a href="/posts">/posts</a></li>
  <li><a href="/posts/hello-world">/posts/hello-world</a></li>
  <li><a href="/posts/hello-world/edit">/posts/hello-world/edit</a></li>
  <li><a href="/posts/hello-world/comments">/posts/hello-world/comments</a></li>
</ul>
<h1>Page Name</h1>

JavaScript

// import UniversalRouter from 'universal-router'

const plainRoutes = [
  { path: '/', action: () => 'Home' },
  { path: '/about', action: () => 'About' },
  { path: '/users', action: () => 'Users' },
  { path: '/users/:id', action: (ctx) => `User #${ctx.params.id}` },
  { path: '/posts', action: () => 'Posts' },
  { path: '/posts/:uri', action: (ctx) => `Post "${ctx.params.uri}"` },
  { path: '/posts/:uri/edit', action: (ctx) => `Post "${ctx.params.uri}" - Edit` },
  { path: '/posts/:uri/comments', action: (ctx) => `Post "${ctx.params.uri}" - Comments` }
]

const nestedRoutes = [
  { path: '/', action: () => 'Home' },
  { path: '/about', action: () => 'About' },
  { path: '/users', children: [
    { path: '/', action: () => 'Users' },
    { path: '/:id', action: (ctx) => `User #${ctx.params.id}` }
  ] },
  { path: '/posts', children: [
    { path: '/', action: () => 'Posts' },
    { path: '/:uri', children: [
      { path: '/', action: (ctx) => `Post "${ctx.params.uri}"` },
      { path: '/edit', action: (ctx) => `Post "${ctx.params.uri}" - Edit` },
      { path: '/comments', action: (ctx) => `Post "${ctx.params.uri}" - Comments` }
    ] }
  ] }
]

const router = new UniversalRouter(nestedRoutes) // or plainRoutes

const container = document.querySelector('h1')
function render() {
  router.resolve(location.pathname).then(page =>
    container.innerHTML = page
  )
}

window.addEventListener('click', event => {
  if (event.target.tagName === 'A') {
    event.preventDefault()
    const anchor = event.target
    const state = null
    const title = anchor.textContent
    const url = anchor.pathname + anchor.search + anchor.hash
    history.pushState(state, title, url)
    render()
  }
})

history.replaceState(null, '', '/')
render()