How can I use Angular to connect to a link and add href until the click is complete?

Context:
I need to get the url from the server when the user clicks on the link. It is not available in advance. Clicking the link should work as usual, but with the specified URL.

The procedure is as follows:

  • Link contains href="#" before clicking it
  • Click the link
  • I connect to the click using ng-mousedown or ng-click and select the URL from the server using the $http request.
  • The href link is updated with the url.
  • The original click should complete (with this new URL, not with the # tag).

The problem arises in the last step. Since the $http request is asynchronous, I suspect there is a synchronization problem. My suspicion: if the server request is fast enough, it will go through and the URL will be changed before the initial click is made. If not, then the original click passes and tries to go to the URL #. Therefore, when you click the link, nothing will happen.

I want to make an original click, expecting that the result of the $http request will return with the url. The reason the original click is important is that it can be either left or middle click (see + Click), and I don’t know which one, so it would be hard to call it myself from javascript.

So, any clever ideas on how to make the original click pass through using the selected URL?

+6
source share
5 answers

If you really cannot resolve the link before the click is detected, you would be better off using the ngClick directive to call a function that can display a loading screen waiting for your $ http promise to resolve, then use $ location.path () to actually trigger change of route. For instance:

HTML

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

And code

 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 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...'); }; }); 

Edit

Updated to support external links and middle click now opens in a new window

Updated to support:

  • CMD + click and CTRL + click to function as a middle mouse click.
  • Entering a new tab instead of a new window.
+10
source

First you have to do event.preventDefault() to complete the time for $http to complete the process. To do this in Angular, you must pass $event the ng-click handler.

HTML example:

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

applications:

 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); }); }; }); 

See an example of an open $event object here .

+1
source

I assume you know how to use the callback with angular $ http and you probably already tried to add the link as a callback. Therefore, I have an alternative.

Alternative:
If you're not picky. You can simply simulate the action performed by the user by clicking on the link with the following function. (more on this here .)

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

I am not familiar with AJAX and Angular, but I am learning them. I will try to put this in the $ http callback for you. It will look something like this.

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

There are two ways to do this simply in Angular

Use...

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

to call a value directly or by calling a function from your controller.

-

See an example ...

EXAMPLE: http://jsfiddle.net/dsmithco/e94SH/

0
source

This will actually intercept a click on the link and change the location until it clicks.

This is due to using ng-mousedown instead of ng-click and using an empty href tag along with ng-href . Please note that this will not work if the href tag has a value as usual (ie href="#" or href="javascript:" ). You also cannot completely remove the href tag and only have the ng-href tag, because the browser needs the href tag to recognize the anchor as a clickable link.

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...'); }; }); 

pros:

  • will catch the left click and middle mouse click (and cmd + click or ctrl + click), presumably from all browsers.
  • No need to double-click the link (if you use ng-click with an existing href, you will have to double-click. The first click will just install the new href in the link, and the browser will also try to access the old / existing href).

minuses:

  • it will not intercept the rightclick "open link in a new tab" context menu, which is impossible with javascript, since the normal context menu belongs to the browser (if you do not want to completely override the context menu using your own context menu or context menu).
0
source

All Articles