0

In an AngularJS application I have the following code:

<a target="_blank" ng-href="{{someProperty.href}}" ng-click="someMethod($event)">Hello!</a>

Now, someMethod() and someProperty belong to the same service.

Initially, someProperty.href has a default value.

What I need to do is that when the user clicks on the link, some calculation is performed and someProperty.href gets a new value. This new value need to be reflected in the ng-href and the user should be redirected to that new href.

7
  • Why not have this logic inside someMethod(). Calculate the new URL and then redirect using $window.location = new href Commented May 25, 2017 at 9:14
  • I don't know if this is a good practice to perform redirects from within a service. Also, I need to open that link in a new tab. Commented May 25, 2017 at 9:15
  • If you update the href property in someProperty object then isn't it updating the href? Commented May 25, 2017 at 9:16
  • @Cosmin Where is someMethod() located? Commented May 25, 2017 at 9:17
  • @ManasHemrajani, it does update the href. But the user is redirected to the previous URL. Commented May 25, 2017 at 9:18

4 Answers 4

1

tried reconstructing it and it seems to work, clicking on the link opens a new tab with the new url.

https://plnkr.co/edit/gy4eIKn02uF0S8dLGNx2?p=preview

<a target="_blank" ng-href="{{someService.someProperty.href}}" ng-click="someService.someMethod()">
    Hello!
    <br/>
    {{someService.someProperty.href}}
</a>
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you, Stav. But I think I know where the problem is. In someMethod() I have an async request so it takes a little time to solve, but until then the click event has been propagated already and the user is redirected to the old url.
1

You can do it as like the below code

;(function(angular) {
    angular.module('myApp.directives')
        .directive('myExample', myExample);

    myExample.$inject = ['$timeout'];

    function myExample($timeout) {
        return {
            restrict: 'A',
            scope: {
                myExample: '&',
                ngHref: '='
            },
            link: function(scope, element, attrs) {
                element.on('click', function(event) {
                    event.preventDefault();
                    $timeout(function() {
                        scope.myExample();
                        scope.$apply();
                        var target = attrs.target || '_blank';
                        var url = scope.ngHref;
                        angular.element('<a href="' + url + '" target="' + target + '"></a>')[0].click();
                    });
                });
            }
        };
    }
})(angular);

In Controller

;(function(angular) {
    'use strict';

    angular.module('myApp.controllers').controller('HomeController', HomeController);

    HomeController.$inject = ['$scope'];

    function HomeController($scope) {
        $scope.url = 'http://yahoo.com';
        $scope.someFunction = function() {
            $scope.url = 'http://google.com';
        };
    }
})(angular);

In HTML You can use like

<div ng-controller="HomeController">
    <a ng-href="url" my-example="someFunction()" target="_blank">Click me to redirect</a>
</div>

Here instead of ng-click I have used custom directive which simulates the ng-click but not as exactly as ng-click

If the parent scope function is async you change your directive and someFunction in controller as like below

@Directive

;(function(angular) {
    angular.module('myApp.directives')
        .directive('myExample', myExample);

    myExample.$inject = ['$timeout'];

    function myExample($timeout) {
        return {
            restrict: 'A',
            scope: {
                myExample: '&',
                ngHref: '='
            },
            link: function(scope, element, attrs) {
                element.on('click', function(event) {
                    event.preventDefault();

                    scope.myExample().then(function() {
                        $timeout(function() {
                            scope.$apply();
                            var target = attrs.target || '_blank';
                            var url = scope.ngHref;
                            angular.element('<a href="' + url + '" target="' + target + '"></a>')[0].click();
                        });
                    });
                });
            }
        };
    }
})(angular);

@Controller

;(function(angular) {
    'use strict';

    angular.module('myApp.controllers').controller('HomeController', HomeController);

    HomeController.$inject = ['$scope', '$q'];

    function HomeController($scope, $q) {
        $scope.url = 'http://yahoo.com';
        $scope.someFunction = function() {
            var deferred = $q.defer();
            $scope.url = 'http://google.com';

            deferred.resolve('');
            return deferred.promise;
        };
    }
})(angular);

Here I just simulated the async, it may be your http call too

1 Comment

If your some method is async you can return the promise and in turn our myExample will return promise, then we can use like myExample.then(function() { scope.$apply(); }, function() {});
0

make sure the value in href tag is updated after you click on it. Try debugging the ng-click function. According to the official documentation:

Using AngularJS markup like {{hash}} in an href attribute will make the link go to the wrong URL if the user clicks it before AngularJS has a chance to replace the {{hash}} markup with its value. Until AngularJS replaces the markup the link will be broken and will most likely return a 404 error. The ngHref directive solves this problem.

In your case, i think the old link is not getting updated with the new values of the model. Hence, redirecting to old link.

Comments

0

Try calling a function on ui-sref or ng-href which will return the state name that you want to redirect. Something like this

html:

<a  ui-href="{{GetUpdatedHref()}}" >Hello!</a>

controller.js

 $scope.GetUpdatedHref = function(){
    //perform your http call while it's being processed show a loader then finally return the desired state (page location)
return "main.home"
}

If this doesn't work for you use ng-click instead of ui-sref and then $state.go("main.home") inside function.

Hope this may resolve your problem.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.