需要在状态退出时关闭模态

时间:2014-05-05 19:37:34

标签: javascript angularjs

我正在使用UI-Router和angular bootstrap-ui。我有一个状态设置来创建模态'onEnter'。当我试图关闭模态'onExit'时,我现在遇到了问题。这是基本状态。当输入'items.detail'时它将打开一个模态,当该模态被关闭或解除时它将转换为'items'。

.state('items.detail', {
    url: '/{id}',
    onEnter: function ($stateParams, $state, $modal, $resource) {
        var modalInstance = $modal.open({
            templateUrl: 'views/modal/item-detail.html',
            controller: 'itemDetailCtrl'
        })
        .result.then(function () {
            $state.transitionTo('items');
        }, function () {
            $state.transitionTo('items');
        });
    }
})

我尝试过像这样使用onExit处理程序。但是无法从该处理程序访问modalInstance或modal所在的范围。我尝试注射的所有东西都是未定义的。

.state('items.detail', {
    url: '/{id}',
    onEnter: function ($stateParams, $state, $modal, $resource) {
        var modalInstance = $modal.open({
            templateUrl: 'views/modal/item-detail.html',
            controller: 'itemDetailCtrl'
        })
        .result.then(function () {
            $state.transitionTo('items');
        }, function () {
            $state.transitionTo('items');
        });
    },
    onExit: function ($scope) {
        controller: function ($scope, $modalInstance, $modal) {
            $modalInstance.dismiss();
        };
    }
})

从我的模态控制器中我试图听取状态变化。

$scope.$on('$stateChangeStart', function() {
    $modalInstance.dismiss();
});

我已经用$ scope。$ on和$ rootScope。$ on尝试过这两种方法,但是每次我在任何状态之间转换时都会调用它们。这只会在我打开模态后发生。

如果最后一点不清楚......当我刷新我的角度应用程序时,我可以在所有其他状态之间进行转换而不会调用此侦听器事件但是在我打开该模态之后,所有状态更改都会被该侦听器调用即使模态关闭后也是如此。

3 个答案:

答案 0 :(得分:6)

虽然这个问题已经很老了,但是我最近遇到了同样的情况,并想出了一个更好的解决方案,我决定在这里分享我的结果。关键点是将$ modal.open服务移动到解决部分状态,这是一种预加载数据和$ promise服务,然后将解析后的modelInstance注入onEnter,onExit等。代码可能如下所示:

.state('items.detail', {
    url: '/{id}',
    resolve: {
        modalInstance: function(){
            return $modal.open({
                templateUrl: 'views/modal/item-detail.html',
                controller: 'itemDetailCtrl'
            })
        },
    },
    onEnter: function ($stateParams, $state, modalInstance, $resource) {
        modalInstance 
        .result.then(function () {
            $state.transitionTo('items');
        }, function () {
            $state.transitionTo('items');
        });
    },
    onExit: function (modalInstance) {
        if (modalInstance) {
            modalInstance.close();
        }
    }
})

答案 1 :(得分:3)

我认为你可以更好地组织你的模态开放行为。我不会在状态定义中使用onEnter和onExit处理程序。相反,定义应该处理模态的控制器更好:

.state('items.detail', {
    url: '/{id}',
    controller:'ItemDetailsController',
    template: '<div ui-view></div>'
})

然后定义你的控制器:

.controller('ItemDetailsController', [
    function($stateParams, $state, $modal, $resource){
        var modalInstance = $modal.open({
            templateUrl: 'views/modal/item-detail.html',
            controller: 'ModalInstanceCtrl',
            size: size,
            resolve: {
                itemId: function () {
                   return $stateParams.id;
            }
         modalInstance.result.then(function () {
                $state.go('items');
            }, function () {
                $state.go('items');
         });
      }
    });       
    }
])

然后定义你的ModalInstanceCtrl:

.controller('ModalInstanceCtrl', [ 
    function ($scope, $modalInstance, itemId) {

        //Find your item from somewhere using itemId and some services
        //and do your stuff


        $scope.ok = function () {
            $modalInstance.close('ok');
        };

        $scope.cancel = function () {
           $modalInstance.dismiss('cancel');
        };
    };
]);

通过这种方式,modal将在ModalInstanceCtrl中关闭,你不必担心状态的onExit处理程序。

关于在$ scope上添加的侦听器。似乎在添加侦听器时并且在状态发生变化时永远不会删除它,这会导致内存泄漏,并且每次应用程序更改状态时都会执行处理程序函数!所以最好摆脱那个事件听众,因为你实际上并不需要它。

答案 2 :(得分:2)

您可以通过收听$stateChangeStart event

来阻止离开州
$scope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams){
    console.log('$stateChangeStart', toState);
    if (toState.name != 'items.list'){
        event.preventDefault();
        var top = $modalStack.getTop();
        if (top) {
            $modalStack.dismiss(top.key);
        }
        $state.go('items.list');
    }
});