当我从默认情况下更改控制器时,Ember JS路由器不会过滤

时间:2014-03-11 23:42:57

标签: ember.js

我的路由器完整:

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

Books.BooksRoute = Ember.Route.extend({
    model: function(){
        return this.store.find('book');
    },
    actions: {
        postAlert: function (msg, classes) {
            var postAlert = $('#alert');

            postAlert.html(msg).toggleClass(classes).toggle(1000);
            setTimeout(function () {
                postAlert.toggle(1000, function () {
                    postAlert.toggleClass(classes)
                });
            }, 3000);
        }
    }
});

Books.BooksIndexRoute = Ember.Route.extend({
    model: function () {
        return this.modelFor('books');
    },
    renderTemplate: function () {
        this.render({ controller: 'books' });
    }
});

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

现在让我们关注路由器的最后一点,BooksSearchRoute。当我离开现在的路由器并转到路径localhost /#/ search / the_adventures_of_huckleberry_finn然后我将看到用模型填充的书籍/索引模板,其中titleSlug包含动态段,这很棒,正是我所期待的。

现在,当我尝试使用我的书籍控制器中从该URL定义的操作时,我收到一个错误,即没有任何操作处理。为此,我切换了renderTemplate行,使其使用“books”作为控制器而不是默认控制器。

renderTemplate: function () {
    this.render('books/index', { controller: 'books' });
}

这一更改允许我访问我需要的书籍控制器中的操作。但是,在进行更改之后,过滤器似乎不再起作用,因为显示了库中的所有书籍而不仅仅是匹配搜索词的书籍。有人可以向我解释这里发生了什么吗?

1 个答案:

答案 0 :(得分:1)

这实际上是预期的行为。

解释

当点击Route时,它会获取模型并将其传递给与该路线相关联的Controller。它使用Ember naming conventions确定哪一个。

覆盖模板

您在此处所做的是覆盖renderTemplate,以指定应使用与命名约定指示使用的模板不同的模板。

在这种情况下工作正常,因为BooksIndexRoute的模型和BooksSearchRoute的模型是兼容的 - 它们都是Book的数组。

覆盖模板和控制器

您接下来要做的是在此处覆盖renderTemplate以指定应该使用不同的模板,并且根据命名约定,它应该使用不同的控制器BooksController。< / p>

当然,BooksController并不知道你已经这样做了,并且会使用它所知道的模型,它自己的Route返回的模型,就是这种情况是this.store.find('book')

...由于未过滤该模型,模板会呈现完整的Book模型集。

建议的解决方案

您可以继续沿着此路径继续覆盖模板和控制器,并重构所需的操作,使它们在两个控制器上都可用。但是,我不建议这样做,因为它违背了Ember的设计方式,而且它将涉及相当多的意大利面条代码。

规范解决方案将涉及使用您已有的路线和控制器,但覆盖renderTemplate中的BooksIndexRoute

相反,将提取书籍列表的代码解压缩到一个单独的模板中,然后将其放入名为partials的文件夹中,然后从两个模板中调用该部分:

  • 来自books(或books\index视情况而定),以及
  • 来自books\search

syntax looks like this

我不知道你的模板是什么样的,但是如果你发布它们,我可以告诉你如何这样做。