从角度服务中调用控制器中方法的最佳方法是什么?

时间:2016-01-25 09:03:46

标签: javascript angularjs

我已经在SO和Google上对这个问题进行了一些研究。但没有一个答案符合我的目的。

我在HTML视图中有一个模态,用于在我的应用中显示弹出通知。 我希望在我通过的div模式中显示一些按钮(' OK','取消''登录'等等)动态地作为JS对象。作为键的按钮的名称和作为值的回调函数。

示例:

{
    "Login": function(){....}
}

{
    "OK": function(){...},
    "Cancel": function(){...}
}

现在我将这种对象传递给我在视图中的弹出模式的控制器中的方法showPopup(message, buttonMap)

message是弹出窗口上的显示消息,buttonMap是示例中的对象。

控制器:

angular.module('core').controller('PopupController', ['$rootScope', 'LogService', 'MessageHandlerService',
    function ($rootScope, LogService, MessageHandlerService) {    
        var ctrl = this;

        ctrl.buttonMap = {};
        ctrl.btnWidth = 100;

        $rootScope.$on('popup', showPopup);

        function showPopup (event, message, buttonMap) {
            $('#genericModalDialog .popup-content p').html(message);
            ctrl.buttonMap = buttonMap;
            var numberOfButtons = Object.keys(buttonMap).length;
            ctrl.btnWidth = (100 - numberOfButtons*2)/numberOfButtons;
            $("#genericModalDialog").modal('show');
        }

        ctrl.callbackFor = function callbackFor(key) {
            ctrl.buttonMap[key].call(null);
        };
    }
]);

服务

    angular.module('core').service('PopupService', ['$rootScope', 'LogService', 'CacheService', 'MessageHandlerService',
        function ($rootScope, LogService) {

            this.isPopupShown = function (){
                return $("#genericModalDialog").hasClass('in');
            }

            this.showPopup = function (message, btnMap){
                $rootScope.$broadcast('popup', message, btnMap);
            }

            this.closePopup = function (){
                $("#genericModalDialog").modal('hide');
            }

        }
    ]);

查看:

<div ng-controller="PopupController as popupCtrl" class="modal fade" id="genericModalDialog" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
  <div class="vertical-alignment-helper">
    <div class="modal-dialog vertical-align-center" style="width:94%;">
      <div class="modal-content">
        <div class="modal-body">
          <br/><br/>
          <div class="popup-content">
            <p align="center"></p><br/>
            <div class="popup-action">
              <button type="button" class="btn" style="width:{{popupCtrl.btnWidth}}%; margin:1%" ng-repeat="(buttonName, callBack) in popupCtrl.buttonMap" ng-click="popupCtrl.callbackFor(buttonName)">{{buttonName}}</button>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

由于我不想在每个其他控制器/服务中实例化PopupController,我已经编写了一个名为PopupService的服务,该服务有一个可以调用的方法$broadcast "popup" 1}} $rootscope上名为PopupController的事件,我正在 Downloading install package from https://downloads.wordpress.org/plugin/types.1.8.11.zip… Unpacking the package… Installing the plugin… The package could not be installed. No valid plugins were found. Plugin install failed.` 处理此事件。在这种情况下,一切都被触发并正常工作。我面临的唯一问题是在UI上呈现弹出窗口的延迟,我一看到弹出窗口就看到了消息但是按钮的渲染非常慢(大约3秒),这是因为加载了一些其他网页在后台。

当我在互联网上搜索这个问题时,我也发现这个总体设置可以改为指令,动态内容的渲染(在这种情况下是弹出窗口和按钮)可以放在链接功能中指令。

我看到的另一种方法是直接处理服务中的DOM操作,这当然不是一个好方法。

我是否错过任何其他方法或解决此问题?

所有我想知道的是最好的方法,处理这种以编程方式和设计明智的方式。

如果我不清楚请告诉我。我会尝试再次解释这个问题。

1 个答案:

答案 0 :(得分:0)

指令将是DOM操作的更好选择。另外,您应该考虑将jQuery对话框的用法更改为https://angular-ui.github.io/bootstrap/#/modal

Here就是一个如何做到的例子:

1)创建指令

DoAsyncNetworkIO

2)创建modalInstance指令

static object mutex = new object();
static Task currentTask;

async Task Fetch()
{
    lock(mutex)
    {
        if(currentTask != null)
            return currentTask;
    }

    currentTask = DoAsyncNetworkIO();
    await currentTask;

    lock(mutex)
    {
        var task = currentTask;
        currentTask = null;
        return task;
    }
}

3)创建指令模板 app.directive('myModal', function() { return { restrict: 'E', scope: { items: "=", message: "=" }, replace: true, templateUrl: "directiveTemplate.html", controller: function($scope, $uibModal, $log) { $scope.open = function(size) { var modalInstance = $uibModal.open({ animation: $scope.animationsEnabled, templateUrl: 'myModalContent.html', controller: 'ModalInstanceCtrl', size: size, resolve: { items: function() { return $scope.items; }, message: function() { return $scope.message; } } }); modalInstance.result.then(function(selectedItem) { $scope.button = selectedItem.name; $scope[selectedItem.callback](selectedItem.name); }); }; } } });

app.controller('ModalInstanceCtrl', function($scope, $uibModalInstance, items, message) {

  $scope.items = items;
  $scope.message = message;

  $scope.close = function(item) {
    $uibModalInstance.close(item);
  };
});

4)创建弹出式模板&#39; myModalContent.html&#39;

directiveTemplate.html

5)定义你的控制器,你将在弹出窗口中显示按钮列表和消息(为了演示目的,这里有两个不同的项目列表和两个消息)

<div>
  {{buttonClicked}}
  <br> {{button}}

  <button type="button" class="btn btn-default" ng-click="open('sm')">{{message}}</button>
</div>

并为了您所需的指令:

{{message}}
<button ng-repeat="item in items" type="button" class="btn btn-default" ng-click="close(item)">{{item.name}}</button>

如果您从不同的角度应用程序实例访问指令,那么只需将指令应用程序注入所需的应用程序(确保指令和模态实例具有自己定义的模块ex: app.controller('ModalDemoCtrl', function($scope) { $scope.message = "modal 1"; $scope.items = [{ name: 'item1', callback: "test1" }, { name: 'item2', callback: "test2" }, { name: 'item3', callback: "test3" }]; $scope.message2 = "modal 12222"; $scope.items2 = [{ name: 'item1222', callback: "test1" }, { name: 'item2222', callback: "test2" }, { name: 'item3222', callback: "test3" }]; $scope.test1 = function(message) { $scope.buttonClicked = "clicked test1"; } $scope.test2 = function(message) { $scope.buttonClicked = "clicked test2"; } $scope.test3 = function(message) { $scope.buttonClicked = "clicked test3"; } }); ,这是一个在此示例之后用于注入其他模块:<div ng-controller="ModalDemoCtrl"> <my-modal items="items" message="message"></my-modal> </br> <my-modal items="items2" message="message2"></my-modal> </div>