如何通过单击{{action}}从外部调用Controller上的操作方法,具有相同的行为

时间:2013-09-18 04:11:26

标签: ember.js

请查看此代码......

```

            App.BooksRoute = Ember.Route.extend({
                model:  return function () {
                    return this.store.find('books');
                }
            });

            App.BooksController = Ember.ArrayController.extend({
                actions: {
                    updateData: function () {
                        console.log("updateData is called!");
                        var books = this.filter(function () {
                            return true;
                        });
                        for(var i=0; i<books.length; i++) {
                            //doSomething…
                        }
                    }
                }
            });

```

我想从外面调用BooksController上的updateData操作。

我尝试了这段代码。

App.__container__.lookup("controller:books").send('updateData');

它确实有效。但是,在updateData操作中,通过点击this模板上的{{action'updateData'}},updateData与调用books的操作不同。< / p>

如果点击{{action'updateData'}},this.filter()操作中的updateData方法将返回图书模型。 但是,如果调用App.__container__.lookup("controller:books").send('updateData');this.filter()操作中的updateData方法将不返回任何内容。

如何通过点击{{action'updateData'}}以相同的行为从外部调用BooksController上的updateData操作。

我很高兴知道这件事。

(我正在使用Ember.js 1.0.0)

3 个答案:

答案 0 :(得分:10)

您可以使用bindjQuery.proxy。自1.8.5版本以来,JS中提供了bind,因此除非您需要支持非常旧的浏览器,否则使用起来非常安全。 http://kangax.github.io/es5-compat-table/

无论哪种方式,您基本上都是手动确定this对象的范围。

所以,如果你有这个IndexController,并且你想从应用程序外部触发raiseAlert

App.IndexController = Ember.ArrayController.extend({
  testValue : "fooBar!",
  actions : {
    raiseAlert : function(source){
      alert( source + " " + this.get('testValue') );
    }
  }
});

使用bind

function externalAlertBind(){
  var controller = App.__container__.lookup("controller:index");
  var boundSend = controller.send.bind(controller);
  boundSend('raiseAlert','External Bind');
}

使用jQuery.proxy

function externalAlertProxy(){
  var controller = App.__container__.lookup("controller:index");
  var proxySend = jQuery.proxy(controller.send,controller);
  proxySend('raiseAlert','External Proxy');
}

有趣的是this 似乎没有在此JSBin中使用bindproxy

function externalAlert(){
  var controller = App.__container__.lookup("controller:index");
  controller.send('raiseAlert','External');
}

这是一个显示所有这些内容的JSBin:http://jsbin.com/ucanam/1080/edit

[更新]:在操作中调用filter的另一个JSBin:http://jsbin.com/ucanam/1082/edit

[更新2]:我通过查找"controller:booksIndex"代替"controller:books-index"来完成工作。

这是一个JSBin:http://jsbin.com/ICaMimo/1/edit

看待它的工作方式(因为路线很奇怪):http://jsbin.com/ICaMimo/1#/index

答案 1 :(得分:5)

这解决了我的类似问题

在这里阅读更多关于行动的信息:http://emberjs.com/guides/templates/actions/#toc_action-bubbling

SpeedMind.ApplicationRoute = Ember.Route.extend({
    actions: {
        // This makes sure that all calls to the {{action 'goBack'}}
        // in the end is run by the application-controllers implementation
        // using the boubling action system. (controller->route->parentroutes)
        goBack: function() {
            this.controllerFor('application').send('goBack');
        }
    },
};

SpeedMind.ApplicationController = Ember.Controller.extend({
    actions: {
        goBack: function(){
            console.log("This is the real goBack method definition!");
        }
    },
});

答案 2 :(得分:2)

你可以让ember动作调用你的方法,而不是在动作本身内部处理它。

App.BooksController = Ember.ArrayController.extend({
            actions: {
                fireUpdateData: function(){
                    App.BooksController.updateData();
                }
            },

            // This is outside of the action
            updateData: function () {
                    console.log("updateData is called!");
                    var books = this.filter(function () {
                        return true;
                    });
                    for(var i=0; i<books.length; i++) {
                        //doSomething…
                    }
                }
        });

现在,只要您想调用updateData(),只需使用

即可
App.BooksController.updateData();

或者是把手文件

{{action "fireUpdateData"}}