Sign up ×
Stack Overflow is a community of 4.7 million programmers, just like you, helping each other. Join them; it only takes a minute:

I would like to assign different functions to ng-click within ng-repeat:

<button ng-repeat="button in notification.buttons" ng-click="button.fn"> {{button.label}} </button>

Controllers:

app.controller('MainCtrl', ['$scope', function($scope){
    $scope.notification = {
        ctrl: 'logout', 
        text: 'Logout?',
        buttons: [
                {label:'Yes', fn: 'logout()'},
                {label:'No', fn: 'cancel()'},
        ],
    };
}]);

app.controller('logout', ['$scope', function($scope){
    $scope.logout = function(){
        alert('logout');
    };
    $scope.cancel = function(){
        alert('cancel');
    };
}]);

If I put button.fn in double curlies ng-click="{{button.fn}}" the generated html looks good in the Chrome inspector, but Angular throws the following error:

Error: [$parse:syntax] Syntax Error: Token 'button.fn' is unexpected, expecting [:] at column 3 of the expression [{{button.fn}}] starting at [button.fn}}].

If there are no double curlies, no error, but Angular generates the html like this and the functions won't fire:

 <button ng-repeat="button in notification.buttons" ng-click="button.fn" class="ng-binding ng-scope"> Yes logout()</button>

PLUNKER

I have a related question about setting ng-controller with scope variables with this very same example here.

share|improve this question
    
ng-click is expecting a function (IE button.fn()) not a pointer which is what you are getting. That's why it won't fire. The only option I have seen involves creating a directive. See This. – dannypaz Oct 16 '14 at 17:20

1 Answer 1

up vote 3 down vote accepted

http://plnkr.co/edit/QE50kpfBjXy2WPvjVsJc?p=preview

I've created a fork of your code. Your 'fn' reference were strings. I changed them to functions, and added '()' to the 'button.fn' in the template. I also changed where the function references were made since the definitions of the functions were in a different controller.

var app = angular.module('plunker', []);

app.controller('MainCtrl', ['$scope', function($scope){
    $scope.notification = {
        ctrl: 'logout', 
        text: 'Logout?',
        buttons: [
    			{label:'Yes', fn: null},
    			{label:'No', fn: null},
        ],
    };
}]);

app.directive('notification', [
	function() {
		return {
		restrict: 'E', // E = Element, A = Attribute, C = Class, M = coMment
		templateUrl: 'notification.tpl.html',
		replace: true,
		link: function(scope, element, attrs) {
      //...
		}
	};
		
		
}])

app.controller('logout', ['$scope', function($scope){
  $scope.logout = function(){
      alert('logout');
  };
  $scope.cancel = function(){
      alert('cancel');
  };
  
  $scope.notification.buttons[0].fn = $scope.logout;
  $scope.notification.buttons[1].fn = $scope.cancel;
}]);
<div ng-controller="logout">
    <p>{{notification.text}}</p>
    <button ng-repeat="button in notification.buttons" ng-click="button.fn()"> {{button.label}} {{button.fn}}</button>
    <button ng-click="logout()"> Test</button>
</div>

share|improve this answer
    
Umm.. I see that you moved the functions into the main controller. Actually this is only half of the solution, because I would like to call the functions from the inner (logout) controller... – TheRebel Oct 16 '14 at 17:47
    
Can you update your answer to call the functions in the original controller? – TheRebel Oct 16 '14 at 17:53
    
The references in MainCtrl controller to logout() and cancel() are defined in the logout controller. That's a problem. MainCtrl will never know about what is defined deeper into the hierarchy. I will have to let the login controller set the function references in the buttons array to make that work. Here's a new plunkr. plnkr.co/edit/QE50kpfBjXy2WPvjVsJc?p=preview – Rick Oct 16 '14 at 19:22
1  
Yes, I've been digging deeper in parent and child scope hierarchy. This is a really interesting way of solving it, thank you for sharing! – TheRebel Oct 16 '14 at 19:58

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.