从控制器内检测ui-router状态变化并相应地关闭Modal

时间:2014-12-04 11:59:08

标签: angularjs angular-ui-bootstrap angular-ui-router

我使用$modal.open({...})方法打开UI-Bootstrap模式。当用户按下后退按钮时,我需要关闭它。

result方法返回的open()承诺在这种情况下无效,因为它无法检测由于后退按钮导致的状态更改。现在,当按下后退按钮时,状态会发生变化,但模态会保持打开状态。

基本上我遇到的问题是this question,但即使它有一个选定的答案,问题也没有从评论中得到证实。 This other question类似,但也无法解决后退按钮问题。

我需要一些方法来检测当前状态是否已从控制器中发生变化并调用$modalInstance.close()$scope.$close()方法。

我可以监听$stateChangeStart事件并检查fromState参数以有条件地关闭模态。但是,此事件也将不必要地继续为所有后续状态变化而开火。

更新:因此,我尝试收听该事件,并在第一次触发时立即取消注册。这样我就可以听到后退按钮状态的变化,然后在我想要的时候停止它。模态的最终代码如下:

$stateProvider.state('itemList.itemNew', {
    url: '/new',
    onEnter: function($state, $modal) {
        $modal.open({
            templateUrl: "/static/partials/item/form.html",
            controller: function($http, $scope, $modalInstance) {
                $scope.editableItem = {};
                $scope.saveItem = function(item) {
                    $http.post('/api/item', item)
                    .success(function(data) {
                        $modalInstance.close(data);
                        alert("Saved Successfully");
                    }).error(function(data) {
                        alert("There was an error.");
                    });
                };
                //Register listener specifically for the back button :(
                deRegister = $scope.$on('$stateChangeSuccess', 
                    function(event, toState, toParams, fromState, fromParams) {
                        if (toState.name === 'itemList' && 
                            fromState.name === 'itemList.itemNew') {
                            $modalInstance.close();//Close the modal
                            deRegister();//deRegister listener on first call
                        }
                    }
                );
            }
        }).result.then(function() {
            //Promise Resolved, Modal Closed.. So reload
            $state.go("^", null, {
                "reload": true
            });
        }, function() {
            //Promise Rejected, Modal Dismissed.. no reload
            $state.go("^");
        });
    },
});

我仍然认为应该有更好的方法来做到这一点。 Constellates显然决定完全从ui-bootstrap转储modal.js。我是否应该这样做,并使用普通的Bootstrap CSS从<ui-view/>中简单地渲染模态?

1 个答案:

答案 0 :(得分:5)

我需要解决同样的问题。也许是一个略有不同的设置,但我相信它可能适合你。

我正在使用angular-modal-service,我相信无论如何都会在bootstrap上运行。

在模态控制器内部,我使用了以下内容:

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

$scope.stateChange = function() {
    //  Manually hide the modal using bootstrap.
    $element.modal('hide');
    //  Now close as normal, but give 500ms for bootstrap to animate
    close('', 500);
};

第二个功能只是根据&#34; docs 退出模式的手动方式;我不想使用&#39;数据-dismiss&#39;按钮上的属性,如何手动关闭模态?&#34;。它说:

  

您需要做的就是抓住控制器中的模态元素,然后调用bootstrap模态函数来手动关闭模态。然后将关闭函数调用为正常

现在,如果状态发生变化(包括用户发起的后退按钮点击),模态会优雅地消失。