solenya-group / solenya

mega-powerful micro-framework
MIT License
81 stars 0 forks source link

Built In Routing #12

Closed solenya-group closed 6 years ago

solenya-group commented 6 years ago

Here's the gist: https://gist.github.com/pickle-ts/9db6a3d9da292fafbc2671bf14742df7

Design:

Client side routing is modeled as a two-way mapping the path of the browser's current url and component state. So if the url changes, it updates the component state, and vice-versa. The component's routing state is maintained by an instance of 'Router', which merely has a possible current child name. That child name maps to part of a path, where each part is separated by forward slashes. Nested routes map to nested components, making routing composable.

Usage:

Here's a Wizard component that implements IRoute as follows:

class Wizard extends Component implements IRoute
{
    @Exclude() routeName = "wizard"
    @Exclude() router: Router = new Router (this)    
    @Type(() => Wizard) page1 = new WizardPage1()
    @Type(() => Wizard) page2 = new WizardPage2()

    childRoute (name: string) {
        return this[name] as IRoute
    }
}

Every routable component needs a name, and a field holding the router. These are excluded from serialization, because the ultimate source of truth for the state is the browser's url. If the router has child components that also implement IRoute, then the router will maintain the current child name. The parent component must implementchildRoute in order to map the parent to the child.

Here's the implement of a child route:

class WizardPage1 extends Component implements IRoute
{
    @Exclude() router: Router = new Router (this)   
    routeName = 'page1'
}

So child routes are identical to parent routes, except that if the child is a terminal/leaf-node, then it has no children, so doesn't need to implement childRoute.

Use the history API to map changes to the history (e.g. back button etc.) to the root route:

history.listen ((historyLocation, action) => {
    this.router.go (location.pathname, action)
})   

The go method of the router sets the parent-relative child route. The childRouteName property of the router is either '', meaning no child is set, or is set to the name of a child route. It should be used to represent the currently selected item in any scenario where that makes sense (e.g. wizards, lists of editable items).

Can include this in the main pickle API at the end of the month.

solenya-group commented 6 years ago

checked in