TehShrike / abstract-state-router

Like ui-router, but without all the Angular. The best way to structure a single-page webapp.

Home Page:http://tehshrike.github.io/state-router-example

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Adding multiple keyed templates for a state

b12f opened this issue · comments

commented

Is the following possible? And if not, how would I go about implementing this? I'm open to putting out a PR but am having trouble understanding the codebase.

addState({
   // everything else
  templates: { // normally just one template
    default: componentFn,
    nav: navComponentFn,
  },
})
<uiView name="nav" />
<uiView />

Can you describe what problem you’re trying to solve?

commented

I have one main component App.svelte, which has two components that are always available but routed pretty much independently;

  • Nav, which changes between landing page / legal pages / workspace pages
  • Main, which changes on every page basically holds all pages and their subpages.

I'd like to not rerender the whole App component (e.g. change out for a different App component for different routes) since it hosts some peripheral components like a modal wrapper, and the styles between nav and main stay pretty much the same.

commented

I guess it would be possible with more wrapping of basically holding components that are empty except for a nav and the next <uiView>, and then having an extra layer in the route tree:

My idea:

const routes = [
  {
    name: 'app',
    route: '/',
    template: App, // hosts `<uiView />` and `<uiView name="nav" />`
    defaultChild: 'landing-area',
  },
  {
    name: 'app.landing-area',
    route: '/',
    templates: {
      default: LandingArea, // Hosts one `<uiView />`
      nav: LandingAreaNav,
    },
    defaultChild: 'landing-page',
  },
  {
    name: 'app.landing-area.landing-page',
    route: '/',
    template: LandingPage,
  },
  {
    name: 'app.landing-area.login',
    route: '/login',
    template: Login
  },
  {
    name: 'app.auth-area',
    route: '/auth',
    templates: {
      default: AuthArea,  // Hosts one `<uiView />` for further child routes
      nav: AuthAreaNav,
    },
  },
];

While, if I understand correct, this would have to be the current solution:

const routes = [
  {
    name: 'app',
    route: '/',
    template: App,
    defaultChild: 'landing-area',
  },
  {
    name: 'app.landing-area',
    route: '/',
    templates: LandingArea,  // hosts `<uiView />` and `<LandingAreaNav />`
    defaultChild: 'landing-page',
  },
  {
    name: 'app.landing-area.landing-page',
    route: '/',
    template: LandingPage,
  },
  {
    name: 'app.landing-area.login',
    route: '/login',
    template: Login
  },
  {
    name: 'app.auth-area',
    route: '/auth',
    template: AuthArea, // hosts `<uiView />` and `<AuthAreaNav />`
  },
];

This makes nav transitions harder, and it prevents parts of nav to be kept between pages, since the whole thing has to be thrown out for the next nav to come in. You cannot do this:

<nav>
  <some-stuff-that-i-want-to-keep />
  <uiView name="nav" transition-this-nicely />
  <account-menu show-if-logged-in />
</nav>

<uiView />

I do currently use the make-a-state-for-just-the-nav method, and it works well. Example: https://github.com/KayserCommentaryOrg/revelation-project/blob/master/client/view/Main.html#L1-L9

since the whole thing has to be thrown out for the next nav to come in

I don't think that's true with the nesting method – if you navigate from app.landing-area.landing-page to app.landing-area.login, the app.landing-area state doesn't change, and the LandingAreaNav component doesn't get reloaded.

If your idea was implemented and there was a <uiView name="nav" />, it would naturally reload/re-render at exactly the same times as when it does now.

commented

Well my gripe is that there's other stuff in the nav that could just stay there and not be rerendered, especially cause it ties in to nice transitions of the part of the nav that's stateful. Like in the HTML example, you'd need to rerender the account menu even though it's the same across all pages. Not only is it less performant, but you'd have to copy paste the code into all Nav components.

Edit: Ok I get the idea of an extra state for the nav. Might take a look at that and just wrap my current route array into a handler that tears them apart into the two states.

commented

Thanks for the discussion!