# Question about setting up component based pages with routes

**URL:** <https://forums.bitovi.com/t/question-about-setting-up-component-based-pages-with-routes/301>\
**Category:** CanJS\
**Created:** [June 8, 2016, 5:01pm UTC](https://forums.bitovi.com/t/question-about-setting-up-component-based-pages-with-routes/301 "2016-06-08T17:01:05Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Nothing\_New](https://yyz1.discourse-cdn.com/flex035/user_avatar/forums.bitovi.com/nothing_new/32/206_2.png) [@Nothing\_New](https://forums.bitovi.com/u/Nothing_New)\
**Post date:** [June 8, 2016, 5:01pm UTC](https://forums.bitovi.com/t/question-about-setting-up-component-based-pages-with-routes/301/1 "2016-06-08T17:01:05Z")

</div>

I am working on a single page web application using canjs and requirejs, this is the first app of this scale for me. I am wondering on the best way to create a ‘page system’, meaning binding a page to a certain route. So when the route changes I load the correct page. Each of my pages is a can.Component.

My biggest issue with the way that I have set this up is that I will be limited by the current ‘route model’ of being ‘:page/:subpage/:id’’. I would end up running into issues if I needed my route url to be lets say five backslashes long like ‘tire/inventory/quote/new/123’.

I’m thinking maybe, instead of having the ‘:page/:subpage/:id’, have all the possible pages hard codded, like each specific route is linked to a specific ‘component page’. I think that this would most likely be the most flexible and easy to work with idea.

I just feel like what I am doing is wrong and I would love to have some feed back. Thank you!

```
define([
    'jquery',
    'can/util/library',
    'can/component',
    'can/view',
    'can/route',
    'can/map/delegate',
    'scope',
    'pages/error/404',
    'pages/fork/inventory',
    'pages/fork/form',
    'pages/attachment/inventory',
    'pages/attachment/form',
    'pages/tire/inventory',
    'pages/tire/form'
], function( $, can, Component, view, route, delegate, Scope ){

    var renderPage = function( element, template ){
        var renderer = can.stache( template );
        var fragment = renderer({
            route: can.route.attr(),
            scope: Scope.getScope()
        });
        element.find( '.app-bench' ).empty().html( fragment );
    };

    var loadPage = function( element ){
        var template = '';
        var page = can.route.attr( 'page' );
        var subpage = can.route.attr( 'subpage' );
        var pageFound = false;
		switch( page ){
			case 'fork':
				switch( subpage ){
					case 'inventory':
						template = '<page-fork-inventory></page-fork-inventory>';
						pageFound = true;
						break;
					case 'add':
					case 'edit':
						template = '<page-fork-form></page-fork-form>';
						pageFound = true;
						break;
				}
				break;
			case 'attachment':
				switch( subpage ){
					case 'inventory':
						template = '<page-attachment-inventory></page-attachment-inventory>';
						pageFound = true;
						break;
					case 'add':
					case 'edit':
						template = '<page-attachment-form></page-attachment-form>';
						pageFound = true;
						break;
				}
				break;
			case 'tire':
				switch( subpage ){
					case 'inventory':
						template = '<page-tire-inventory></page-tire-inventory>';
						pageFound = true;
						break;
					case 'add':
					case 'edit':
						template = '<page-tire-form></page-tire-form>';
						pageFound = true;
						break;
				}
				break;
		}
		if( !pageFound ) {
			template = '<page-error-404></page-error-404>';
		}
		renderPage( element, template );
    };

    return Component({
        tag: 'app-bench',
        template: can.view( 'app/views/bench.stache' ),
        events: {
            destroy: function(){

            },
            inserted: function( element, event ){
                loadPage( element );
                can.route.delegate( 'page,subpage,id', 'set', function( ev,newVal,oldVal,from ){
                    loadPage( element, element );
                });
                can.route.delegate( 'page,subpage', 'set', function( ev,newVal,oldVal,from ){
                    if( !can.route.attr( 'id' ) ){
                        loadPage( element, element );
                    }
                });
            }
        }
    });

});
```

---

<div class="post-metadata">

**Author:** ![leoj3n](https://yyz1.discourse-cdn.com/flex035/user_avatar/forums.bitovi.com/leoj3n/32/174_2.png) [@leoj3n](https://forums.bitovi.com/u/leoj3n)\
**Post date:** [June 8, 2016, 8:40pm UTC](https://forums.bitovi.com/t/question-about-setting-up-component-based-pages-with-routes/301/2 "2016-06-08T20:40:13Z")

</div>

Have you looked into using [DoneJS](https://donejs.com/place-my-order.html)? AFAIK, DoneJS wires this all together for you and provides a bunch of niceties like app and component generators. I’m new to this stuff as well, so maybe I’m off base, but with DoneJS you would have an `app.js` like:

```auto
import DefineMap from "can-define/map/";
import route from "can-route";
import "can-route-pushstate";

const AppViewModel = DefineMap.extend({
  route: "string",
  page: "string",
  title: {
    value: 'my-app',
    serialize: false
  }
});

route('/:page', { page: 'home' });

export default AppViewModel;

```

And an `index.stache`:

```auto
<html>
  <head>
    <title>{{title}}</title>
  </head>
  <body>
    <can-import from="./app" export-as="viewModel" />
    <can-import from="./loading.component" />

    {{#switch page}}
      {{#case "home"}}
        <can-import from="./app/home/home" can-tag="app-loading">
          <app-home/>
        </can-import>
      {{/case}}
      {{#case "photo"}}
        <can-import from="./app/photos/photos" can-tag="app-loading">
          <app-photos/>
        </can-import>
      {{/case}}
    {{/switch}}

    {{#switch env.NODE_ENV}}
      {{#case "production"}}
        <script src="{{joinBase 'node_modules/steal/steal.production.js'}}" main="my-app/index.stache!done-autorender"></script>
      {{/case}}
      {{#default}}
        <script src="/node_modules/steal/steal.js"></script>
      {{/default}}
    {{/switch}}
  </body>
</html>

```

Then when you visit `/` or `/home` or `/photos` the respective component is selectively loaded. Perhaps you are avoiding DoneJS for learning purposes or just want to wire it up with CanJS yourself. Either way hopefully this helps give some insight into how you might accomplish your SPA.

---

<div class="post-metadata">

**Author:** ![leoj3n](https://yyz1.discourse-cdn.com/flex035/user_avatar/forums.bitovi.com/leoj3n/32/174_2.png) [@leoj3n](https://forums.bitovi.com/u/leoj3n)\
**Post date:** [June 8, 2016, 8:59pm UTC](https://forums.bitovi.com/t/question-about-setting-up-component-based-pages-with-routes/301/3 "2016-06-08T20:59:10Z")

</div>

And here are the routings of the two major examples:

Place My Order:

> <https://github.com/donejs/place-my-order/blob/8f7bbc2988374c746b5a171d249cd85cfd15381f/src/app.js#L15-L17>

Which gets as complex as [http://place-my-order.herokuapp.com/restaurants/brunch-place/order](http://place-my-order.herokuapp.com/restaurants/brunch-place/order)

BitBalls:

> <https://github.com/donejs/bitballs/blob/3c724845c9702db7596e9151ba097d75e08f828b/public/app.js#L169-L171>

Which gets as complex as [http://bitballs.herokuapp.com/tournaments/2](http://bitballs.herokuapp.com/tournaments/2)

---

<div class="post-metadata">

**Author:** ![Nothing\_New](https://yyz1.discourse-cdn.com/flex035/user_avatar/forums.bitovi.com/nothing_new/32/206_2.png) [@Nothing\_New](https://forums.bitovi.com/u/Nothing_New)\
**Post date:** [June 8, 2016, 9:30pm UTC](https://forums.bitovi.com/t/question-about-setting-up-component-based-pages-with-routes/301/4 "2016-06-08T21:30:22Z")

</div>

Ok, thank you. It looks like I am heading in the right direction. 🙂

If anyone has any other methods of doing so, please post!

---

<div class="post-metadata">

**Author:** ![Nothing\_New](https://yyz1.discourse-cdn.com/flex035/user_avatar/forums.bitovi.com/nothing_new/32/206_2.png) [@Nothing\_New](https://forums.bitovi.com/u/Nothing_New)\
**Post date:** [June 9, 2016, 6:14pm UTC](https://forums.bitovi.com/t/question-about-setting-up-component-based-pages-with-routes/301/5 "2016-06-09T18:14:22Z")

</div>

I didn’t see this earlier reply, It looks like you can do this exact thing in CanJS. Thanks!

---

<div class="post-metadata">

**Author:** ![marshallswain](https://yyz1.discourse-cdn.com/flex035/user_avatar/forums.bitovi.com/marshallswain/32/22_2.png) [@marshallswain](https://forums.bitovi.com/u/marshallswain)\
**Post date:** [June 9, 2016, 10:44pm UTC](https://forums.bitovi.com/t/question-about-setting-up-component-based-pages-with-routes/301/6 "2016-06-09T22:44:17Z")

</div>

Yep, you can. CanJS is a part of DoneJS.

---

<div class="post-metadata">

**Author:** ![leoj3n](https://yyz1.discourse-cdn.com/flex035/user_avatar/forums.bitovi.com/leoj3n/32/174_2.png) [@leoj3n](https://forums.bitovi.com/u/leoj3n)\
**Post date:** [June 12, 2016, 6:07am UTC](https://forums.bitovi.com/t/question-about-setting-up-component-based-pages-with-routes/301/7 "2016-06-12T06:07:13Z")

</div>

No worries and it’s not your fault; my first reply was put into moderation by the spam filter 😥
