将控制器传递给$ ionicModal

我想知道你是否可以将控制器传递给$ ionicModal服务。 就像是。

$ionicModal.fromTemplateUrl('templates/login.html', { scope: $scope, controller: 'MyModalCotroller' }) 

有一点上下文:我想有一个分布在整个应用程序的模式,我不想在每个控制器中重复所有的方法(在模态中隐藏,显示,button),我想从“主控制器“保持干净。 这将封装模式的function。

有没有办法做到这一点。? 谢谢

只需在模态的html的主体中添加您要使用的控制器即可。 我创build了一个小提示,向您展示一个基于离子文档中提供的示例的示例: http : //jsfiddle.net/g6pdkfL8/

但基本上:

 <-- template for the modal window --> <ion-modal-view> <ion-content ng-controller="ModalController"> ... </ion-content> <ion-modal-view> 

在离子方面没有直接的方法。 但是,如果您确实想要在一个地方分隔一些通用代码,则可以使用服务来执行此操作。 这里怎么样。

  1. 在模态声明中,将范围传递为null,模态声明也应该在服务中移动。
 app.service('utilsService', function($ionicModal) { this.showModal = function() { var service = this; $ionicModal.fromTemplateUrl('templates/login.html', { scope: null, controller: 'MyModalCotroller' }).then(function(modal) { service.modal = modal; service.modal.show(); }); }; this.hideModal = function() { this.modal.hide(); }; }); 

  1. 你所有的常用方法也将进入相同的服务。

  1. 将对此服务的引用添加到您的控制器的作用域中。
  app.controller('indexController', function($scope, utilsService) { $scope.utilsService = utilsService; }); 

  1. 现在,您可以直接使用此服务从视图中调用所有常用方法。
 eg <button ng-click="utilsService.hideModal()">Hide modal</button> 

基于这个问题和其他需求,我创build了一个有用的服务。

无论如何,使用CodePen代码,这个更新,改进,并提供$ ionicModal参数的“选项”。

看到这个职位: 离子莫代尔服务或在操作中看到: CodePen

 (function () { 'use strict'; var serviceId = 'appModalService'; angular.module('app').factory(serviceId, [ '$ionicModal', '$rootScope', '$q', '$injector', '$controller', appModalService ]); function appModalService($ionicModal, $rootScope, $q, $injector, $controller) { return { show: show } function show(templateUrl, controller, parameters) { // Grab the injector and create a new scope var deferred = $q.defer(), ctrlInstance, modalScope = $rootScope.$new(), thisScopeId = modalScope.$id; $ionicModal.fromTemplateUrl(templateUrl, { scope: modalScope, animation: 'slide-in-up' }).then(function (modal) { modalScope.modal = modal; modalScope.openModal = function () { modalScope.modal.show(); }; modalScope.closeModal = function (result) { deferred.resolve(result); modalScope.modal.hide(); }; modalScope.$on('modal.hidden', function (thisModal) { if (thisModal.currentScope) { var modalScopeId = thisModal.currentScope.$id; if (thisScopeId === modalScopeId) { deferred.resolve(null); _cleanup(thisModal.currentScope); } } }); // Invoke the controller var locals = { '$scope': modalScope, 'parameters': parameters }; var ctrlEval = _evalController(controller); ctrlInstance = $controller(controller, locals); if (ctrlEval.isControllerAs) { ctrlInstance.openModal = modalScope.openModal; ctrlInstance.closeModal = modalScope.closeModal; } modalScope.modal.show(); }, function (err) { deferred.reject(err); }); return deferred.promise; } function _cleanup(scope) { scope.$destroy(); if (scope.modal) { scope.modal.remove(); } } function _evalController(ctrlName) { var result = { isControllerAs: false, controllerName: '', propName: '' }; var fragments = (ctrlName || '').trim().split(/\s+/); result.isControllerAs = fragments.length === 3 && (fragments[1] || '').toLowerCase() === 'as'; if (result.isControllerAs) { result.controllerName = fragments[0]; result.propName = fragments[2]; } else { result.controllerName = ctrlName; } return result; } } // end })(); 

用法:

 appModalService .show('<templateUrl>', '<controllerName> or <controllerName as ..>', <parameters obj>) .then(function(result) { // result from modal controller: $scope.closeModal(result) or <as name here>.closeModal(result) [Only on template] }, function(err) { // error }); 

您可以使用其他服务来集中所有模态的configuration:

 angular.module('app') .factory('myModals', ['appModalService', function (appModalService){ var service = { showLogin: showLogin, showEditUser: showEditUser }; function showLogin(userInfo){ // return promise resolved by '$scope.closeModal(data)' // Use: // myModals.showLogin(userParameters) // get this inject 'parameters' on 'loginModalCtrl' // .then(function (result) { // // result from closeModal parameter // }); return appModalService.show('templates/modals/login.html', 'loginModalCtrl as vm', userInfo) // or not 'as controller' // return appModalService.show('templates/modals/login.html', 'loginModalCtrl', userInfo) } function showEditUser(address){ // return appModalService.... } }]); 

创build一个指令在模态中使用,在指令内部可以指定模态它自己的控制器和范围。 如果有人想要一些示例代码,我可以把一些东西。

我正在寻找一种简单的方法来将控制器附加到模态实例,并使用单个服务来pipe理所有的模块。 另外,我希望模态具有独立的子范围。 我对使用ng-controller并不满意,而且我发现其他的答案太复杂了,以至于你很容易忽略范围,最终导致循环或不可识别的依赖。 我为我的目的创build了以下服务。

您可以传递一个可选的parentScope参数,以便将父范围显式分配给创build的模式范围。

你可以很容易地修改instantiateModal方法来接受$ ionicModal选项作为参数 – 我只是不需要它。

顺便说一句 – 我正在使用Webpack babel-loader进行转换,并使用html-loader加载模板。 但是,最简单的forms就是基本的服务。

 /** * nvModals * @description A modal manager. Attaches a specified controller to an $ionicModal instance. */ import myModalTemplate from '../common/modals/my-modal.html'; import otherModalTemplate from '../common/modals/other-modal.html'; let nvModals = function ( $rootScope, $controller, $ionicModal ) { var _self = this; _self.methods = { /** * Instantiate and show a modal */ showMyModal: (parentScope) => { var parentScope = parentScope || null; _self.methods.instantiateModal('MyModalController', myModalTemplate, parentScope) .show(); }, /** * Instantiate and show another modal */ showOtherModal: (parentScope) => { var parentScope = parentScope || null; _self.methods.instantiateModal('OtherModalController', otherModalTemplate, parentScope) .show(); }, /** * Instantiate a new modal instance * * @param {object} controller Controller for your modal * @param {string} template Template string * @param {object} parentScope Optional parent scope for the modal scope * @return {object} Modal instance */ instantiateModal: (controller, template, parentScope) => { var modalScope; if(parentScope) { modalScope = $rootScope.$new(false, parentScope); } else { modalScope = $rootScope.$new(false); } $controller(controller, { '$scope': modalScope }); modalScope.modal = $ionicModal.fromTemplate(template, { scope: modalScope, animation: 'slide-in-up' }); modalScope.$on('modal.hidden', (evt) => { evt.targetScope.$destroy(); if (evt.targetScope.modal) { evt.targetScope.modal.remove(); } }); modalScope.hideModal = function () { modalScope.modal.hide(); }; return modalScope.modal; } }; return _self.methods; }; nvModals.$inject = [ '$rootScope', '$controller', '$ionicModal' ]; export default nvModals; 

在你的控制器…

 $scope.modals = nvModals; 

在关联的模板中

 ng-click="modals.showMyModal()" 

在模态模板中

 ng-click="hideModal()" 

好吧,我已经看到了很多不同的解决scheme,以更好地处理离子模式,因为缺乏控制器选项或类似的东西。 在和React玩了一段时间之后,我想出了另外一个select,在我看来更具说明性。 在ES6中,只是一个原型,但你可以有一个想法:

 (function() { 'use strict'; @Inject('$scope', '$ionicModal', '$transclude', '$rootScope') class Modal { constructor() { let { animation, focusFirstInput, backdropClickToClose, hardwareBackButtonClose } = this; $transclude((clone, scope) => { let modal = this.createModalAndAppendClone({ scope, animation, focusFirstInput, backdropClickToClose, hardwareBackButtonClose }, clone); this.setupScopeListeners(modal.scope); this.createIsOpenWatcher(); this.addOnDestroyListener(); this.emitOnSetupEvent(modal.scope); }); } setupScopeListeners(scope) { scope.$on('modal.shown', this.onShown); scope.$on('modal.hidden', this.onHidden); scope.$on('modal.removed', this.onRemoved); } addOnDestroyListener() { this.$scope.$on('$destroy', () => { this.removeModal(); }); } createIsOpenWatcher() { this.isOpenWatcher = this.$scope.$watch(() => this.isOpen, () => { if (this.isOpen) { this.modal.show(); } else { this.modal.hide(); } }); } emitOnSetupEvent(scope) { this.onSetup({ $scope: scope, $removeModal: this.removeModal.bind(this) }); } createModalAndAppendClone({ scope = this.$rootScope.$new(true), animation = 'slide-in-up', focusFirstInput = false, backdropClickToClose = true, hardwareBackButtonClose = true }, clone) { let options = { scope, animation, focusFirstInput, backdropClickToClose, hardwareBackButtonClose } this.modal = this.$ionicModal.fromTemplate('<ion-modal-view></ion-modal-view>', options); let $modalEl = angular.element(this.modal.modalEl); $modalEl.append(clone); return this.modal; } removeModal() { this.modal.remove(); this.isOpenWatcher(); } } function modal() { return { restrict: 'E', transclude: true, scope: { 'onShown': '&', 'onHidden': '&', 'onRemoved': '&', 'onSetup': '&', 'isOpen': '=', 'animation': '@', 'focusFirstInput': '=', 'backdropClickToClose': '=', 'hardwareBackButtonClose': '=' }, controller: Modal, bindToController: true, controllerAs: 'vm' } } angular .module('flight') .directive('modal', modal); })(); 

然后你可以像这样使用它:

 <modal is-open="vm.isOpen" on-shown="vm.onShown()" on-hidden="vm.onHidden()" on-removed="vm.onRemoved()" on-setup="vm.onSetup($scope, $removeModal)"> <div class="bar bar-header bar-clear"> <div class="button-header"> <button class="button button-positive button-clear button-icon ion-close-round button-header icon" ng-click="vm.closeModal()"></button> </div> </div> <ion-content class="has-header"> <create-flight-form on-submit="vm.submit()"></create-flight-form> </ion-content> </modal> 

你打开和closures模式与一个布尔值绑定到is-open,然后注册不同事件的callback。