Report this

What is the reason for this report?

Introduction to Routing Using Stencil

Published on August 31, 2017
Introduction to Routing Using Stencil

@stencil/router is the NPM package to use with Stencil to make it easy to define routes for your web component-powered PWA. The API for the router is very similar to React Router’s, so you may already be familiar with the syntax.

In this post we’ll build a simple example where we have global components for an app shell, header and menu, as well as 3 routes: home, about and contact.

Setup & Configuration

First, make sure you have the @stencil/router package installed in your project:

$ npm install @stencil/router

# or, using Yarn
$ yarn add @stencil/router

Next you’ll want to make sure that your Stencil config file’s config object contains a collections array with the router package:

stencil.config.js
exports.config = {
  bundles: [
    { components: ['app-shell', 'app-header', 'app-menu'] }
  ],
  collections: [
    { name: '@stencil/router' }
  ]
};


If you’re using Stencil’s starter app to initiate your project, the @stencil/router package and proper config will already be in place.

Defining Routes

Routes are defined in a global <stencil-router> element that contains <stencil-route> elements for each individual route definition. Routes will be rendered inside the stencil-router element.

The <stencil-router> should have an id that the <stencil-route> elements can refer to. Here’s a simple example with our 3 routes:

<stencil-router id="router">
  <stencil-route
    url="/"
    component="app-home"
    router="#router"
    exact={true}
  />
  <stencil-route
    url="/contact"
    component="app-contact"
    router="#router"
  />
  <stencil-route
    url="/about"
    component="app-about"
    router="#router"
  />
</stencil-router>

Notice the use of exact={true} on the root / url to match only the root path to the home component.

We would place such route config in our app’s top level component, here app-shell. Here, our whole app root component could look like this:

/components/app-shell/app-shell.tsx
import { Component } from '@stencil/core';

@Component({
  tag: 'app-shell'
})
export class AppComponent {
  render() {
    return [
      <app-header title="Fancy Alligator!" />,

      <app-menu />,

      <stencil-router id="router">
        <stencil-route
          url="/"
          component="app-home"
          router="#router"
          exact={true}
        />
        <stencil-route
          url="/contact"
          component="app-contact"
          router="#router"
        />
        <stencil-route
          url="/about"
          component="app-about"
          router="#router"
        />
      </stencil-router>
    ];
  }
}

The render method returns multiple top level elements. This can be done using an array of top level elements, like in the above example. Or, it can also be done by wrapping the 3 top level elements in a wrapping div element.

Linking to a Route

To link to a route with the app, use the <stencil-route-link> element with the id of the router and the url. Here for example, here’s the render method of our app-menu component:

/components/app-menu/app-menu.tsx (partial)
render() {
  return (
    <ul>
      <li>
        <stencil-route-link
          router="#router"
          url="/"
          activeClass="active"
          exact={true}
        >
          Home
        </stencil-route-link>
      </li>
      <li>
        <stencil-route-link
          router="#router"
          url="/about"
          activeClass="active"
        >
          About
        </stencil-route-link>
      </li>
      <li>
        <stencil-route-link
          router="#router"
          url="/contact"
          activeClass="active"
        >
          Contact
        </stencil-route-link>
      </li>
    </ul>
  );
}

Here we’re also using the activeClass property to set a class name on active routes. The root route also has its exact property set to true so that the active class gets added only on an exact match of the url.

Passing Data to a Route

You can also pass props to a route in its configuration using the componentProps property:

<stencil-route
  url="/contact"
  component="app-contact"
  router="#router"
  componentProps={{ method: 'Walkie-talkie' }}
/>

And then in the component it can be accessed using using the @Prop decorator:

app-contact.tsx
import { Component, Prop } from '@stencil/core';

@Component({
  tag: 'app-contact'
})
export class ContactComponent {
  @Prop() method: string;
  render() {
    return <p>📞 Getting in touch by {this.method}</p>;
  }
}

👷‍ The Stencil router is in heavy development and the API is bound to change rapidly. Refer to the official repo for the latest changes.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the author

Alligator
Alligator
Author
See author profile

Alligator.io is a developer-focused resource that offers tutorials and insights on a wide range of modern front-end technologies, including Angular 2+, Vue.js, React, TypeScript, Ionic, and JavaScript.

Category:
Tags:
While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.

Still looking for an answer?

Was this helpful?


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Creative CommonsThis work is licensed under a Creative Commons Attribution-NonCommercial- ShareAlike 4.0 International License.
Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.