Skip to content

invisiblethemes/pinecone-router

 
 

Repository files navigation

GitHub tag (latest by date) npm bundle size Downloads from JSDelivr npm Changelog Sponsor

Pinecone Router

The extendable client-side router for Alpine.js v3.

About

An easy to use but feature-packed client-side router for use with Alpine.js.

It can be used to:

  • Register routes & process route variables.
  • Use magic helper $router helper to display elements dynamically etc. inside all Alpine.js Components.
  • Many more using middlewares!.

Features:

  • 😄 Easy and familiar syntax well integrated with Alpine.js.
  • 🔗 Automatically dispatch relative links and handle them.
  • Magic $router helper to access current route, params, redirect, ect. from all alpine components!
  • #️⃣ Hash routing.
  • ➕ Extendable using tiny Middlewares!.

Demo: Pinecone example, (source code).

Installation

Check the CHANGELOG before updates.

CDN

Include the following <script> tag in the <head> of your document, before Alpine.js:

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/router.min.js"></script>

ES6 Module on the browser:

import PineconeRouter from 'https://cdn.jsdelivr.net/npm/[email protected]/dist/router.esm.js'
import Alpine from 'https://esm.sh/alpinejs'
Alpine.plugin(PineconeRouter)
Alpine.start()

NPM

npm install pinecone-router
// load pinecone router
import PineconeRouter from 'pinecone-router'
// then load alpine.js
import Alpine from 'alpinejs'
// add the router as a plugin
Alpine.plugin(PineconeRouter)
// start alpine
Alpine.start()

Usage

Declare routes

Declare routes by creating a template tag with x-route and optionally an x-handler attribute.

Note: alternatively you can use Javascript to add routes

Without x-handler

<!-- register the route, no need for a handler-->
<template x-route="/profile/:id"></template>

<!-- now you can use the route in anyway you'd like! -->
<template x-if="$router.route == '/profile/:id'">
	<div>profile <span x-text="$router.params.id"></span></div>
</template>

More about $router helper

With x-handler

<div x-data="router()">
	<!-- You can pass in a function name -->
	<template x-route="/" x-handler="home"></template>
	<!-- Or an anonymous/arrow function -->
	<template x-route="/home" x-handler="(ctx) => ctx.redirect('/')"></template>
	<!-- Or even an array of multiple function names/anonymous functions! -->
	<!-- To prevent the next handlers from executing return 'stop' from the previous handler` or redirect -->
	<template x-route="/hello/:name" x-handler="[checkName, hello]"></template>
	<!-- 404 handler -->
	<template x-route="notfound" x-handler="notfound"></template>
</div>

<div id="app"></div>

The javascript:

can also be embedded inside x-data.

function router() {
	return {
		home(context) {
			document.querySelector('#app').innerHTML = `<h1>Home</h1>`
		},
		checkName(context) {
			if (context.params.name.toLowerCase() == 'rafik') {
				console.log('we have the same name!')
			}
		},
		hello(context) {
			document.querySelector(
				'#app'
			).innerHTML = `<h1>Hello, ${context.params.name}</h1>`
		},
		notfound(context) {
			document.querySelector('#app').innerHTML = `<h1>Not Found</h1>`
		},
	}
}

Multiple Handlers for a single route

To prevent / stop the next handlers from executing return 'stop' from the previous handler or return $router.redirect('/some/path')

Context Object

Contains information about the current route. This available at all times:

Using the $router magic helper in Alpine components

From Javascript using window.PineconeRouter.currentContext

Every handler method takes the context object as the only argument

  • context.route (/path/:var) The route set with x-route.
  • context.path (/path/something) The path visited by the client.
  • context.params ({var: something}) Object that contains route parameters if any.
  • context.hash hash fragment without the #
  • context.query search query without the ?
  • context.redirect(path: string) function that allow you to redirect to another page.
    • Note: usage within x-handler: return context.redirect('/path');
  • context.navigate(path: string) same as clicking a link

Using magic helper: $router.params.id, $router.route, etc

Route matching

Parameters can be made optional by adding a ?, or turned into a wildcard match by adding * (zero or more characters) or + (one or more characters):

<template x-route="/b/:id" x-handler="..."></template>
<template x-route="/a/:optional?/:params?" x-handler="..."></template>
<template x-route="/c/:remaining_path*" x-handler="..."></template>
<template x-route="/d/:remaining_path+" x-handler="..."></template>

Borrowed from Preact Router

Redirecting

From an Alpine component:

Redirecting from the handler:

To redirect from inside a handler function return the context's redirect method:

This will stop any other handlers from executing

handler(context) {
	...
	return context.redirect(path)
}

Important: inside the handler you must return the context.redirect() function.

return context.redirect(path) will prevent execution of any other handelers that are after this one

if you wish to prevent execution of other handlers without redirecting use return 'stop'

Middlewares

Pinecone Router is extendable through middlewares!

Allows you to set the path for an HTML file and it'll be fetched and displayed in the specified element (#app by default).

Create your own middlewares using this template!

Settings:

<script>
	document.addEventListener('alpine:initialized', () => {
		window.PineconeRouter.settings.hash = false // use hash routing
		window.PineconeRouter.settings.basePath = '/' // set the base for the URL, doesn't work with hash routing
	})
</script>

Bypass link handling

Adding a native attribute to a link will prevent Pinecone Router from handling it:

<a href="/foo" native>Foo</a>

Loading bar

You can easily use nProgress.

if you're going to fetch pages, you can use views middleware which provide loading events

Demo Source

Advanced

Adding & Removing routes with Javascript

you can add routes & remove them anytime using Javascript.

Adding a route:

window.PineconeRouter.add(path, options)
  • path: string, the route's path.
  • options: array of options that can be anything for example: {handlers: [], view: '/home.html'}

Removing a route:

window.PineconeRouter.remove(path)
  • path: string, the path of the route you want to remove.

Navigating from Javascript:

To navigate to another page from javascript you can use:

window.PineconeRouter.currentContext.navigate(path)

Compatibility

Version Alpine.js Version
^v2.x v3
v1.x v2

Contributing:

Please refer to CONTRIBUTING.md

Credits

This library uses modified chunks of code from this tutorial & from page.js.

Acknowledgment

@KevinBatdorf for many ideas and early feedback!

Disclaimer: Not affiliated with the Alpine.js team, developed independently.

Versioning

This projects follow the Semantic Versioning guidelines.

License

Copyright (c) 2023 Rafik El Hadi Houari and contributors

Licensed under the MIT license, see LICENSE.md for details.

Creative Commons License
Pinecone Router Logo by Rafik El Hadi Houari is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.

Code from Page.js is licensed under the MIT License. Copyright (c) 2012 TJ Holowaychuk [email protected]

Code from Simple-javascript-router tutorial is licensed under the MIT License. Copyright (c) 2021 Vijit Ail (https://github.com/vijitail).

Route matching function from Preact Router is licensed under the MIT License. Copyright (c) 2015 Jason Miller

About

The extendable client-side router for Alpine.js v3

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • TypeScript 96.0%
  • JavaScript 3.6%
  • SCSS 0.4%