Code Monkey home page Code Monkey logo

router's Introduction

NPM version npm bundle size (minified + gzip)

Vaadin Router

Demo · API documentation

Vaadin Router is a small and powerful client-side router JS library. It uses the widely adopted express.js syntax for routes (/users/:id) to map URLs to Web Component views. All features one might expect from a modern router are supported: async route resolution, animated transitions, navigation guards, redirects, and more. It is framework-agnostic and works equally well with all Web Components regardless of how they are created (Polymer / SkateJS / Stencil / Angular / Vue / etc).

Vaadin Router is a good fit for developers that do not want to go all-in with one framework, and prefer to have freedom in picking the components that work best for their specific needs.

npm install --save @vaadin/router
import {Router} from '@vaadin/router';

const router = new Router(document.getElementById('outlet'));
router.setRoutes([
  {path: '/', component: 'x-home-view'},
  {path: '/users', component: 'x-user-list'}
]);

Browser support

A specific version of Vaadin Router supports the same browsers as the Vaadin platform major version which includes that version of Vaadin Router. See Vaadin platform release notes for details on included Vaadin Router version and supported technologies. The Supported Technologies section is typically listed in the release notes of the first publicly available release of a Vaadin platform major version (for example Vaadin 18.0.1 since 18.0.0 was skipped).

Desktop browsers

Evergreen versions of the following browsers

  • Chrome, Firefox, Firefox ESR, Safari and Edge (Chromium)

Mobile browsers

Built-in browsers in the following mobile operating systems:

  • Safari starting from iOS 13 (Safari 13 or newer)
  • Google Chrome evergreen on Android (requiring Android 4.4 or newer)

Sauce Labs test status

Sauce Test Status

Big Thanks

Cross-browser Testing Platform and Open Source <3 Provided by Sauce Labs.

Running demos and tests in the browser

  1. Fork the vaadin-router repository and clone it locally.

  2. Make sure you have npm installed.

  3. When in the vaadin-router directory, run npm install and then npm run install:dependencies to install dependencies.

  4. Run npm start, and open http://127.0.0.1:8000/components/vaadin-router in your browser to see the component API documentation.

  5. You can also open demo or in-browser tests by adding demo or test to the URL, for example:

Running tests from the command line

  1. When in the vaadin-router directory, run npm test

Following the coding style

We are using ESLint for linting JavaScript code. You can check if your code is following our standards by running npm run lint, which will automatically lint all .js files as well as JavaScript snippets inside .html files.

Contributing

  • Make sure your code is compliant with our code linters: npm run lint
  • Check that tests are passing: npm test
  • Submit a pull request with detailed title and description
  • Wait for response from one of Vaadin components team members

License

Apache License 2.0

Vaadin collects development time usage statistics to improve this product. For details and to opt-out, see https://github.com/vaadin/vaadin-usage-statistics.

router's People

Contributors

abdonrd avatar dependabot[bot] avatar haijian-vaadin avatar haprog avatar jouni avatar limonte avatar manolo avatar miladkdz avatar pdurbin avatar platosha avatar qtdzz avatar someonetoignore avatar vursen avatar web-padawan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

router's Issues

(debug) auto-generated routes table

As a developer I want to review / debug the routing structure in a large app with dynamic routing, so I want to automatically generate the effective global routing table in the run time of the app (when running in the dev mode).

Implemented by design in #27 and #51.

DoD:

  • Vaadin.Router has a getRoutes() method that returns the current routing configuration as a single JSON object.

The common DoD does not apply (because this story does not introduce new code).

Page title updates

As a developer I want to update the browser window title when the current route changes.

While there is no special support for this use case, it is straightforward to implement via the onAfterEnter route component lifecycle callback (see #23):

onAfterEnter() {
  document.title = 'Title';
}

SkateJS integration

As a developer I want to use Vaadin Router with SkateJS-based route components.

DoD:

  • all features of Vaadin Router work with SkateJS-based web components
  • there is a demo for how to use SkateJS web components in a Vaadin Router app

The common DoD applies.

Route parameters

As a developer I want to extract route parameters from the current URL and render the route content based on them. This story includes path parameters (/users/:userid) but not query string parameters (/users?userid=123).

DoD:

  • The named route parameters are bound to the route component properties.
  • All route parameters (named and unnamed) are exposed to the route component as a route.parameters property.
  • There is a demo for using named and unnamed route parameters through Web Component properties.

The common DoD applies.

Styled router links

As a developer I want to have an easy way to style differently the navigation link that leads to the currently active route in order to support the common UX pattern in navigation menus.

DoD:

  • the active property should automatically be updated when the current URL changes
  • to support Polymer integration, changes in the active property should trigger active-changed events (non-bubbling)
  • if not configured otherwise, the active property should be set if the current path matches the href property
  • if an active-path string property is set, the active property should be set if the current path matches the path specified in the active-path property
  • if an active-path property is set, the default is prefix-matching. It can be changed to exact matching by adding an exact boolean property
  • there is a demo showing both the basic href matching and the path matching

The common DoD applies.

Stencil integration

As a developer I want to use Vaadin Router with Stencil-based route components.

DoD:

  • all features of Vaadin Router work with Stencil-based web components
  • there is a demo for how to use Stencil web components in a Vaadin Router app

The common DoD applies.

Bundle-specific route tables

As a developer I want to add sub-routes dynamically to allow non-monolithic app structures so that the teams working on different parts of the app are free to define the routing structures for their sub routes without a central coordination.

As a JS developer I want to do that without having to add additional web components to my app.

DoD:

  • routes configuration supports a config property which can be an object or a function that returns such object synchronously or asynchronously (via a Promise)
  • routes configuration for a sub-path can be imported from a separate file and added into the global routes config:
//-- routes/user.js:
export default [
  { path: '/', component: 'x-user-home' },
  { path: '/:user', component: 'x-user-profile' },
];
  • statically
import {Router} from '@vaadin/router';
import userRoutes from './routes/user.js';

const router = new Router(document.body);
router.setRoutes([
  { path: '/', component: 'x-home-view' },
  { path: '/users', children: userRoutes },
  { path: '(.*)', component: 'x-not-found-view' }
]);
  • or dynamically
import {Router} from '@vaadin/router';

const router = new Router(document.body);
router.setRoutes([
  { path: '/', component: 'x-home-view' },
  { path: '/users', children: (context) => import('./routes/user.js') },
  { path: '(.*)', component: 'x-not-found-view' }
]);
  • there are two demos
    -- adding a bundle-specific routes config from a static import
    -- adding a bundle-specific routes config from a lazy-loaded bundle

The common DoD applies.

<vaadin-router> DOM API (basic functionality)

As a developer I want to display different content on the page depending on the current URL.

As a Polymer developer I want to do that with HTML markup.

DoD:

  • the <vaadin-router> DOM API allows creating a router with a default router outlet, and setting a routes config with <vaadin-route> elements.
  • The route contents can be defined by a 'component' property on a <vaadin-route> element.
  • The route content can be defined by a <template> child of a <vaadin-route> element.
  • Changes to the DOM are handled and trigger a re-render if necessary:
    -- changes to the 'path' and / or 'component' properties / attributes
    -- adding / removing the child <template> element to a <vaadin-route>
    -- adding / removing child <vaadin-route> elements to a <vaadin-router>
  • add a demo for basic <vaadin-router> DOM API usage
  • the following snippet should work:
<vaadin-router>
  <vaadin-route path="/">
    <template>
      <h1>Home</h1>
    </template>
  </vaadin-route>
  <vaadin-route path="/users" component="x-user-list"></vaadin-route>
</vaadin-router>

The common DoD applies.

Generate URL for a route (with parameters)

As a developer I want to generate URLs that link to other routes of my app, so that when I define a component template I do not have to hard-code the URLs in that template. That is, instead of defining a template like

<nav>
  <a href="/myapp/users/">All Users</a>
  <a href="/myapp/users/42">Your profile</a>
<nav>

I would define it like

<nav>
  <a href="${Router.linkTo({path: '/users'})}">All Users</a>
  <a href="${Router.linkTo({path: '/users/:userid', params: {userid: 42}})}">Your profile</a>
<nav>

DoD:

  • there is a public static linkTo(route) method on the Vaadin.Router class. It accepts a route descriptor with the following properties:
    • path: a string, same as any other route path (e.g. /users/:userid)
    • params: a map where keys are route parameter names and / or indices, and values are parameter values (the same structure as the params property of a location object)
    • [after named route support is implemented] name: a string, name of a named route. Either name or path should be provided. If both a provided, name is ignored and a warning is triggered.
  • there are docs describing the new API method
  • there is a demo showing how to use the new API method

The common DoD applies.

Navigation lifecycle events

As a developer I want to define handlers for navigation lifecycle events for a route component:

  • before a navigation to the component
  • before a navigation away from the component

DoD:

  • If a route component has an onBeforeEnter method, this method is called (during the resolve pass) every time before a navigation to the component happens.
  • If the onBeforeEnter method returns something (not null nor undefined), that return value is used as a resolve pass result for the component (instead of the component itself).
  • If a route component has an onBeforeLeave method, this method is called (during the resolve pass) every time before a navigation to the component happens.
  • If the onBeforeLeave method returns something (not null nor undefined), the resolve pass ends before actually navigating to where it was going to, and that return value is used as the resolve pass result.
  • (no demos are in scope for this story because the lifecycle callbacks are demoed in the issues #24 and #25)

The common DoD applies.

Non-root deployments: in-app URLs

As a developer I want in-app URLs to work in non-root deployments by default so that I do not have to change the source code for those cases.

DoD:

  • the Vaadin.Router constructor supports setting a baseUrl property via the options argument
  • the default value is taken from <base> tag (if any)
  • the router.baseUrl property is a part of the public API
  • the baseUrl property is available for view Web Components as location.baseUrl
  • in the example below the Home and Profile links get handled by Vaadin Router: The URL in the browser address bar changes to /ui and /ui/users/guest respectively and the corresponding view Web Component is rendered without reloading the page.
  • in the example below the Shop link gets handled by the browser: A network request gets triggered and the page is reloaded.
<base href="/ui/">

<nav>
  <a href=".">Home</a>
  <a href="user/guest">Profile</a>
  <a href="/shop">Shop</a>
</nav>

<main></main>

<script>
  const router = new Router(
    document.querySelector('main'),
    {baseUrl: '/ui/'} // this is optional because it's exactly the same as the <base> tag
  );
  router.setRoutes([
    {path: '/', component: 'home-view'},
    {path: '/user/:id', component: 'user-list-view'},
    {path: '(.*)', component: 'not-found-view'},
  ]);
</script>
  • there is a demo of how to serve the app on a non-root URL (how to use the <base> tag or the baseUrl property, how to write appropriate hrefs in <a> tags, how to use the location.baseUrl property in view components to generate correcr in-app URLs)

In-app navigation with regular <a> links

As a developer I want to use Vaadin.Router with regular <a> links. If the href property on the link points to the same origin as the app's base URL, and Vaadin.Router is configured to listen to click events, then clicks on such links should be handled by Vaadin.Router instead of the browser's default handler (that triggers a full page reload).

As Flow I want Vaadin.Router to support using <a router-link> links for in-app navigation so that the future versions of Vaadin Flow could switch to Vaadin.Router instead of the own implementation.

This should be an opt-in feature (i.e. the app should not include any source code for it unless it's actually used) because some non-Flow apps may choose to use <vaadin-router-link> links instead.

DoD:

  • Vaadin.Router has a static method to change the events it listens for navigation.
  • There is a demo for in-app navigation without <vaadin-router-link>s.

The common DoD applies.

Polymer integration

As a developer I want to use Vaadin Router with Polymer-based route components.

DoD:

  • all features of Vaadin Router work with Polymer-based web components
  • there is a demo for how to use Polymer 2 / 3 web components in a Vaadin Router app

The common DoD applies.

Route lazy-loading

As a developer I want to lazily load the bundles required to render a route, so that page load times remain low and user experience is good.

DoD:

  • the route config JS API supports a bundle property. If the property is set for a route, during the resolve pass the router would automatically load the bundle from the given URL before returning the route component
  • if the bundle URL ends with .html the router loads the bundle as an HTML import
  • if the bundle URL ends with .js the router loads the bundle as a ES module
  • The following snippet should work:
router.setRoutes([
  {
    path: '/about',
    bundle: 'bundles/about-bundle.html',
    component: 'x-about-view'
  }, {
    path: '/user',
    bundle: 'bundles/user-view.js',
    component: 'x-user-view'
  }
]);
  • there is a demo of lazy bundle loading

The common DoD applies.

vaadin-license-checker for Vaadin.Router

In order to make the vaadin-router-core a commercial product, Vaadin Ltd. needs to add a license checker to it (same as is used for commercial Vaadin web components). The existing front-end license checker is designed for Web Components and is not designed for non-WC NPM packages. This task is to figure a way of using the license checker component with vaadin-router-core.

Animated transitions

As a developer I want to add CSS animations to route transitions so that I can implement the common app-like visual design patterns for page transitions (like swipes).

Use the FLIP animation technique to ensure smooth 60fps animations.

Query string parameters

As a developer I want to extract route parameters from the current URL and render the route content based on them. This include path parameters (/users/:userId) and query string parameters (/users?sort=asc).

Fallbacks (404s)

As a developer I want to handle the case when the current URL does not match any of the routes I have defined, and display fallback content in that case.

DoD:

  • In the Vaadin.Router JS API the promise returned from the render() method gets rejected if no content is rendered.
  • It's possible to add a route with the path='*'. It matches any path and if it is the last in the list of routes, it works as a fallback option. (The exact syntax for the match all pattern may vary).
  • There can be partial fallbacks (e.g. /users/*)
  • The fallback route should be correctly displayed for all kinds of malformed URLs including /repeating///slashes/in//path
  • There is a demo showing how to define a fallback route.

The common DoD applies.

<vaadin-route> DOM API

As a Polymer developer I want to define route properties declaratively using the element, and have access to all the same features that the JS API provides.

DoD:

  • the 'component' property works
    -- for a single router outlet
    -- for multiple router outlets the syntax is like in component.main="x-home-view" / component.sidebar="x-home-sidebar"
  • the bundle property works (including the implicit component names feature)
  • the redirect property works

The common DoD applies.

Async route resolution

As a developer I want to perform asynchronous operations in my route's action() method (e.g. make a network request and return a result based on the response).

The functionality is implemented by design in #13, but the demo is missing.

DoD:

  • the return type of the route's action(context) method is a Promise
  • there is a demo of async route resolution

The common DoD applies.

Set up continuous integration (CI)

In order to ensure the required product quality level there should be continuous automatic quality control.

DoD:

  • for each PR there is a quick check:
    -- run all tests in at least one local browser
    -- measure the code coverage in at least one local browser
    -- measure the library size in bytes (minified, gzipped)
  • for each commit to the master branch there is a full check:
    -- run all tests in all supported browsers
    -- measure the code coverage for own code in at least one local browser
    -- measure the library size in bytes (minified, gzipped)
  • if at least one of the quality criteria is not met, the check prevents merging the PR / indicates a build failure for the master branch
  • both the quick and the full checks can be run locally from a developer's environment with a simple command (to allow troubleshooting in cases of CI test failures)

Unconditional redirects

As a developer I want to unconditionally redirect users from one URL to another so that when a page changes its URL the old URL would still work (e.g. /team -> /company/team).

DoD:

  • The route config JS API supports a redirect property. If a route with this property is visited during the resolve pass, the resolve pass completes with a 'redirect' result.
  • When a resolve pass completes with such a 'redirect' result, it triggers a new resolve pass using the value of the redirect property as a parameter to the resolve(pathnameOrContext) method.
  • Unconditional redirects work for routes both with and without parameters
  • The following snippets should work:
router.setRoutes([
  { path: '/about', redirect: '/company/about' },
  { path: '/company/about', component: 'x-about-view' },
  { path: '/users/:user', component: 'x-user-view' },
  { path: '/u/:user', redirect: '/users/:user' },
]);
  • There is a demo showing how to use unconditional redirects with and without parameters

The common DoD applies.

Publish to npm

As a developer I want to install the @vaadin/router package from npm so that I can use Vaadin.Router in my npm-based front-end projects.

DoD:

  • npm install --save @vaadin/router works (installs a package)
  • the @vaadin/router package has an ES module bundle (it works in any browser that supports static ES modules: <script type="module">)
  • the @vaadin/router package has an UMD bundle (it works in the browsers that do not support static ES modules: <script nomodule>)
  • the UMD module adds its exports into the global.Vaadin namespace. If the namespace object does not exist, it is created. If does exist, the exports are appended into the existing object.
  • the installed @vaadin/router package does not contain unnecessary files (tests, demos, linter configs, etc)

Nested router outlets (multiple router instances)

As a developer I want to add sub-routes dynamically to allow non-monolithic app structures so that the teams working on different parts of the app are free to define the routing structures for their sub routes without a central coordination.

As a Polymer developer I want to do that by adding a router outlet into a bundle layout component's template (that is itself rendered in a router outlet).

DoD:

  • the routes defined in a nested vaadin-router are rendered in the same resolve pass as root route component
  • if a route in a nested vaadin-router component prevents a transition, the outer router also stops the resolve pass
  • there is a demo of using nested vaadin-router elements

The common DoD applies.

vaadin-usage-statistics for Vaadin.Router

In order to make the vaadin-router-core product comparable to Vaadin UI components, Vaadin Ltd. needs to gather the same usage statistics for it as are gathered for Vaadin Web Components. The existing way of gathering it is designed for Web Components and is not designed for non-WC NPM packages. This task is to figure a way of gathering it for vaadin-router-core (or to conclude that it's not needed).

DoD:

  • the same usage stats are collected for the vaadin-router-core package as are collected for Vaadin Components via vaadin-usage-statistics
  • OR there is a decision to not gather usage statistics for the vaadin-router-core package

<vaadin-router-link> for in-app navigation

As a developer I want to add links that trigger an in-app navigation and change the current URL (without a full page reload).

DoD:

  • The web component acts as a <a> tag but instead of triggering a network request update the HTML5 History state and triggers a popstate event.
  • The basic Vaadin.Router demo is updated to use the <vaadin-router-link> elements

The common DoD applies.

Router demo component for docs

As a developer I want to see interactive demos for the router component on the docs page (similar to the react-router online demos).

DoD:

The common DoD does not apply.

Routing config JS API

As a developer I want to have a JS API to add / remove routes at the run time, so that I can add routes from a bundle or a route component.

Adding sub-routes dynamically allows non-monolithic app structures so that the teams working on different parts of the app are free to define the routing structures for their sub routes without a central coordination.

DoD:

  • the router JS API has methods to get / add / remove routes
  • it should be possible to add routes from inside a route action so that the added routes are visited in the same resolve pass (i.g. add a /users/:user route inside the /user route action so that calling context.next() after router.addRoutes() would go to the new route).
  • no demos since this is mostly an internal feature - the user value comes from the stories this feature enables

The common DoD applies.

Navigation JS API

As a developer I want to trigger navigation imperatively from JS, and to add custom listeners for navigation events.

DoD:

  • Vaadin.Router has a public static go(pathname) method that updates the browser URL, triggers a popstate event and calls the router's render(pathname) method (returns its result).
  • Vaadin.Router dispatches a vaadin-router:route-changed event on window every time after completing a render pass
  • there is a demo for both features

The common DoD applies.

Publish to Bower

As a developer I want to install the vaadin/vaadin-router package from Bower so that I can use <vaadin-router> in my Polymer 2 projects.

  • bower install --save vaadin/vaadin-router works (installs a package)
  • the vaadin/vaadin-router package contains HTML imports for the Polymer 2 versions of web components (vaadin-router, vaadin-route, etc) and the UMD bundle from the @vaadin/router package (without the Polymer 3 versions of web components)
  • the installed vaadin/vaadin-router package does not contain unnecessary files (tests, demos, linter configs, etc)

Vue integration

As a developer I want to use Vaadin Router with Vue-based route components.

DoD:

  • all features of Vaadin Router work with Vue-based web components
  • there is a demo for how to use Vue web components in a Vaadin Router app

The common DoD applies.

View caching

As a developer I want to control when route components are disposed after the user navigates away from them, so that I can set the right balance between resource consumption, performance and UX:

  • keeping stale views in the DOM / memory consumes browser resources
  • repeat navigation to an already rendered view is faster
  • transient UI state is discarded when a view is disposed and sometimes it’s nice to keep it

Dynamic redirects

As a developer I want to dynamically redirect users from one URL to another to support authentication flows (e.g. if the user is not authenticated /profile -> /login?return=/profile).

DoD:

  • A resolve pass can complete with a 'redirect' result, i.e. a result with a redirect property.
  • When a resolve pass completes with such a 'redirect' result, it triggers a new resolve pass using the value of the redirect property as a parameter to the resolve(pathnameOrContext) method.
  • The users of the JS API can define a route's action() method so that it returns an object with a redirect property.
  • A route component can return a 'redirect' result from its onBeforeEnter callback.
  • There are two demos:
    -- redirecting from an onBeforeEnter callback
    -- redirecting from a custom route action() method

The common DoD applies.

Use exact route matching in Vaadin.Resolver by default

As a developer I want exact route matching to be the default so that the routing config is more intuitive and wrong URLs are easier to detect.

DoD:

  • Vaadin.Resolver is updated so that if a route does not have an exact property it matches a route only if the given pathname exactly matches the route path (trailing slashes are optional).
  • the specs for resolveRoute and Vaadin.Resolver are updated

Route 'active' state tracking

As a developer I want to detect events when a route becomes 'active' (i.e. it gets visited in a resolve pass, while it was skipped by the previous resolve pass), and 'inactive' (i.e. an 'active' route does not get visited in a resolve pass).

While this feature might not have a direct user value, it is a prerequisite for a number of other stories.

DoD:

  • there is an activeRoutes read-only array property on the router object. It is an array containing the full chain of routes that were traversed in the last render's resolve pass--from the root to a leaf. Initially it is an empty array.

  • the activeRoutes array is updated to the new routes chain every time when a render pass is completed, after the router outlet content is updated.

  • a route object may have an inactivate property (function (context) => Promise<RenderResult>). During each render's resolve pass a new activeRoutes chain is constructed (starting from the root route). As each new route is added to the new activeRoutes chain, the new chain is compared to the last activeRoutes chain. As long as the active routes in the new chain remain the same as they were in the last chain, no additional actions are taken. When the new active chain is about to diverge from the last active chain (i.e. when the new resolve pass is about to resolve a route which was not a part of the last resove chain), the tail of the last active route chain is 'inactivated' before the new route resolution starts.

    Example:
    Routes config:

  [
      {path: '/', component: 'x-home-view'},
      {path: '/users', component: 'x-users-list-view'},
      {path: '/users/new', component: 'x-new-user-view'},
      {path: '/users/:user', component: 'x-user-profile-view'},
  ]

Last active route chain: ['/', '/users', '/users/:user']

The new pathname to render: '/users/new'

The new active route chain before calling resolveRoute() for the '/users/new' route: ['/', '/users']. It matches the beginning of the last active route chain.

The '/users/new' route, when appended to the new active routes chain, would make it diverge from the last active route chain: the 3rd item in the array is going to be different.
At that point, before calling 'resolveRoute' for the '/users/new' route, the tail of the last active route chain after the divergence point is 'inactivated'. It's only one route in this example: '/users/:user'. In a generic case, all views in that chain should be inactivated in sequence starting from the end of the chain.

  • 'Inactivating' a route without the inactivate property is a no-op.
  • 'Inactivating' a route with the inactivate property means that the function defined by that property is called with the current render context. If the inactivate function returns a non-null, non-undefined result, the render pass ends with that result and the active route chain does not change (i.e. inactivation is prevented).
  • If a render's resolve pass ends, and the new active routes chain is shorter than the last active routes chain, the tail of the last active routes chain is 'inactivated' before the render is completed. E.g. when navigating from '/users/sam' to '/users' the '/users/:user' route should be successfully inactivated before the new view chain can become active.
  • (no demos--this is an internal feature--but thorough testing)

The common DoD applies.

Implicit route components

As a developer I want to avoid boilerplate and rely on smart defaults when defining routes config. For instance, for routes with the bundle property if

  • the bundle is an ES module
  • and it has a default export
  • and this default export is a class
  • and it extends HTMLElement

then the bundle's default export should be used as the route component by default.

If a route has both the bundle and the component properties, the explicit component property should be used.

DoD:

  • in the following snippet the component property is unnecessary
router.setRoutes([
  {
    path: '/about',
    bundle: './src/x-about-view.mjs',
    component: 'x-about-view'
  }
]);

The common DoD applies.

Vaadin.Router JS API (basic functionality)

As a developer I want to display different content on the page depending on the current URL. As a JS developer I want to do that purely with JavaScript.

DoD:

  • the Vaadin.Router JS API allows creating a router, setting a routes config with a plain JSON-like structure, and rendering to DOM. The route contents is defined by a 'component' route property.
  • Vaadin.Router automatically subscribes to navigation events, so that I do not have to write boilerplate popstate event listener code.
  • add a demo for basic JS API usage for Vaadin.Router
  • The following snippet should work
import {Router} from '@vaadin/router';

const router = new Router(document.body);
router.setRoutes([
    { path: '/', component: 'x-home-view' },
    { path: '/users',
      children: [
        { path: '/', component: 'x-user-list' },
        { path: '/:user', component: 'x-user-profile' }
      ]
    },
    { path: '', component: 'x-not-found-view' }
  ]);

The common DoD applies.

Reduce the bundle size with Google Closure Compiler

Investigate whether or not using the Google Closure Compiler reduces the minified gzipped bundle size for the core package. If so, switch from uglify-es onto google-closure-compiler for production builds.

DoD:

  • build the core package with gcc and make sure all tests pass
  • measure the difference in the prodution bundle size between gcc and uglify-es
  • if gcc produces a smaller bundle, replace uglify-es with gcc
  • in any case write a summary of the findings in this ticket

Multiple router outlets

As a developer I want to have several sections on the page that change their content based on the current route to support the use case when both the main part of the page and the sidebar have the route-dependent content.

DoD:

  • the Vaadin.Resolver resolve() method returns either a single HTMLElement result or an object containing several named HTMLElement properties
  • the Vaadin.Router constructor accepts either a single Node for the router outlet or an object with several named Node properties (several named router outlets)
  • If the resolve pass returns several named results, each result is rendered into a matching router outlet
  • The route config JS API supports the component property to be either a string or an object where property names are outlet names, and property values are components that should be rendered in the corresponding outlets.
  • The following snippet should work
import {Router} from '@vaadin/router';

const router = new Router({
  main: document.getElementById('main'),
  sidebar: document.getElementById('sidebar')
});
router.setRoutes([
  { path: '/',
    exact: true,
    component: {
      main: 'x-home-view',
      sidebar: 'x-home-sidebar'
    }
  }
]);
  • There is a demo for multiple router outlets

Integrate the source and tests of `universal-router` into the project

The Vaadin.Resolver class in the vaadin-router-core package has an API / offers a feature set similar to that of the universal-router library. However it cannot use the existing library 'as-is' because there are also a few significant differences. Since the universal-router library is MIT licensed it is possible to make a custom fork of it and use that in the source code of the vaadin-router-core package.

This task is to incorporate the source and the tests of the universal-router library into the vaadin-router-core package (and remove an NPM dependency). This will set the stage for further extensions and customization.

DoD:

  • there is no NPM dependency on the universal-router package
  • the source code of the universal-router library is included into the vaadin-router-core source
  • the tests from the universal-router package are a part of the vaadin-router-core test suite
  • the questions of attribution are correctly addressed:
    -- does the universal-router library license need to be included / distributed with the vaadin-router-core package?
    -- do the library authors need to be mentioned in the vaadin-router-core code / license?

Preventing transitions

As a developer I want to subscribe to navigation events and prevent a transition (e.g. when navigating from a view that has unsaved data).

DoD:

  • A resolve pass can complete with a 'cancel' result, i.e. a result with a cancel: true property.
  • When a resolve pass completes with such a 'cancel' result, it restores the URL to what is was before the resolve pass has started
  • The users of the JS API can define a route's inactivate() method so that it returns an object with a cancel property.
  • A route component can return a 'cancel' result from its onBeforeLeave callback.
  • There are two demos:
    -- preventing navigation from an onBeforeLeave callback
    -- preventing navigation from a custom route inactivate() method

The common DoD applies.

Parent layouts

As a developer I want to define a common parent layout for a list of child routes so that the common parts of the page layout are defined only once.

As a JavaScript developer, I want to do that purely in JS without using special additional Web Components.

DoD:

  • if a route with children defines a component, any content returned when resolving a child route is added as a light DOM child to the parent root's component. The parent's root component with a child is returned back.
  • there is a demo of using a parent layout with <slot>s and light DOM children

The common DoD applies.

Route parameters for inline templates

As a developer I want to extract route parameters from the current URL and render the route content based on them. This story includes path parameters (/users/:userid) but not query string parameters (/users?userid=123).

As a Polymer developer I want to access route parameters in inline route templates.

DoD:

  • If Polymer.Templatize is defined the route parameters are available for Polymer data binding inside inline route templates both as named properties and as route.parameters.
  • Note: this feature does not create a dependency on Polymer - it is only available for the apps that already use Polymer.
  • There is a demo for using named and unnamed route parameters in an inline template (required Polymer)

The common DoD applies.

Ambiguous matches

As a developer I want to define ambiguous URL matching rules (i.e. several routes would match at the same time) so that I could have shorter URLs in my app. E.g. /company, /about and /:user instead of /company, /about and /users/:user. When the rules are ambiguous the order in which the rules are defined should determine the matching route.

DoD:

  • The following sample should work as expected (/ matches the home view, /about matches the about view, /anything/else matches the user view)
router.setRoutes([
  { path: '/', exact: true, component: 'src/x-home-view.html' },
  { path: '/about', component: 'src/x-about-view.html' },
  { path: '/:user', component: 'src/x-user-view.html' },
]);
  • There is a demo showing that the order in which the routes are defined matters

The common DoD applies.

<vaadin-router> JS API (basic functionality)

As a developer I want to display different content on the page depending on the current URL. As a Polymer developer I want to do that with HTML markup, but I also want to interact with the router via a JS API.

DoD:

  • the <vaadin-router> JS API allows
    -- adding / removing routes
    -- getting / setting the entire routes config
    -- getting / setting the router options
    -- triggering the router to re-render
  • the <vaadin-router> JS API can be combined with its DOM API. e.g. the routes defined in the DOM are included into the list returned by the getRoutes() method
  • add 2 demos
    -- basic <vaadin-router> JS API usage
    -- a combination of the JS API and DOM API

The common DoD applies.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.