【问题标题】:Angular UI Bootstrap modal dialog in $http interceptor hangs the browser$http 拦截器中的 Angular UI Bootstrap 模式对话框挂起浏览器
【发布时间】:2014-11-05 17:10:08
【问题描述】:

我正在尝试实现延迟授权,仅当用户触发对需要身份验证的 API 的调用时才会引入登录对话框。我正在使用引导程序ui.bootstrap.modal(和模态中的ui.bootstrap.alert)。问题是这些指令明确指定以下teamplateUrl

  • template/modal/backdrop.html(在modal.jshere
  • template/modal/window.html(在modal.jshere
  • template/alert/alert.html(在alert.jshere

像这样:

.directive('modalBackdrop', ['$timeout', function ($timeout) {
  return {
    restrict: 'EA',
    replace: true,
    templateUrl: 'template/modal/backdrop.html',
    link: function (scope, element, attrs) {
      /* ... */
    }
  };
}])

每次我调用 $modal.open() 并且 ui-bootstrap 为新的模态窗口构建 DOM 时,Angular 都会尝试通过 $http 服务解析这些 url,即使模板已经通过 $templateCache.put 方法或通过添加<script> 标签。 这基本上导致了我的拦截器中的无限递归,它试图在request 重载中为上面的 url 引入登录对话框。

这是我的拦截器的简化版本:

.config(['$provide', '$httpProvider', function($provide, $httpProvider) {
    $provide.factory('testInterceptor', ['$injector', function($injector) {
        return {
        'request': function(config) {

            var auth = $injector.get('authService');
            var modal = $injector.get('$modal');
            if (!auth.LoggedIn) {
              var loginModal = modal.open({
                  template: 'Login screen <alert type="warning">some message</alert>',
              });
              return loginModal.result;
            }
            return config;
          }
}}]);

工作演示是here

谁能建议不涉及对ui.bootstrap.modalui.bootstrap.alert 中使用的templateUrls 进行硬编码的方法?

我还在 github 上将此报告为 issue

【问题讨论】:

  • 你为什么使用 $injector 而不是仅仅将这些东西作为依赖项传递?即$injector.get('$modal')
  • 这可能不起作用,因为拦截器正在config 部分中注册,该部分仅支持提供者注入(请参阅documentation

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


【解决方案1】:

解决此问题的一种简单方法是不对以template/ 开头的任何 URL 的请求强制执行身份验证。像这样:

      $provide.factory('testIntercepter', ['$q', '$injector',
        function($q, $injector) {
          return {
            'request': function(config) {
              if (config.url.indexOf('template/') == 0) {
                log('ignoring ' + config.url);
                return config;
              }

              log(config.method + ' ' + config.url);
              var auth = $injector.get('authService');
              if (!auth.LoggedIn) {
                return auth.Login();
              }
              return config;
            },
          }
        }
      ]);

Plunker 示例: http://plnkr.co/edit/kADmHkfHiyKW8kd7aNep?p=preview


一个更复杂的选项可能是检查 $templateCache 是否包含请求的 URL,并在这些情况下跳过身份验证:

      $provide.factory('testIntercepter', ['$q', '$injector', '$templateCache',
        function($q, $injector, $templateCache) {
          return {
            'request': function(config) {
              if ($templateCache.get(config.url)) {
                log('in $templateCache ' + config.url);
                return config;
              }

              log(config.method + ' ' + config.url);
              var auth = $injector.get('authService');
              if (!auth.LoggedIn) {
                return auth.Login();
              }
              return config;
            },
          }
        }
      ]);

Plunker:http://plnkr.co/edit/RfkTmGinobxIWmg1BrMJ?p=preview

【讨论】:

  • 谢谢@sirhc,我会做这两项检查。关于$templateCache的好点!
【解决方案2】:

您不必使用templateUrl。检查此代码(也处理授权)。我使用内联模态模板。这是打开模态并允许在打开的模态对话框中路由的更大脚本的一部分,因此当您想在模态对话框中执行一系列操作时,不必关闭模态。

$modal.open({
     template: "<div data-ng-include='templateUrl'></div>",
     controller: function ($scope, $modalInstance) {

     $modalInstance.opened
         .then(function () {
             if (startRouteName != "unauthorized") {
                 var requiredAuthorizations = 
                        $scope.getRequiredPermissions(startRouteName);
                 if (requiredAuthorizations) {
                     $scope.hasAnyPermission(requiredAuthorizations)
                         .then(function (result) {
                             if (!result) {
                                 startRouteName = "unauthorized";
                             }
                             afterModalOpened($scope);
                     });
                 } else {
                     afterModalOpened($scope);
                 }
             } else {
                 afterModalOpened($scope);
             }
         });
     }
});

【讨论】:

  • 我还在我的example 中使用内联template 问题是angular-ui 本身正在使用templateUrl,这导致我的迭代器循环
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-07
相关资源
最近更新 更多