如何从 backbone 控制器执行 angularJS 控制器中的功能

How can I execute a function in an angularJS controller from a backbone controller

我正在开发最初使用 backbone 和 jQuery 创建的应用程序,但是由于客户要求,新模块是使用 angular 构建的。应用程序的路由使用 backbone 路由处理,我们已成功集成 angular 个模块。

实际问题是,我需要检索 angular 中模块的当前实例,并根据 backbone 控制器处理的操作从该模块的控制器执行函数。

这是我的 angular 模块和控制器的样子:

//In chat.module.js
( function () {
angular
    .module( 'chat.module', [] );
})();

//In chat.controller.js
(function () {
angular
        .module('chat.module')
        .controller('chat.controller', ['profileFactory', '$filter', '$q', '$timeout', 'Position', 'Chat', chat]);

function chat(profileFactory, $filter,  $q, $timeout, Position, Chat) {
    var vm = this;
    vm.initChatFlag = false;

    vm.initChat = initChat;
    vm.setInformation = setInformation;


    function setInformation() {
        //handle business logic here
    }

    ...

在backbone中创建模块如下:

        chatmodule: function () {
        var self = this;
        var element = angular.element(document.querySelector('#modalCallback'));
        var chat = angular.element(document.querySelector('#chatModule'));
        var isInitializedChat = chat.injector();

        var isInitialized = element.injector();
        if (!isInitialized) {
            angular.bootstrap($('#modalCallback'), ['app']);
        }
        if (!isInitializedChat) {
            angular.bootstrap($('#chatModule'), ['app']);
        }

        //TODO: chat.controller.setInformation() get access to fields like chat.controller.initChatFlag etc

主应用模块定义如下:

    (function(){
    angular
        .module('app',[
            'callback',
            'ui.bootstrap',
            '720kb.datepicker',
            'ngLocale',
            'directives.module',
            'interceptor',
            'directive.loading',
            'angularUtils.directives.dirPagination',
            'blog.module',
            'profile.module',
            'filters.module',
            'chat.module',
            'ui.toggle',
        ]);
})();

AngularJS $injector 是很多魔法发生的地方,所以如果你在 AngularJS 代码之外公开它,你可以将它连接到 non-AngularJS代码如下:

//A simple AngularJS service:
app.service('myService', function() {
  this.message = "This is my default message.";
});

//Expose the injector outside the angular app.
app.run(function($injector, $window) {
  $window.angularInjector = $injector;
});

//Then use the injector to get access to the service.
//Make sure to wrap the code in a `$apply()` so an 
//AngularJS digest cycle will run
function nonAngularEventHandler() {
  angularInjector.invoke(function(myService, $rootScope) {    
    $rootScope.$apply(function() {
      myService.message = "Now this is my message."
    });
  });
}

编辑:或者,像这样简化调用。

//Instead of exposing the $injector directly, wrap it in a function
//which will do the $apply() for you.
app.run(function($injector, $window, $rootScope) {

  $window.callInMyAngularApp = function(func) {
    $rootScope.$apply(function() {
      $injector.invoke(func);
    });
  }

});

//Then call that function with an injectable function like so.
function nonAngularClick() {
  callInMyAngularApp(function(myService) {    
      myService.message = "Now this is my message."
  });
}

//And remember if you're minifying, you'll want the minify-safe
//version of the injectable function like this
function nonAngularClick() {
  callInMyAngularApp(['myService', function(myService) {    
      myService.message = "Now this is my message."
  }]);
}

更新:(我保证是最后一个!) 以上可以正常工作,但您可能需要考虑公开 well-defined API 而不是通用的可注入接口。考虑以下因素。

//Now I have a limited API defined in a service
app.service("myExternalApi", function($rootScope, myService) {
  this.changeMyMessage = function(message) {
    $rootScope.$apply(function() {
      myService.message = message;
    });
  };
});

//And I just expose that API
app.run(function($window, myExternalApi) {
  $window.myExternalApi = myExternalApi;
});

//And the call from outside of angular is much cleaner.
function nonAngularClick() {
  myExternalApi.changeMyMessage("Now this is my message.");
}

我能够使用来自此 post 的答案访问控制器 -

    var Chat = angular.element(document.querySelector('#chatModule')).scope();

    if(!Chat) return;

    if(Chat.chatCtrl.initChatFlag) {
        Chat.chatCtrl.setInformation();
    }else{
        console.log('Chat has not been initialized');
    }