【问题标题】:How to use the same controller for modal and non-modal form in Angular UI Bootstrap?如何在 Angular UI Bootstrap 中对模态和非模态表单使用相同的控制器?
【发布时间】:2014-07-09 23:07:33
【问题描述】:

我有一个带有注册表单的模式。相同的表单应该显示在着陆页的底部,而不是模式。

目前我处理注册模式的控制器将$modalInstance 作为其参数之一以及$scope 等。如果我将ng-controller="SignUpCtrl" 添加到登录页面中的元素,它不起作用,因为控制器不是t 通过 $modal.open 方法创建,因此 Angular 抱怨 Unknown provider: $modalInstanceProvider <- $modalInstance

我有一个用于注册用户的服务(authService.signUp(data).then/catch...),但控制器本身做的更多——处理输入、发出事件(例如,带有翻译的错误消息)、设置 cookie 等。

在不复制几乎整个控制器代码的情况下处理这种情况的最佳方法是什么?我应该将代码从控制器移到另一个更高级别的服务中吗?

【问题讨论】:

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


【解决方案1】:

在挣扎了很长时间后,我找到了一个更简单的技巧,可以将我们的控制器重用于模态和正常情况。

我发现我们可以将调用者的作用域传递给模态控制器,所以我将 modalInstance 推入 $scope 并将其传递给模态控制器。 现在你没有未知的提供者问题,因为 $scope 是一个众所周知的问题。

下面是一个例子:

CallerController = function($rootScope, ...) {
   var modalScope = $rootScope.$new();
   modalScope.modalInstance = $modal.open({
        templateUrl: tempUrl,
        controller: ReusableModalController,
        scope: modalScope // <- This is it!
    });

    modalScope.modalInstance.result.then(function (result) {
        // Closed
    }, function () {
        // Dismissed
    });
};

ReusableModalController = function($scope, ...){
    var dataToSendBack = 'Hello World';
    $scope.modalInstance.close(dataToSendBack);
};

干杯!

【讨论】:

  • 漂亮!我最终使用了$scope.modalInstance = $modal.open({ [...] scope: $scope });
  • @jsruok 如果您不愿意,请注意不要覆盖 CallerController 的变量 :)
  • 谢谢!我正在拔头发
  • var modalScope = $rootScope.$new();有什么用。根据angular-ui.github.io/bootstrap/#/modal 文档,scope - a scope instance to be used for the modal's content (actually the $modal service is going to create a child scope of a provided scope). Defaults to $rootScope
  • @Aniket Sinha 就像它说的那样,模态框使用范围,如果我们没有在 $modal.open({... scope: modalScope ...}) 中指定它,模态框将自动创建一个范围。在这种情况下,我们想以一种棘手的方式将 modalInstance 传递给模态,也就是说,我用 var modalScope = $rootScope.$new(); 创建一个范围,然后将 modalInstance 推入新的 modalScope ,最后告诉模态“不要”不要创建范围,使用我给你的东西”。对不起我的英语不好......
【解决方案2】:

如果您使用的是 ui-router,您可以轻松地使用 ui-router 的解析来提供 $uibModalInstance(之前是 $modalInstance):

$stateProvider
.state('conductReview', {
    url: '/review',
    templateUrl: '/js/templates/review.html',
    controller: 'yourController',
    resolve: {
        $uibModalInstance: function () { return null; } // <- workaround if you want to use $uibModalInstance in your controller.
    }
})

这样您就可以像使用普通控制器一样使用模态控制器。如果您在控制器中注入 $uibModalInstance ,它将为空。

【讨论】:

    【解决方案3】:

    如果您想对模态表单和登录页面表单使用相同的控制器,请使用

    modalInstance.result.then(function (selectedItem) { $scope.selected = selectedItem; }, function () { $log.info('Modal dismissed at: ' + new Date()); });

    您可以从selectedItem 的模态表单中获取所有数据,并将其用于登录页面表单。 另外,如何打开模态。如果是通过按钮,请使用$modal.open 将该 ng-model 绑定到打开模式。不要为您的模式创建单独的控制器。使用与登录页面相同的控制器。这样您就可以使用 1 个控制器打开模态以及关闭模态后的其他功能。

    PS: 这里给出的代码 sn-p 来自 angular ui's page。检查该页面的文档以获取 selectedItem

    【讨论】:

    • 谢谢,但是这个解决方案有一个问题,因为(如果我理解正确的文档)你必须关闭模式来传递数据。如果您关闭模式,但注册失败,例如因为电子邮件已经被占用了?这就是为什么我在控制器内部处理传递给$modal.open 的实际逻辑 - 以便能够在不关闭模式的情况下处理错误。
    • 是的,模态需要关闭。但是您仍然可以在模式内执行逻辑来检查可用的电子邮件 ID。你为什么不创建一个 plunk 或 fiddle,它会帮助人们解决你的问题
    • 当然,但这正是问题所在。如果我将逻辑移动到依赖$modalInstance 的模态控制器,问题是如何在没有$modalInstance 的其他地方重用它。这是我当前的解决方案gist.github.com/szimek/76fc9fc295f317c3cac8,它不需要太多的代码更改(例如创建新服务),但也许有更好的解决方案。
    • 为什么不在模态控制器中直接使用逻辑。如果你想重用代码,你总是可以使用服务。编辑:IMO,您应该为您的逻辑使用服务,并将该服务作为依赖项添加到您的模态控制器中。
    • 谢谢我正在使用该代码将数据从模态传递到调用者控制器,它的工作原理就像一个魅力:D
    猜你喜欢
    • 1970-01-01
    • 2015-03-09
    • 1970-01-01
    • 1970-01-01
    • 2015-03-04
    • 1970-01-01
    • 1970-01-01
    • 2016-03-10
    • 1970-01-01
    相关资源
    最近更新 更多