Rigel
Rigel

Reputation: 882

Both automatic and conditional routing Emberjs

If the user access the site directly www.mysite.com the routes should transition to first product page of first category.

If the user copy paste url of a particular product. user should be navigate to that particular product page.

I need some directions how to go about it as when I copy a product url www.mysite.com/Men/shirts it navigate to default first category first product as per my transitionTo

My router.js looks like this

 MyApp.Router.map(function () {
   this.resource('categories', {path: '/'}, function () {
     this.resource('category', { path: '/:category_id'}, function () {
        this.resource('product', { path: '/:product_id' });
     });
   });
});

my categories route's after model look like this

afterModel: function(categories,transition){
       this.transitionTo('category',categories.get('firstObject'));
}, 

my category route after model looks like this

afterModel: function (category) {
        var self = this;
        self.transitionTo('product', category.get('products').get('firstObject'));
    }

Upvotes: 0

Views: 529

Answers (2)

melc
melc

Reputation: 11671

This is an example following your routing structure,

http://emberjs.jsbin.com/viyagaga/1/edit

specific category: http://emberjs.jsbin.com/viyagaga/1#/category/2

specific product: http://emberjs.jsbin.com/viyagaga/1#/category/2/product/4

hbs

<script type="text/x-handlebars" data-template-name="categories">
    this is all categories<br/>
    <ul>
    {{#each category in model}}
    <li>
      {{#link-to "category" category.id}}
        id:{{category.id}}&nbsp;name:{{category.name}}
      {{/link-to}}
    </li>
    {{/each}}
    </ul>
    {{outlet}}
  </script>

  <script type="text/x-handlebars" data-template-name="category">
    this is category {{model.name}}<br/>
    with products:<br/>
    <ul>
    {{#each product in model.products}}
    <li>
      {{#link-to "product" product.id}}
        id:{{product.id}}&nbsp;name:{{product.name}}
      {{/link-to}}
    </li>
    {{/each}}
    </ul>
    {{outlet}}
  </script>

  <script type="text/x-handlebars" data-template-name="product">
    this is product:<br/>
    {{model.name}}<br/>

  </script>

js

App = Ember.Application.create();

App.Router.map(function () {
   this.resource('categories', {path: '/'}, function () {
     this.resource('category', { path: 'category/:category_id'}, function () {
        this.resource('product', { path: 'product/:product_id' });
     });
   });
});

App.IndexRoute = Ember.Route.extend({
  beforeModel: function() {
    this.transitionTo("categories");
  }
});

App.CategoriesRoute = Ember.Route.extend({
  model:function(){
    return allCategoriesData;
  }
});

App.CategoryRoute = Ember.Route.extend({
  model: function(params) {
    return allCategoriesData.findBy("id",parseInt(params.category_id,10));
  }
});

App.ProductRoute = Ember.Route.extend({
  model: function(params) {
   return this.modelFor("category").products.findBy("id",parseInt(params.product_id,10));
  }
});

var allCategoriesData = [
  {"id":1,"name":"Category1",
   "products":[
     {"id":1, "name":"product11"},
     {"id":2, "name":"product12"}
   ]
  },
  {"id":2,"name":"Category2",
   "products":[
     {"id":3, "name":"product21"},
     {"id":4, "name":"product22"},
     {"id":5, "name":"product23"}
   ]
  },
  {"id":3,"name":"Category3",
   "products":[
     {"id":6, "name":"product31"}
   ]},
  {"id":4,"name":"Category4",
   "products":[
     {"id":7, "name":"product41"},
     {"id":8, "name":"product42"},
     {"id":9, "name":"product43"},
     {"id":10, "name":"product43"}
   ]}
];

If you need to show each route on its own window without the corresponding master then the routing and hbs templates need to change as follows,

http://emberjs.jsbin.com/cajalosu/1/edit

hbs

<script type="text/x-handlebars" data-template-name="categories">
    this is all categories<br/>
    <ul>
    {{#each category in model}}
    <li>
      {{#link-to "category" category.id}}
        id:{{category.id}}&nbsp;name:{{category.name}}
      {{/link-to}}
    </li>
    {{/each}}
    </ul>
  </script>

  <script type="text/x-handlebars" data-template-name="category">
    this is category {{model.name}}<br/>
    with products:<br/>
    <ul>
    {{#each product in model.products}}
    <li>
      {{#link-to "product" model.id product.id}}
        id:{{product.id}}&nbsp;name:{{product.name}}
      {{/link-to}}
    </li>
    {{/each}}
    </ul>

  </script>

  <script type="text/x-handlebars" data-template-name="product">
    this is product:<br/>
    {{model.name}}<br/>

  </script>

js

....
App.Router.map(function () {
  this.route('categories', {path: '/'});
  this.resource('category', { path: 'category/:category_id'});
  this.resource('product', { path: 'category/:category_id/product/:product_id' });
});
....
App.ProductRoute = Ember.Route.extend({
  model: function(params) {
   return allCategoriesData.findBy("id",parseInt(params.category_id,10)).products.findBy("id",parseInt(params.product_id,10));
  }
});
....

EDIT - transition to first object of first category

http://jsbin.com/felalizo/1#/category/1/product/1

Upvotes: 1

selvagsz
selvagsz

Reputation: 3872

You should probably do the default transition from the Index Routes.

 MyApp.CategoriesIndexRoute = Em.Route.extend({
   afterModel: function(model) {
    this.transitionTo('category',model.get('firstObject')); 
   }  
 });

 MyApp.CategoryIndexRoute = Em.Route.extend({
   afterModel: function(model) {
    this.transitionTo('product', Em.get(model, 'products.firstObject')); 
   }  
 });

Child resources/routes inherits parent's model since this PR. You can use this.modelFor if you are using older version

Working Demo

Upvotes: 2

Related Questions