簡體   English   中英

從角度服務中調用控制器中方法的最佳方法是什么?

[英]What is the best way to call a method in a controller from a service in angular?

我已經在SO和Google中對此問題進行了一些研究。 但是,沒有一個答案符合我的目的。

我在HTML視圖中有一個模式,用於在應用程序中顯示彈出通知。 我想在模式上的div上顯示一些按鈕(“確定”,“取消”,“登錄”等),我將其作為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服務,該服務具有一個可以調用的方法,該方法可以在$rootscope$broadcast並調用$rootscope "popup"事件,而我正在處理該事件在PopupController 在這種情況下,一切都已觸發並正常工作。 我面臨的唯一問題是延遲在UI上渲染彈出窗口,顯示彈出窗口后我立即看到消息,但是按鈕的渲染非常慢(大約3秒),這是因為加載了其他一些網頁在后台。

當我在Internet上搜索該問題時,我還發現可以將整個設置更改為指令,並且可以將動態內容的呈現方式(在本例中為彈出窗口和按鈕)放在該指令的鏈接函數中。

我看到的另一種方法是直接在服務中處理DOM操作,這當然不是一個好方法。

我是否錯過任何其他方法或解決方案?

我想知道的是,最好的方式是處理這種情況,這在程序上和設計上都是明智的。

如果我不清楚,請告訴我。 我將嘗試再次解釋該問題。

指令將是比DOM操作更好的選擇。 另外,您應該考慮將jQuery對話框的用法更改為https://angular-ui.github.io/bootstrap/#/modal

是一個如何完成的示例:

1)創建指令

 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);
         });
       };

     }
   }
 });

2)創建modalInstance指令

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

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

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

3)創建指令模板directiveTemplate.html

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

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

4)創建彈出模板'myModalContent.html'

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

5)定義您的控制器,您將在其中顯示要在彈出窗口中顯示的按鈕和消息的列表(出於演示目的,這里是兩個不同的項目列表和兩個消息)

 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>

如果您從不同的角度應用程序實例訪問了指令, var app = angular.module('myPopupDynamicModule', ['ngAnimate', 'ui.bootstrap']);只是將指令應用程序注入所需的實例中(請確保指令和模態實例具有自己定義的模塊,例如: var app = angular.module('myPopupDynamicModule', ['ngAnimate', 'ui.bootstrap']);並在以下示例var app2 = angular.module('ui.bootstrap.demo', ['ngAnimate', 'ui.bootstrap', 'myPopupDynamicModule']);其用於注入其他模塊: var app2 = angular.module('ui.bootstrap.demo', ['ngAnimate', 'ui.bootstrap', 'myPopupDynamicModule']);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM