diff --git a/dist/ko-component-router.js b/dist/ko-component-router.js index 2b5332d..b3e5ee0 100644 --- a/dist/ko-component-router.js +++ b/dist/ko-component-router.js @@ -226,7 +226,7 @@ return /******/ (function(modules) { // webpackBootstrap createViewModel: function createViewModel(routerParams, componentInfo) { var el = componentInfo.element; var bindingCtx = ko.contextFor(el); - return new Router(el, bindingCtx, routerParams); + return new Router(el, bindingCtx, ko.toJS(routerParams)); } }; diff --git a/dist/ko-component-router.min.js b/dist/ko-component-router.min.js index 8a13fd9..260095b 100644 --- a/dist/ko-component-router.min.js +++ b/dist/ko-component-router.min.js @@ -1,2 +1,2 @@ -(function webpackUniversalModuleDefinition(root,factory){if(typeof exports==="object"&&typeof module==="object")module.exports=factory(require("knockout"));else if(typeof define==="function"&&define.amd)define(["knockout"],factory);else if(typeof exports==="object")exports["ko-component-router"]=factory(require("knockout"));else root["ko-component-router"]=factory(root["ko"])})(this,function(__WEBPACK_EXTERNAL_MODULE_1__){return function(modules){var installedModules={};function __webpack_require__(moduleId){if(installedModules[moduleId])return installedModules[moduleId].exports;var module=installedModules[moduleId]={exports:{},id:moduleId,loaded:false};modules[moduleId].call(module.exports,module,module.exports,__webpack_require__);module.loaded=true;return module.exports}__webpack_require__.m=modules;__webpack_require__.c=installedModules;__webpack_require__.p="";return __webpack_require__(0)}([function(module,exports,__webpack_require__){"use strict";var ko=__webpack_require__(1);var router=__webpack_require__(2);__webpack_require__(14);ko.components.register("ko-component-router",{synchronous:true,viewModel:router,template:"
\n
'+s("")+"
\n \n \n
"+s('')+"
\n \n \n
"+s("")+"
\n \n \n you may use one — or any combination of — these bindings on an element\n to create a click handler that will update the path, state, and/or query\n
\n\n these can be handy to avoid base-path + hashbang hell, and to pass in an initial\n state when navigating via click\n
\n\n they can also be used to prepopulate the data for a page, e.g.\n
\n"+s("\n\n \n
")+'\n
\n \n in this case, the `state` and `path` bindings are being used together\n to create a link from an index page listing users, to an individual users\n page, and passes in the user on the state object. this could prevent the\n need for ajax altogether on some pages, or reduce the amount of additional\n data required, allowing you to render more of the page, sooner.\n
\n'+s("\n ")+"\n
\n \n routes should be passed into the router as an object where\n key === express-style route and value === component\n
\n\n\nconst routes = {\n // explicit path\n '/about': 'about',\n\n // one required param (`name`)\n // one optional param (`operation`)\n '/user/:name/:operation?': 'user',\n\n // wildcard segment\n '/*': '404',\n\n // named wildcard segment\n '/file/:file(*)': 'file'\n}\n
\n \n the base path your app is running under, if applicable.\n e.g., your app is running from a `/blog` directory\n
\n\n this option is only applicable to the top-level router\n
\n\n whether or not to use HTML4 hashbang routing. defaults to false
.\n
\n this option is only applicable to the top-level router\n
\n\n when using with legacy browsers that do not support the history
\n API, you should include the HTML5-History-API polyfill\n as follows:\n
\n"+s('')+'\n
\n \n defines a function to run immediately after mounting a component\n
\n\n useful for animating when the component you are transitioning\n from influences the entry animation\n
\n\n defines a function to run immediately before unmounting a component\n
\n\n useful for animating when the component you are transitioning\n to influences the exit animation\n
\n\n if done
is passed in, the router will wait for it to be called\n before finishing the unmount\n
\n route params are directly accessible as read-only observables via\n ctx.params
\n
\n// route: \'/user/:id/:operation?\'\n\nclass ViewModel {\n constructor(ctx) {\n // @ \'/user/1234\'\n ctx.params.id() // 1234\n ctx.params.operation() // null\n\n // @ \'/user/1234/edit\'\n ctx.params.id() // 1234\n ctx.params.operation() // \'edit\'\n }\n}\n
\n\n \n read/write query parameter observables are accessible via\n ctx.query.get(parameterName, defaultValue)
\n
\n query params are scoped to the local router, so you may use the same\n name for params across different components, or nest the same component\n within itself, and maintain separate states.\n
\n\n query params that don\'t exist in the querystring will be initialized\n to their default values (if defined), and params that match their default\n values will not pollute the querystring.\n
\n\n See the page on nested routing for an example\n
\n\n\nclass ViewModel {\n constructor(ctx) {\n // read/write observable for \'foobar\' querystring parameter with\n // a default value of \'foo\'\n this.foobar = ctx.query.get(\'foobar\', \'foo\')\n\n // set \'foobar\' to \'bar\'\n this.foobar(\'bar\')\n\n // reset all params to their default values; triggers only\n // one update\n ctx.query.clear()\n\n // update multiple query params; triggers only one update\n ctx.query.update({\n foo: randomString(),\n bar: randomString()\n })\n }\n}\n
\n\n \n read/write observable history.state abstraction accessible directly via\n ctx.state()
\n
\n scoped to local router, similarly to query params\n
\n\n See the page on nested routing for an example\n
\n\n read-only observable containing route\n
\n\n read-only observable containing path relevant to local router\n
\n\n read-only observable containing pathname (path w/o querystring) relevant to local router\n
\n\n read-only observable containing full path\n
\n\n read-only observable containing anchor\n
\n\n updates the context and trigger one update\n
\n\n if push === true
, use pushState
, else replaceState
\n
\n if query
is false (or unsupplied), get from parsed querystring from url
\n
\n if query
is an object, set this context\'s query to the contents\n
\n ko-component-router
is a client-side router that allows you\n to easily build single page apps with KnockoutJS. It supports all the things\n you would expect a road-worthy spa router to support, with just enough\n Knockout magic thrown in.\n
\n It aims to be as performant as possible by batching\n updates, and it provides simple abstractions for working with querystring parameters\n and history.state is a self-contained manner.\n
\n\n
\n For a more in depth look at building SPA's with Knockout + ko-component-router,\n may I direct your attention to this blog post.\n
\n\n\n$ npm install ko-component-router\n
\n \n'use strict'\n\nrequire('ko-component-router')\n\nko.components.register('app', {\n viewModel: class App {\n constructor() {\n this.routes = {\n '/': 'home',\n '/user/:id': 'user'\n }\n }\n },\n template: `"+r("\n \n \n ")+"`\n})\n\nko.component.register('home', {\n template: `"+r('Show user')+"`\n})\n\nko.components.register('user', {\n viewModel: class User {\n constructor(ctx) {\n // ctx contains a bunch of information about the\n // current state of the router\n\n // many are read/write observables,\n // see each section for more info\n },\n template: '"+r("")+'\'\n }\n})\n\nko.applyBindings()\n
\n\n\n'+r('\n\n ')+'\n
\n \n For the most part, you don't have to think about nested routing,\n it just works.\n
\n\n The only caveat is that the parent component's route must be suffixed\n with a !
.\n
\n ctx
will have query
and state
\n objects just as you would expect, and they are scoped to the local router.\n To better understand this, check out the demo below.\n\n Reading the source for this page is also highly recommended.\n
\nko.components.register('foo-router', {\n viewModel: class FooRouter {\n constructor(ctx) {\n this.qsParam = ctx.query.get('foo', 'foo')\n\n this.state = ko.pureComputed({\n read() {\n return JSON.stringify(ctx.state())\n },\n write(v) {\n ctx.state(JSON.parse(v))\n }\n })\n\n this.routes = {\n '/foo': 'foo',\n '/bar': 'bar',\n '/baz': 'baz',\n '/qux': 'qux',\n // note the suffixed `!` denoting a child path may exist\n '/fooception/!': 'foo-router'\n }\n }\n\n randomString() {\n return lipsum[Math.floor(Math.random() * 100)]\n }\n\n randomObj() {\n const obj = {}\n for (let i = 0; i < 5; i++) {\n obj[lipsum[Math.floor(Math.random() * 100)]] = lipsum[Math.floor(Math.random() * 100)]\n }\n return obj\n }\n },\n template: `"+i('\n \n \n\n \n requires valid JSON\n \n\n foo\n bar\n baz\n qux\n foo-ception\n\n \n \n ')+'`\n})\n\nko.components.register(\'foo\', {\n template: \'foo!\'\n})\n\n// ...\n
\n \\n defines a function to run immediately after mounting a component\\n
\\n\\n useful for animating when the component you are transitioning\\n from influences the entry animation\\n
\\n\\n defines a function to run immediately before unmounting a component\\n
\\n\\n useful for animating when the component you are transitioning\\n to influences the exit animation\\n
\\n\\n if done
is passed in, the router will wait for it to be called\\n before finishing the unmount\\n
\\n route params are directly accessible as read-only observables via\\n ctx.params
\\n
\\n// route: \\'/user/:id/:operation?\\'\\n\\nclass ViewModel {\\n constructor(ctx) {\\n // @ \\'/user/1234\\'\\n ctx.params.id() // 1234\\n ctx.params.operation() // null\\n\\n // @ \\'/user/1234/edit\\'\\n ctx.params.id() // 1234\\n ctx.params.operation() // \\'edit\\'\\n }\\n}\\n
\\n\\n \\n read/write query parameter observables are accessible via\\n ctx.query.get(parameterName, defaultValue)
\\n
\\n query params are scoped to the local router, so you may use the same\\n name for params across different components, or nest the same component\\n within itself, and maintain separate states.\\n
\\n\\n query params that don\\'t exist in the querystring will be initialized\\n to their default values (if defined), and params that match their default\\n values will not pollute the querystring.\\n
\\n\\n See the page on nested routing for an example\\n
\\n\\n\\nclass ViewModel {\\n constructor(ctx) {\\n // read/write observable for \\'foobar\\' querystring parameter with\\n // a default value of \\'foo\\'\\n this.foobar = ctx.query.get(\\'foobar\\', \\'foo\\')\\n\\n // set \\'foobar\\' to \\'bar\\'\\n this.foobar(\\'bar\\')\\n\\n // reset all params to their default values; triggers only\\n // one update\\n ctx.query.clear()\\n\\n // update multiple query params; triggers only one update\\n ctx.query.update({\\n foo: randomString(),\\n bar: randomString()\\n })\\n }\\n}\\n
\\n\\n \\n read/write observable history.state abstraction accessible directly via\\n ctx.state()
\\n
\\n scoped to local router, similarly to query params\\n
\\n\\n See the page on nested routing for an example\\n
\\n\\n read-only observable containing route\\n
\\n\\n read-only observable containing path relevant to local router\\n
\\n\\n read-only observable containing pathname (path w/o querystring) relevant to local router\\n
\\n\\n read-only observable containing full path\\n
\\n\\n read-only observable containing anchor\\n
\\n\\n updates the context and trigger one update\\n
\\n\\n if push === true
, use pushState
, else replaceState
\\n
\\n if query
is false (or unsupplied), get from parsed querystring from url
\\n
\\n if query
is an object, set this context\\'s query to the contents\\n
\\n ko-component-router
is a client-side router that allows you\\n to easily build single page apps with KnockoutJS. It supports all the things\\n you would expect a road-worthy spa router to support, with just enough\\n Knockout magic thrown in.\\n
\\n It aims to be as performant as possible by batching\\n updates, and it provides simple abstractions for working with querystring parameters\\n and history.state is a self-contained manner.\\n
\\n\\n
\\n For a more in depth look at building SPA\\'s with Knockout + ko-component-router,\\n may I direct your attention to this blog post.\\n
\\n\\n\\n$ npm install ko-component-router\\n
\\n \\n\\'use strict\\'\\n\\nrequire(\\'ko-component-router\\')\\n\\nko.components.register(\\'app\\', {\\n viewModel: class App {\\n constructor() {\\n this.routes = {\\n \\'/\\': \\'home\\',\\n \\'/user/:id\\': \\'user\\'\\n }\\n }\\n },\\n template: `' + escape('\\n \\n \\n ') + '`\\n})\\n\\nko.component.register(\\'home\\', {\\n template: `' + escape('Show user') + '`\\n})\\n\\nko.components.register(\\'user\\', {\\n viewModel: class User {\\n constructor(ctx) {\\n // ctx contains a bunch of information about the\\n // current state of the router\\n\\n // many are read/write observables,\\n // see each section for more info\\n },\\n template: \\'' + escape('') + '\\'\\n }\\n})\\n\\nko.applyBindings()\\n
\\n\\n\\n' + escape('\\n\\n ') + '\\n
\\n \\n For the most part, you don\\'t have to think about nested routing,\\n it just works.\\n
\\n\\n The only caveat is that the parent component\\'s route must be suffixed\\n with a !
.\\n
\\n ctx
will have query
and state
\\n objects just as you would expect, and they are scoped to the local router.\\n To better understand this, check out the demo below.\\n\\n Reading the source for this page is also highly recommended.\\n
\\nko.components.register(\\'foo-router\\', {\\n viewModel: class FooRouter {\\n constructor(ctx) {\\n this.qsParam = ctx.query.get(\\'foo\\', \\'foo\\')\\n\\n this.state = ko.pureComputed({\\n read() {\\n return JSON.stringify(ctx.state())\\n },\\n write(v) {\\n ctx.state(JSON.parse(v))\\n }\\n })\\n\\n this.routes = {\\n \\'/foo\\': \\'foo\\',\\n \\'/bar\\': \\'bar\\',\\n \\'/baz\\': \\'baz\\',\\n \\'/qux\\': \\'qux\\',\\n // note the suffixed `!` denoting a child path may exist\\n \\'/fooception/!\\': \\'foo-router\\'\\n }\\n }\\n\\n randomString() {\\n return lipsum[Math.floor(Math.random() * 100)]\\n }\\n\\n randomObj() {\\n const obj = {}\\n for (let i = 0; i < 5; i++) {\\n obj[lipsum[Math.floor(Math.random() * 100)]] = lipsum[Math.floor(Math.random() * 100)]\\n }\\n return obj\\n }\\n },\\n template: `' + escape('\\n \\n \\n\\n \\n requires valid JSON\\n \\n\\n foo\\n bar\\n baz\\n qux\\n foo-ception\\n\\n \\n \\n ') + '`\\n})\\n\\nko.components.register(\\'foo\\', {\\n template: \\'foo!\\'\\n})\\n\\n// ...\\n
\\n