Skip to content
This repository has been archived by the owner on Dec 19, 2017. It is now read-only.

Named States

Casey Webb edited this page Dec 18, 2016 · 3 revisions
import ko from 'knockout'
import Router from 'ko-component-router'
import pathToRegexp from 'path-to-regexp'

const states = {
  'user': {
    path: '/user',
    component: 'user-index',
    states: {
      'list': {
        path: '/',
        component: 'user-list'
      },
      'create': {
        path: '/new',
        component: 'user-create'
      },
      'show': {
        path: '/:id',
        component: 'user-show'
      },
      'edit': {
        path: '/:id/edit',
        component: 'user-edit'
      },
    }
  }
}

function toRoutes(states) {
  return Object.values(states).reduce((routes, { path, component, states }) => {
    routes[path] = []
    if (component) routes[path].push(component)
    if (states) routes[path].push(toRoutes(states))
    return routes
  }, {})
}

function getPathForState(state, params) {
  let path = ''
  let _states = states
  for (const _state of state.split('.')) {
    path += _states[_state].path
    _states = _states[_state].states
  }
  path = pathToRegexp.compile(path)(params)
}

function navigateToState(state, params, push) {
  const path = getPathForState(state, params)
  return Router.update(path, push)
}

Router.routes = toRoutes(states)

Router.navigateToState = navigateToState

ko.bindingHandlers.state = {
  init(el, valueAccessor) {
    const state = valueAccessor()
    const name = typeof state === 'string' ? state : state.name
    ko.applyBindingsToNode(el, {
      path: getPathForState(name, state.params)
    })
  }
}

// Router.navigateToState('user.show', { id: user.id })
//
// <a data-bind="state: { name: 'user.show', params: user.id }"></a>
Clone this wiki locally