PAYATHON 2026

如何从 PopupController 调用 openAddCardModal()

支付阿杰

结论

不要在 PopupController 中直接调用 ModalController 的方法。两个 Controller 通常使用不同的 $scope,也不应互相持有对方的实例。

按现有结构,可以由 PopupController 广播事件,ModalController 收到事件后再调用 openAddCardModal()。还要处理 $ionicModal.fromTemplateUrl() 的异步初始化,避免用户点击时 modal 尚未创建。

实现方式

在 PopupController 中注入 $rootScope,点击 “Add” 时广播事件:

function PopupController(
    $scope,
    $rootScope,
    $ionicPopup,
    $timeout,
    $state
) {
    $scope.showPaymentOptionsPopup = function() {
        $ionicPopup.confirm({
            title: 'Payment Options',
            cssClass: 'popup-vertical-buttons',
            buttons: [
                {
                    text: 'Add',
                    type: 'button-positive',
                    onTap: function() {
                        $rootScope.$broadcast('payment:add-card');
                    }
                },
                {
                    text: 'Edit',
                    type: 'button-positive',
                    onTap: function() {
                    }
                },
                {
                    text: 'Close',
                    type: 'button-dark',
                    onTap: function() {
                    }
                }
            ]
        });
    };
}

在 ModalController 中监听这个事件:

function ModalController($scope, $ionicModal, $stateParams) {
    var modalReady = $ionicModal.fromTemplateUrl(
        'views/payment-add-card.view.html',
        {
            scope: $scope,
            animation: 'slide-in-up'
        }
    ).then(function(modal) {
        $scope.addCardModal = modal;
        return modal;
    });

    $scope.openAddCardModal = function() {
        return modalReady.then(function(modal) {
            return modal.show();
        });
    };

    $scope.closeAddCardModal = function() {
        if ($scope.addCardModal) {
            return $scope.addCardModal.hide();
        }
    };

    var stopListening = $scope.$on('payment:add-card', function() {
        $scope.openAddCardModal();
    });

    $scope.$on('$destroy', function() {
        stopListening();

        if ($scope.addCardModal) {
            $scope.addCardModal.remove();
        }
    });
}

为什么不能直接调用

$scope.openAddCardModal 只存在于 ModalController 对应的作用域中。除非两个 Controller 正好处于可以通过父子 $scope 访问的层级,否则 PopupController 无法直接取得这个函数。

即使能通过下面的方式访问,也不建议这样写:

$scope.$parent.openAddCardModal();

这种写法依赖页面的 DOM 和作用域层级。模板结构或路由一旦改变,调用就可能失效。

注意事项

$ionicModal.fromTemplateUrl() 返回 Promise,modal 不会同步创建。把 modal.show() 放进 modalReady.then(),可以避免下面这类错误:

Cannot read property 'show' of undefined

如果弹窗和 modal 属于同一个页面功能,可以让同一个 Controller 同时管理 $ionicPopup 和 $ionicModal,代码会更简单。如果多个页面都要打开这个 modal,则可以把 modal 的创建、打开和销毁逻辑封装到 AngularJS service 中。相比全局事件,这种方式更容易维护。

备注:内容仅供参考。