Building a Glimmer Router with Navigo
Tags: glimmer, glimmerjs, navigo, routing
Published: 2021-01-07 02:23:52


This is the third post in the series of building a Router component in Glimmer.js. In the [second post](https://dev.to/rajasegar/building-a-glimmer-router-with-page-js-hb5) we built our Router component using page.js for handling anchor tag clicks, history state changes and so on. In this post we are going to make use of a library called `navigo` for all those capabilities.

{% post https://dev.to/rajasegar/building-a-glimmer-router-with-page-js-hb5 %}



# Navigo
[Navigo](https://github.com/krasimir/navigo) is a simple dependency-free minimalistic JavaScript router with a fallback for older browsers. It is based on History API so it does update the URL of the page. It has got a simple mapping of route to a function call, parameterized routes, programmatic navigation between routes and lifecycle hooks such as before, after, leave, already. It can be easily integrated with HTML links via `data-navigo` attribute.

You can install it with:
```
yarn add navigo -S
```

Navigo is created by [Krasimir Tsonev](https://github.com/krasimir) based on this blog post by him called [A modern Javascript router in 100 lines](http://krasimirtsonev.com/blog/article/A-modern-JavaScript-router-in-100-lines-history-api-pushState-hash-url).

The api of Navigo is very simple. First you have to create a new instance of Navigo,
```js
const router = new Navigo('/');
```
And then using that instance, you have to define your route mappings with the `on` function of the router instance. The on function takes two parameters, one is the url and the next one is the handler function for that particular url.

```js
router.on('/products/list', function() {
  // do something
});
```
And finally, you have to trigger the resolving logic.
```js
router.resolve()
```

## App.js
We will be modifying our `App` component from the [previous post](https://dev.to/rajasegar/building-a-glimmer-router-with-page-js-hb5). The markup for our `App.js` component will look something like this. As you see we are using two components here, `LinkTo` and `Router`.  And our `Router` component is where the routing logic is placed.

```html
<nav>
  <ul>
    <li><LinkTo @route="/">Home</LinkTo></li>
    <li><LinkTo @route="about">About</LinkTo></li>
    <li><LinkTo @route="contact">Contact</LinkTo></li>
  </ul>
</nav>
<main>
  <Router/>
</main>
```

## LinkTo component
`LinkTo` is to render the anchor tags with special attributes for Navigo called `data-navigo` so that Navigo can pick up these elements and listen for their click events. The markup for LinkTo will be like:
```html
<a href={{@route}} data-navigo>{{yield}}</a>
```

## Router component
This is just a placeholder component for rendering the page level components when the url is matched. All the routing logic is done through a modifier called `startNavigo`.

```html
<div id="glimmer-router-outlet" {{startNavigo}}></div>
```

## startNavigo modifier
The startNavigo modifier function is where we will instantiate the Navigo library and invoke it with the route mappings, the url and the handler functions from a separate file called `routes.js`. 

```js
function startNavigo(element) {

  const router = new Navigo("/");
  const navigoRoutes = routes(element);

  router.on(navigoRoutes).resolve();

  return () => {
    router.destroy();
  }

}
```

## routes.js
The `routes.js` contains the route mappings for the various routes within the app. It will export a default function which takes only one parameter the element, which is passed on by the modifier function `startNavigo` in the previous section. And it returns an object of route mappings with the url patterns and the handler functions.

Inside each handler function, we will be resetting the element DOM content and then we will be using the `renderComponent` function from `@glimmer/core` to render the appropriate component. All the components are stored in a special folder called `pages` in the project in a conventional fashion.

```js
import { renderComponent } from '@glimmer/core';

import Home from './pages/Home.js';
import About from './pages/About.js';
import Contact from './pages/Contact.js';

export default function(element) {
  return {
    'about': () => {
      element.innerHTML = '';
      renderComponent(About, element);
    }  ,
    'contact': () => {
      element.innerHTML = '';
      renderComponent(Contact, element);
    },
    '*': () => {
      element.innerHTML = '';
      renderComponent(Home, element);
    }
  };
}
```

## Source Code
The source code for this post is available in this Github [repository](https://github.com/rajasegar/glimmer-routing-navigo).

## References:
- [Navigo](https://github.com/krasimir/navigo)
- [A modern Javascript router in 100 lines](http://krasimirtsonev.com/blog/article/A-modern-JavaScript-router-in-100-lines-history-api-pushState-hash-url)
- [Glimmer.js](https://glimmerjs.com)

Please let me know for any queries/feedbacks in the comments section.