[英]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.