2
votes

I am working on learning how to work with Ember JS and I have run into an issue.

I have been developing a very simple application that allows users to add/edit/delete books from a library and then search for books based on either the title or the author. Based on that I am attempting to create a link-to that would render like "/search/title/adventures_of_huckleberry_finn" which would tell the router to filter the model so that it only returns books with the title equals "Adventures of Huckleberry Finn" (I know I'll need to do some string formating for the character case and replacing spaces with underscores for the URL, but I'm not worried about that).

I have the following link-to in my template (the title is hard coded to simplify testing)

{{#link-to "books.search" "title" "adventures_of_huckleberry_finn"}}Search by title{{/link-to}}

I have the following route defined (I suspect I need to nest the second dynamic segment but I'm not sure how to do that since I don't want a new controller/route involved)

Books.Router.map(function () {
    this.resource('books', { path: '/' }, function () {
        this.route('search', { path: 'search/:search_by/:keyword' });
    });
});

<!-- ... additional lines truncated for brevity ... -->

Books.BooksSearchRoute = Ember.Route.extend({
    model: function (params) {
        return this.store.filter('book', function (book) {
            return book.get(params.search_by) == params.keyword;
        })
    },
    renderTemplate: function (controller) {
        this.render('books/index', { controller: controller });
    }
});

Now if I hard code the value or either the :searchBy or :keyword parms in the BooksSearchRoute then this works fine, however when I attempt to dynamicly pass both params I get the following error:

More context objects were passed than there are dynamic segments for the route: books.search

How can I update the route so that it allows me to pass both dynamic params into the BooksSearchRoute correctly?

1
To be completely honest, I'd avoid composite keys on a route. We did it on one of our routes and it's just a pain in the ass. It'd be significantly easier to either wrap the route in 2 routes, or join the composite keys with a dash. If you'd like I can show the wrap method. - Kingpin2k
@kingpin2k I'm facing the same issue here within my project. it would be awesome if you could show your wrap method here (if it's ok for the topic owner too) ;) - herom
@kingpin2k Yes I'd deffinitly like to see the wrap method your talking about. Thanks - efarley
There ya go, hopefully it helps some. - Kingpin2k

1 Answers

0
votes

Here's the general concept, you essentially use a route as a dummy route used just for the composite key. Personally I'd still prefer joining the key with a dash or something and using a single route, but hey, here's how this would work.

App.Router.map(function() {
  this.resource('colorWrap', {path:'/:pk1'}, function(){
    this.resource('color', {path: '/:pk2'});
  });
});

App.ColorWrapRoute = Ember.Route.extend({
  model: function(params) {
    return {pk1:params.pk1};
  }
});

App.ColorRoute = Ember.Route.extend({
  model: function(params) {
    var wrapModel = this.modelFor('colorWrap');
    return $.getJSON('/colors/' + wrapModel.pk1 + '/' + params.pk2);
  }
});


{{link-to 'Click to see the red color!' 'color' 1 2}}

http://emberjs.jsbin.com/OxIDiVU/273/edit