Cosmin
Cosmin

Reputation: 954

Update href in AngularJS before navigating to the URL

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.

Upvotes: 0

Views: 2986

Answers (4)

DevSab
DevSab

Reputation: 143

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.

Upvotes: 0

Kanagu
Kanagu

Reputation: 606

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

Upvotes: 1

Stav
Stav

Reputation: 46

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>

Upvotes: 1

Manas
Manas

Reputation: 838

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.

Upvotes: 0

Related Questions