Каков наилучший способ вызова метода в контроллере из службы в angular?

0

Я провел некоторое исследование по этому вопросу как в SO, так и в Google. Но ни один из ответов не служит моей цели.

У меня модальный вид в HTML, который я использую для отображения всплывающих уведомлений в моем приложении. Я хочу показать несколько кнопок ("ОК", "Отмена", "Вход" и т.д.) В div модуле, который я динамически передаю как объект JS. Название кнопки - это ключ, а функция обратного вызова - это значение.

Примеры:

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

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

Теперь я showPopup(message, buttonMap) такие объекты методу showPopup(message, buttonMap) в контроллере всплывающего showPopup(message, buttonMap) у меня есть.

message является отображаемым сообщением во всплывающем buttonMap а 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 $rootscope события под названием "popup" на $rootscope и я обрабатываю это событие в PopupController. В этом случае все срабатывает и работает нормально. Единственная проблема, с которой я сталкиваюсь, - это задержка в отображении всплывающего окна в пользовательском интерфейсе, я вижу сообщение, как только отображается всплывающее окно, но рендеринг кнопок очень медленный (примерно 3 секунды), это связано с загрузкой какой-либо другой веб-страницы на заднем фоне.

Когда я искал информацию об этой проблеме в Интернете, я также обнаружил, что эта общая настройка может быть изменена на директиву и рендеринг динамического содержимого (в этом случае всплывающее окно и кнопки на нем.) Можно поместить в функцию ссылки этой директивы.

Другой подход, который я видел, заключался в прямом обращении с манипуляциями DOM в службе, что, конечно, не очень хорошо.

Я пропустил какой-либо другой подход или решение этой проблемы?

Все, что я хочу знать, - это то, что было бы наилучшим образом, чтобы справиться с этой ситуацией, которая является программным и конструктивным.

Если я не понимаю, сообщите мне. Я попробую снова объяснить проблему.

Теги:

1 ответ

0

Директива будет гораздо лучшим выбором, чем манипуляция 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>

Если у вас есть директива, доступная из разных экземпляров углового приложения, чем просто вставлять директивное приложение в необходимое (убедитесь, что директива и модальный экземпляр имеют свой собственный определенный модуль ex: var app = angular.module('myPopupDynamicModule', ['ngAnimate', 'ui.bootstrap']); и это тот, который будет использоваться для инъекций в другие модули, следующие этому примеру: var app2 = angular.module('ui.bootstrap.demo', ['ngAnimate', 'ui.bootstrap', 'myPopupDynamicModule']);)

  • 0
    Спасибо за предложение, но у меня есть некоторые опасения здесь, даже если я изменю диалоговое окно Jquery на угловой модальный режим, я смогу вызвать всплывающее отображение из службы, тогда как манипуляции с DOM или динамический контент должны быть доступны в контроллере. Это снова приводит нас к квадрату 1, как я могу вызвать метод в Контроллере из Службы?
  • 0
    @VamshiKrishnaAlladi для этого, вы просто создадите модальный экземпляр в контроллере и передадите его в службу, где просто откроется модальный. Однако я не понимаю, почему вы смешиваете сервис (который должен быть отделен от манипуляции с представлением) с модальным (который является компонентом представления и должен поддерживаться контроллером или директивой). Я думаю, что вы неправильно понимаете использование директивы.
Показать ещё 5 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню