Calling angularjs scope function from href

42,654

Solution 1

That's a bit convoluted.

CAVEAT: This is very, very hacky and just absolutely exactly what you're NOT supposed to do in angular, but I guess you know that and the library is making your life hard...

First, unlike onclick, an href won't interpret a string as javascript. Instead, you'd have to use

<a href="javascript:someFunction()"></a>

But this alone won't make it work, because someFunction() is not a method on the document, but on the controller, so we need to get the controller first:

<a href="javascript:angular.element(
         document.getElementById('myController')).scope().someFunction();"></a>

Where myController refers to the DOM element that is decorated with ng-controller, e.g.

<div data-ng-controller="SomeController" id="myController"> ... </div>

If someFunction modifies the state of the view, you'll also need to use $scope.apply, i.e.

<a href="javascript:angular.element(document.getElementById('myController')).
           scope().$apply(someFunction)"></a>

Note that you don't need the {{ }} syntax, because you're calling javascript directly, you're not asking angular to modify your markup.

Solution 2

So I was not pleased with the answer to this as it doesn't really utilize an elegant angular solution.

Here's my solution: http://jsfiddle.net/jjosef/XwZ93

HTML:

<body class="wrapper" ng-app="ExampleApp">
  <a my-href="buildUrl('one', aVariable, 'three')">This is my a tag with a function that builds the url</a>
</body>

JS:

angular.module('ExampleApp', []);
angular.module('ExampleApp').run(function($rootScope) {
  $rootScope.buildUrl = function() {
    var link = [];
    for(var i = 0; i < arguments.length; i++) {
      link.push(arguments[i].toLowerCase());
    }
    return '/#!/' + link.join('/');
  };

  $rootScope.aVariable = 'two';
});

angular.module('ExampleApp').directive('myHref', function($parse) {
  return {
    restrict: 'A',
    link: function(scope, element, attrs) {
      var url = $parse(attrs.myHref)(scope);
      element.attr('href', url);
    }
  }
});

Solution 3

You should probably use ng-click here.

Solution 4

The simplest solution is

<a href="" ng-click="someFunction(x,y,z)">Go</a>

href="" is important, otherwise hover cursor style does not change to a pointer

Solution 5

I mixed some things here and I have it working.

I have a menu with some options, each one calls a different method on the controller.

<span ng-show="hoverOptions" ng-mouseleave="hoverOut()" class="qk-select ui-select-container qk-select--div">
    <ul>
        <li ng-repeat="option in menuOptions"><a href="javascript:void(0);" ng-click="callFunction(option.action)">{{option.name}}</a></li>
    </ul>
</span>

The callFunction method in the controller is defined like that:

$scope.callFunction = function (name){
      if(angular.isFunction($scope[name]))
                $scope[name]();
}

And the menu options are defined also in the controller in that way:

$scope.menuOptions = [{action: "uploadPhoto" , name:"Cargar foto"}, {action: "logout", name:"Cerrar sesión"}, {action: "createUser", name:"Nuevo usuario"}];

Hope it helps someone.

Share:
42,654
user1200387
Author by

user1200387

Updated on July 30, 2022

Comments

  • user1200387
    user1200387 almost 2 years

    I am using a library which appends a href element onto an tag. On this link I need to make a call to an angularjs function that is within scope. Something like...

    <a href="{{someFunction()}}"></a>
    

    Note: I am attaching this href via javascript from another library (nvd3.js) not actually writing this in because if I was I could easily use ng-click or ng-href.

  • user1200387
    user1200387 over 10 years
    The most beautiful hack I have seen. Works like a charm!
  • user1200387
    user1200387 over 10 years
    I thought it was working but jumped the gun: This is definitely the right track. Here is what I tried:angular.element('directive-name').scope().loadUsers(1)‌​; And the error said angular.element(...).scope(...).loadUsers is not a function. When I type angular.element('directive-name') it returns the proper object with the scope() function on it.
  • user1200387
    user1200387 over 10 years
    Ok figured out I have to be on the $$childHead object first like so... angular.element("directive-name").scope().$$childHead and it works!
  • Dvid Silva
    Dvid Silva almost 10 years
    this should be the top answer :/
  • thetallweeks
    thetallweeks over 9 years
    You could you also use scope.$eval instead of $parse to avoid the need for dependency injection. See modified jsfiddle.
  • th1rdey3
    th1rdey3 over 8 years
    this code will not work if minified. see modified jsfiddle which will work with minification.
  • Alberto La Rocca
    Alberto La Rocca over 8 years
    The problem with ng-click is it would only detect clicks and not when the user navigates to the element with the Tab key and then press Space. In other words, the click event is not semantic.
  • Alberto La Rocca
    Alberto La Rocca over 8 years
    See my comment above, ng-click handles the click DOM event, which is not semantic: it detects clicks but it doesn't detect when the user navigates to the element with the Tab key and then presses Space.