AngularJS中$window.open弹窗被阻止

6

我正在尝试在AngularJS应用程序中使用Github API的网页授权流程。当我的注册表单提交时,我想打开一个新窗口将他们发送到授权页面。通常,我会在用户事件中使用window.open以确保它不会被弹出拦截器捕获。

在我的Angular应用程序中,我正在将一部分Github API封装在Angular服务中,并将打开窗口的代码放在那里。因此,它被阻止了。我还尝试将其放在控制器中的一个函数中,该函数通过ng-submit由表单调用。

所以问题是,是否有一种优雅的方式从我的服务或控制器内的某个位置打开新页面,或者我需要找到另一种方法来实现它?

3个回答

28

Chrome默认会阻止不是用户直接操作产生的弹出窗口。在您的情况下,我猜测调用window.open的操作是在回调函数中进行的。这使得它成为异步操作,而Chrome会对其进行阻止。

//before
$scope.userClicked = function(){
  $http.post('your/api/endpoint',{data:x}).then(function(r){
    $window.open(r.data.url,'window name','width=800,height=600,menubar=0,toolbar=0');
  });
}

不过,有一个解决方法可以让它工作。在回调函数之外实例化您的窗口,并且您可以在回调函数中引用该变量来更改该窗口的目标URL。

//after
$scope.userClicked = function(){
  var popup = $window.open('','window name','width=800,height=600,menubar=0,toolbar=0');
  popup.document.write('loading ...');

  $http.post('your/api/endpoint',{data:x}).then(function(r){
    popup.location.href = r.data.url;
  });
}

1
这应该是一个被接受的答案。非常感谢。 - Esen

5

对于由脚本自动触发的 window.open 弹出窗口,您无法摆脱弹出窗口拦截器。只有真实用户的操作事件才能打开新窗口而不被弹出窗口拦截器屏蔽。想象一下,在没有浏览器弹出窗口拦截器的站点中,JavaScript 在循环中打开 100 个弹出窗口的情况。你喜欢吗?在我们过去的好时光里,这就像一种病毒,但现代浏览器要聪明得多,这种烦恼被优雅地处理了。


嗯,这正是我所想的。我得想出其他办法。 - giodamelio

2
您可以很简单地从click事件内容中创建一个指令来实现这一点:
yourapp.directive('awesomeClick', ['$parse',function ($parse): ng.IDirective {
    return {
        restrict: 'A',        
        link: (scope, element:JQuery, attrs) => {
            var fn = $parse(attrs.awesomeClick);
            element.on('click', function (event) {

                // open the window if you want here 

                scope.$apply(function () {
                    fn(scope, { $event: event });
                });
            });
        }
    }
}]);

1
这个代码可以在按钮点击时运行,但我想在表单提交时运行。 - giodamelio

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接