Search code examples
ember.jsroutesnestedwildcardglob

Ember nested global routes (Wildcard)


I'm trying to do something like this in my routes:

this.route('products', { path: "/products/*choises"}, function() {
   this.route('promotion', {path: "/promotion/*offers"});
}); 

product route:

    offerPath: function(params){
      this.transitionTo('product.promotion', params);
    }

The problem is that it doesn't matter the promotion that I visit, the app thinks is part of the products route. How can I do this? I need them to be nested.


Solution

  • Update: You can use beforeModel(transition) hook in router to check what's in the url.

    http://example.com/products/manufacturer-209/series-881/tag-17143/none/494822/f‌​lawless

    import Ember from 'ember';
    
    export default Ember.Route.extend({
    
      beforeModel(transition) {
        console.log(transition.params.products.choises)
       // if you use this url: http://example.com/products/manufacturer-209/series-881/tag-17143/none/494822/f‌​lawless
       // console log would be: "manufacturer-209/series-881/tag-17143/none/494822/f‌​lawless"
      }
    
    });
    

    At least you have the rest of the url so, you can filter out the important information and redirect with this.transitionTo() to the exact place.


    You could have the following route:

    http://example.com/products/123/promotions/456
    

    or

    http://example.com/products/awesome_souce/promotions/monday_deal
    

    In the first case, your route would look like this:

    this.route('product', { path: "/products/:product_id"}, function() {
      this.route('promotion', {path: "/promotions/:promotion_id"});
    });
    

    In the second case, maybe like this:

    this.route('product', { path: "/products/:product_name"}, function() {
      this.route('promotion', {path: "/promotions/:promotion_name"});
    });
    

    Finally, your route handlers can download the proper models (example for the first case):

    // app/routes/product.js
    import Ember from 'ember';
    
    export default Ember.Route.extend({
      model(params) {
        return this.store.findRecord('product', params.product_id);
      }
    });
    
    ---
    
    // app/routes/product/promotion.js
    import Ember from 'ember';
    
    export default Ember.Route.extend({
      model(params) {
        // you can get access to the parent route model if you need for the api query
        const product = this.modelFor('product');
        return this.store.findRecord('promotion', params.promotion_id);
      }
    });
    

    If you need only the param from the product route, instead of returning a whole record, for example you can just return params.product_name, so you will have access to a string with this.modelFor('product') in a subroute level.