如何使用Angular挂钩点击链接,并在点击完成之前添加href?

时间:2014-04-11 22:00:44

标签: javascript ajax angularjs

背景:
当用户单击链接时,我必须从服务器获取URL。它不是事先可用的。链接上的点击应该正常,但是使用该获取的URL。

程序如下:

  • 该链接在点击之前包含href="#"
  • 点击链接
  • 我使用ng-mousedownng-click加入点击,然后使用$http请求从服务器获取网址。
  • 使用网址更新链接的href。
  • 原始点击应该完成(使用新的网址,而不是#占位符)。

问题出现在最后一步。由于$http请求是异步的,我怀疑存在时间问题。我的怀疑是:如果服务器请求足够快,它将通过,并在原始点击进行之前更改URL。如果没有,则原始点击进入并尝试转到#占位符URL。所以单击链接时不会发生任何事情。

我想让原始点击等待$http请求的结果与URL一起返回。原始点击很重要的原因是它可以是鼠标左键单击或鼠标中键(cmd +点击),我也不知道哪一个,所以很难自己调用它来自javascript。

那么,关于如何使用获取的URL进行原始点击的任何聪明的想法?

5 个答案:

答案 0 :(得分:10)

如果在检测到点击之前确实无法解析链接,那么最好使用ngClick指令调用可能在等待$ http时显示加载屏幕的函数承诺解决然后使用$location.path()实际启动路由更改。例如:

HTML

<button ng-click="changeRoute($event)">Click me</button>

代码

angular.module('myApp', [])
  .controller('pageCtrl', function($scope, $http, $location, $window) {
    $scope.changeRoute = function(event) {
      console.log('Fetching URL');

      // The popup must be created before the callback, because the callback 
      // is not considered user-initiated by the browser. Non-user-initiated
      // events always open in a new browser window (not a tab).
      if (event.which === 2 || (event.which ===1 && (event.metaKey || event.ctrlKey))) {
        // MIDDLE CLICK or CMD+LEFTCLICK - new tab
        var popup = $window.open("about:blank", "_blank"); 
        // the about:blank is to please Chrome, and _blank to please Firefox
      }

      $http.get('/some/path')
        .success(function(data){
          //check that it's a good URL, then route to it
          //$location.path(data);
          if (event.which === 1 && !event.metaKey && !event.ctrlKey) {
            // LEFTCLICK - same window
            $window.location.href = data;
          } else if (event.which === 2 || (event.which ===1 && (event.metaKey || event.ctrlKey))) {
            // MIDDLE CLICK or CMD+LEFTCLICK - new tab
            popup.location = data;
          }
        })
        .error(function(data, status, headers, config) {
          console.error('Failed to get URL: ' + status);
        });
      console.log('Fetch request sent, awaiting response...');
    };
  });

修改

更新以支持外部链接,中间点击现在将在新窗口中打开

更新为支持:

  • CMD +单击并按CTRL +单击以作为鼠标中键单击。
  • 放入新标签页,而不是新窗口。

答案 1 :(得分:1)

您应首先event.preventDefault()$http留出时间来完成其过程。要在Angular中执行此操作,您应该将$event传递给ng-click处理程序。

示例HTML:

<body ng-controller="appController">
    <a href="#" ng-click="navigate($event)">LINK</a>
</body>

应用:

var app = angular.module('app', []);
app.controller('appController',
    function ($scope, $http, $window, $log) {
        // generic function for window navigation
        function nav(url, newTab) {
            if (newTab) {
                $window.open(url, '_blank');
            } else {
                $window.location.href = url;
            }
        }
        // handler for ng-click directive
        $scope.navigate = function (event) {
            // This is the key -> preventing default navigation
            event.preventDefault();
            // determine whether to open a new page or not
            var newTab = ((event.which === 1 && (event.metaKey || event.ctrlKey)) || event.which === 2);
            // get the URL from a file
            $http.get('links.json')
                .success(function (data, status, headers, config) {
                    // navigate when URL is fetched
                    nav(data.someLink, newTab);
                })
                .error(function (data, status, headers, config) {
                    $log.debug('Error:', data, status);
                });

        };
    });

查看公开的$event对象here的示例。

答案 2 :(得分:0)

我假设您知道如何使用有角度的$ http进行回调,并且您可能已经尝试将该链接添加为回调。所以我有另一种选择。

<强>替代:
如果你不挑剔。您可能只想模拟用户单击具有以下功能的链接所执行的操作。 (更多关于此here。)

window.location.href = "http://stackoverflow.com";

我不熟悉AJAX和Angular,但我正在学习它们。我会尝试将它放在$ http回调中。它看起来像这样。

$http.get("my/api/getUrl").success(function (data) { 
  window.location.href = data.url;
});

答案 3 :(得分:0)

在Angular

中有两种方法可以做到这一点

使用......

##

<a ng-href="{{linkModel}}" href target="_blank" ng-click="linkModel='http://google.com'">Link1 to Google</a>

##

直接或通过调用控制器中的函数来触发值。

-

参见示例......

示例:http://jsfiddle.net/dsmithco/e94SH/

答案 4 :(得分:0)

这实际上会拦截链接上的点击,并在点击进入之前更改位置。

这是因为使用ng-mousedown代替ng-click,并使用空href标记和ng-href。请注意,如果href标记的值与您通常的值相同(即href="#"href="javascript:"),则无效。您也无法完全删除href标记,只能使用ng-href标记,因为浏览器需要href标记将该锚点识别为可点击链接。

HTML:

<a href ng-href="{{linkModel}}" ng-mousedown="changeRoute($event)">Link1 to Google</a>

Angular Code:

angular.module('myApp', [])
  .controller('pageCtrl', function($scope, $http, $location, $window) {
    $scope.changeRoute = function(event) {
      console.log('Fetching URL');
      $http.get('/some/path')
        .success(function(data){
          linkModel = data; // or data.url if it is stored as a url on the data object
        })
        .error(function(data, status, headers, config) {
          console.error('Failed to get URL: ' + status);
        });
      console.log('Fetch request sent, awaiting response...');
    };
  });

的优点:

  • 会捕捉左键和鼠标中键(以及cmd +点击或ctrl +点击),大概是所有浏览器。
  • 无需单击链接两次(如果使用ng-click与现有的href,则必须单击两次。第一次单击只会在链接上设置新的href,浏览器也会尝试访问旧的/现有的href)。

缺点:

  • 将不会捕获右键单击上下文菜单&#34;在新标签中打开链接&#34;,这是javascript无法实现的,因为正常的上下文菜单属于浏览器(除非您想完全使用自己的权限覆盖上下文菜单点击事件或上下文菜单)。