0

I'm creating a calculator app in AngularJS, but am having trouble with ng-repeat and ng-click.

<div class="col-md-3">
  <button ng-repeat="op in operations" name="btn{{ op.name }}"
          value="{{ op.symbol }}" class="operationbutton" 
          ng-click="{{ op.function }}"> {{ op.symbol }}
  </button>
</div>

In my app.js, inside my controller, I have an operations variable tied to $scope.

$scope.operations = [
    { "symbol": "+", "name": "add", "function": "add()" },
    { "symbol": "-", "name": "subtract", "function": "subtract()" },
    { "symbol": "*", "name": "multiply", "function": "multiply()" },
    { "symbol": "/", "name": "divide", "function": "divide()" }
];

I've tried taking the quotation marks off the function names, but it turns out that JavaScript object values must contain strings.

I could do something like this

ng-click="{{ op.name === 'add' ? add() : op.name === 'subtract' ? subtract()
: op.name === 'multiply' ? multiply() : op.name === 'divide' ? divide() : multiply()}}"

But that seems like a terrible practice. Is there any way I can improve this, so I can call a function based on the operation?

2
  • 1
    Can you not assign the actual function to op.function rather some string expression? Commented Sep 17, 2015 at 18:11
  • Create single function with switch statement for each symbol, assign that function to ng-click (without any symbol). Finally to make it work you'd have to create another variable called op_symbol, or something like that and use it in your method. Plus I'd recommend reading about bindToController/controllerAs syntax. That drops using $scope in controller because you are able to assign vars, functions to this of controller's function - a lot easier to test such controller. Commented Sep 17, 2015 at 18:13

3 Answers 3

4

The best approach is to assign the actual function, rather than a string expression of function invocation, to each op:

function add(){
  // whatever you do now
}

// same for other functions
function subtract(){}
function multiply(){}
function divide(){}

$scope.operations = [
    { "symbol": "+", "name": "add", "function": add },
    { "symbol": "-", "name": "subtract", "function": subtract },
    { "symbol": "*", "name": "multiply", "function": multiply },
    { "symbol": "/", "name": "divide", "function": divide }
];

And ng-click becomes:

<button ng-repeat="op in operations"  
        ng-click="op.function()"> 
  {{ op.symbol }}
</button>
Sign up to request clarification or add additional context in comments.

1 Comment

Beat me to the answer by 1 second lol. Here's a demo, though. jsbin.com/fiveduxeye/2/edit?html,js,output
1

You could possibly reorganize your code this way. You controller you would define your functions add to the $scope object.

var add = function() {
 //code here
 }    

var subtract = function() {
 //coder her
 }     
$scope.operations= [
    { "name" : "add", "func" : add},
    { "name" : "subtract", "func" : subtract},
    ]

In the html you would do this reference them this way

  <div class="col-md-3">
  <button ng-repeat="op in operations" ng-click="op.func()"> {{ op.symbol }}
  </button>
  </div>

3 Comments

To nitpick, there is no need to set the functions themselves on the $scope
Thanks! I had tried the scope thing, but forgot to invoke the functions in ng-click. I had op.function instead of op.function()
@NewDev you are right. I just typed it up real quick. Thanks for the correction.
0
$scope.operations = [
    { "symbol": "+", "name": "add"},
    { "symbol": "-", "name": "subtract"},
    { "symbol": "*", "name": "multiply"},
    { "symbol": "/", "name": "divide"}
];

<div class="col-md-3">
  <button ng-repeat="op in operations" name="btn{{ op.name }}"
          value="{{ op.symbol }}" class="operationbutton" 
          ng-click="op.Operationfunction(op.name)"> {{ op.symbol }}
  </button>
</div>

$scope.Operationfunction = function(operation){
switch(operation)
 case 'add':
  add();
  break;
 case 'multiply':
  multiply();
  break;
....
};

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.