GithubHelp home page GithubHelp logo

zyxd / svelte-store-router Goto Github PK

View Code? Open in Web Editor NEW
91.0 3.0 5.0 109 KB

Store-based router for Svelte

Home Page: https://svelte-store-router-demo.vercel.app

License: MIT License

JavaScript 86.93% Svelte 13.07%
svelte router store state javascript frontend browser node ssr svelte-pathfinder

svelte-store-router's Introduction

Store-based router for Svelte | Demo

Inspired by the svelte-pathfinder by PaulMaly

A completely different approach of routing. State-based router suggests that routing is just another global state and History API changes are just an optional side-effects of this state.

How it works (russian language)

Features

  • Just another global state;
  • It doesn't impose any restrictions on how to apply this state to the application;
  • Manipulate different parts of a state (path / query / fragment) separately;
  • Automatic parsing of the query and fragment parameters;
  • Components for path matching and parameters extracting (using regexparam);
  • Configurable delay of History changing;
  • Converting query and fragment string values to JavaScript types;
  • Cleaning query and fragment from empty values like a null / undefined / '';
  • Automatically handling <a> navigation what allow updating the route state without reloading the page;
  • Works fine with SSR.

Install

npm i svelte-store-router --save-dev

Usage

Create a route store in your stores.js:

import { createRouteStore } from 'svelte-store-router'

export const route = createRouteStore({
  delay: 300,
  queryClean: true,
  fragmentClean: true
})

Now you can access it as usual store.

<script>
  import { route } from './stores.js'
</script>

Full route:   {$route}
Path:         {$route.path}
Query:        {$route.query}
Fragment:     {$route.fragment}

You can change it.

<button on:click={() => $route.path = '/'}>home page</button>
<button on:click={() => $route.path = '/users'}>user list</button>

<button on:click={() => $route.query.sort = 'name'}>sort by name</button>
<button on:click={() => $route.query.team = 'svelte'}>filter by team</button>

<button on:click={() => $route.fragment.modal = true}>open modal window</button>
<button on:click={() => $route.fragment.scroll = 5}>skip first 50 users</button>

You can bind store values.

<textarea placeholder="fragment.search" bind:value={$route.fragment.search}/>

You can navigate to the full path you want by assigning a string value to the store or by calling the store's goto function (without $). Don't forget that the route must be relative to the base path. So calling goto('https://google.com') with base: '/test' redirects you to /test/https://google.com.

<button on:click={() => $route = '/users?orderBy=karma&limit=10'}>show top 10 users</button>
<button on:click={() => route.goto('/users?orderBy=karma&limit=10')}>show top 10 users</button>

You can match path pattern and parametrize it (regexparam).

<script>
  import { Match } from 'svelte-store-router'
  import { route } from './stores.js'
</script>

<Match route={$route} pattern="/users">
  User list
</Match>
<Match route={$route} pattern="/users/:id" let:params={{ id }}>
  User {id} profile
</Match>

You can show only first matching path.

<script>
  import { Match, Matcher } from 'svelte-store-router'
  import { route } from './stores.js'
</script>

<Matcher>
  <Match route={$route} pattern="/users">
    User list
  </Match>
  <Match route={$route} pattern="/users/:id" let:params={{ id }}>
    User {id} profile
  </Match>
  <Match route={$route}>
    Page not found
  </Match>
  <Match route={$route}>
    This content will never be displayed, because
    the previous <Match> handle all possible routes
  </Match>
</Matcher>

You can use nested match components using the loose parameter.

<script>
  import { Match, Matcher } from 'svelte-store-router'
  import { route } from './stores.js'
</script>

<Matcher>
  <Match route={$route} pattern="/users" loose>
    Begin of users template
    <Matcher>
      <Match route={$route} pattern="/users">
        Users list
      </Match>
      <Match route={$route} pattern="/users/:id" let:params={{ id }}>
        User {id} profile
      </Match>
    </Matcher>
    End of users template
  </Match>
  <Match route={$route}>
    Page not found
  </Match>
</Matcher>

Or you can do it all above manually using match function instead of components.

<script>
  import { match } from 'svelte-store-router'
  import { route } from './stores'

  let params
</script>

<!--
  It is recommended to first check if the route matches the base path of application by 
  calling `match($route)`. Not necessary if the application will always be in the root path.
-->
{#if match($route)}
  {#if match($route, '/users', true)}
    Begin of users template
    
    {#if params = match($route, '/users/:id')}
      User {params.id}
    {:else if params = match($route, '/users/:id/friends')}
      User {params.id} friends
    {/if}

    End of users template
  {:else}
    Page not found
  {/if}
{/if}

Options

base [String]

Base path of application. Routes and links which not match under this path will not be handled. '' by default.

delay [Number]

Sets delay in milliseconds before history.pushstate was called. This prevents a large number of items from appearing in History state. For example, it could be useful when the parameter of query or fragment is binded with the search input field. 0 by default.

queryParse, fragmentParse [Boolean]

Enables query and fragment string to objects conversion. true by default.

queryTyped, fragmentTyped [Boolean]

Converts query and fragment string values to JavaScript types. true by default. For example strings will be converted from -> to:

"1"         -> 1
"0.123"     -> 0.123
"true"      -> true
"null"      -> null
"undefined" -> undefined
"01234"     -> 1234
"a1234"     -> "a1234"

queryClean, fragmentClean [Boolean]

Clean query and fragment from empty (null / undefined / "") values. Might be useful to avoid /path?page=undefined&search=. false by default.

queryShortBoolean, fragmentShortBoolean [Boolean]

Automatically shortens the parameter string for boolean values, e.g. a=true&b=false&c=true into a&c. So for parameters with true only the parameter name will be shown, and with false they will be hidden completely. false by default.

sideEffect [Boolean]

Controls side effect of route changing which push items to History. true by default in browser, always false on server side.

handleNavigation [Boolean / String]

Toggles a navigation handler that automatically intercepts <a> clicks, updating the route state without reloading the page. Adding a rel="external" attribute to a <a> will trigger a usual browser navigation when the link is clicked. In addition to boolean, can contain a string with CSS selectors (e.g. ".foo, #bar, form") for elements only within which <a> clicks should be handled. true by default.

autoClearParams [Boolean]

This option toggles automatically clear the query and fragment when the path is changed. false by default.

svelte-store-router's People

Contributors

dkaoster avatar zyxd 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

Watchers

 avatar  avatar  avatar

svelte-store-router's Issues

Error in Webpack: Module not found

When compiling with Webpack, I get these errors:

WARNING in ./resources/js/stores/stores.js 3:21-37
export 'createRouteStore' (imported as 'createRouteStore') was not found in 'svelte-store-router' (possible exports: )
 @ ./resources/js/pages/App.svelte 22:0-41 261:16-21 262:29-34 275:2-7
 @ ./resources/js/fbk.js 1:0-37 3:16-19

ERROR in ./node_modules/svelte-store-router/src/node_modules/components/Match.svelte 20:0-36
Module not found: Error: Can't resolve 'functions/match' in 'node_modules/svelte-store-router/src/node_modules/components'
 @ ./node_modules/svelte-store-router/src/index.mjs 3:0-58 3:0-58
 @ ./resources/js/pages/App.svelte 21:0-53 112:14-19 122:14-19 198:15-22 273:2-7 274:2-9
 @ ./resources/js/fbk.js 1:0-37 3:16-19

ERROR in ./node_modules/svelte-store-router/src/index.mjs 1:0-72
Module not found: Error: Can't resolve 'functions/createRouteStore' in 'node_modules/svelte-store-router/src'
 @ ./resources/js/pages/App.svelte 21:0-53 112:14-19 122:14-19 198:15-22 273:2-7 274:2-9
 @ ./resources/js/fbk.js 1:0-37 3:16-19

ERROR in ./node_modules/svelte-store-router/src/index.mjs 2:0-50
Module not found: Error: Can't resolve 'functions/match' in 'node_modules/svelte-store-router/src'
 @ ./resources/js/pages/App.svelte 21:0-53 112:14-19 122:14-19 198:15-22 273:2-7 274:2-9
 @ ./resources/js/fbk.js 1:0-37 3:16-19

I am not a JS or Webpack expert but I am using several other packages without issue. I see inside the src directory there is a node_modules directory which I don't see in other packages, and wherein reside the files webpack is trying to find but can't. I don't know if that is an issue or not, maybe I am just doing something dumb?

Recommended Approach(es) For SSR Isn't Documented

Hi, I see this library doesn't inherit a url parameter as others do. I would like to take your advice on the SSR case, if possible. Should I just set $route.path before rendering? Or something else I could do.

What about nested routes?

What about nested pages?

E.g.:

  1. Users Index (the list and the detail can change)

    1. Users Sidebar

    2. User Detail

      1. User Edit
      2. User Show

I hope I explained myself.

Query and fragment as a string

At the moment only $route has the toString() function, which allows to display the full route as /path?a=1&b=2#c=3.

Does it make sense to add $route.query.toString() to get ?a=1&b=2 and $route.fragment.toString() to get #c=3?

The problem is that $route.query and $route.fragment are objects and a name conflict may occur if you need to use the name toString as the property of query / fragment.

Make Svelte a peerDependency

You ought to make Svelte a peerDependency of this package and a devDependency, but not a direct dependency. This package, otherwise, is locked to a single version of svelte, even though it's not in-fact locked and woudl work fine for any svelte >2

Update URL on new assignment to $route.path

When using <a href="/users">users</a> the URL is changed accordingly, but not when using <button on:click={() => ($route.path = '/users')}>user list</button>. I'm not sure if this is an oversight, or by design, but it makes this tool very confusing to get up and running with. Consider changing your documentation to something like <button on:click={() => (window.location.assign('/users'))}>user list</button> instead or update the code to change url on assingments to $route.path in the same manner as you do for $route.query... and fragment.

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.