背景:
当用户单击链接时,我必须从服务器获取URL。它不是事先可用的。链接上的点击应该正常,但是使用该获取的URL。
程序如下:
href="#"
ng-mousedown
或ng-click
加入点击,然后使用$http
请求从服务器获取网址。#
占位符)。问题出现在最后一步。由于$http
请求是异步的,我怀疑存在时间问题。我的怀疑是:如果服务器请求足够快,它将通过,并在原始点击进行之前更改URL。如果没有,则原始点击进入并尝试转到#占位符URL。所以单击链接时不会发生任何事情。
我想让原始点击等待$http
请求的结果与URL一起返回。原始点击很重要的原因是它可以是鼠标左键单击或鼠标中键(cmd +点击),我也不知道哪一个,所以很难自己调用它来自javascript。
那么,关于如何使用获取的URL进行原始点击的任何聪明的想法?
答案 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...');
};
});
更新以支持外部链接,中间点击现在将在新窗口中打开
更新为支持:
答案 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>
##
直接或通过调用控制器中的函数来触发值。
-
参见示例......
答案 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...');
};
});
的优点:
缺点: