1

I have a directive which looks something like this

 <a href ng-click="metric='Distance'; metricshow=false;" >
 <a href ng-click="metric='Time'; metricshow=false;">

Now In my controller.

console.log($scope.metric);
    switch($scope.metric)
    {
        case 'Distance' : console.log('Distance');
        break;
        case 'Time' : console.log('Time');
        break;
    }

The console.log() gives me undefined. Why?

5
  • When is that console.log invoked? How are you declaring your controllers and their use at HTML? Could you please put {{metric}} right behind the anchor tags Commented Nov 5, 2015 at 22:24
  • I am getting values at {{metric}}. But not using $scope is what is causing the issue I believe Commented Nov 5, 2015 at 22:33
  • Again, please tell me where is that console.log placed Commented Nov 5, 2015 at 22:34
  • At the start of the controller. And I get it, the first time the program runs through it. $scope. Metric is undefined. Could you tell me one thing like what is run first. The html or the controller. Or both are executed as they are encountered Commented Nov 5, 2015 at 22:37
  • Ive offered you an answer, telling some extra details Commented Nov 5, 2015 at 22:54

4 Answers 4

2

You have not assigned anything to the $scope.metric when the controller is created therefore it console logs undefined.

Now, if you had something like:

<a href ng-click="doSomething()" >

in your HTML and something like:

$scope.doSomething = function() {
    $scope.metric='Distance'; 
    $scope.metricshow=false;
    console.log($scope.metric);
}

in your controller, you would be responding to the ng-click.

Sign up to request clarification or add additional context in comments.

Comments

2

So, right as other answers tell, it's because that console.log is being executed right away.

I'd like to tell a few extra points:

  1. It's better to use functions with ng-click instead of inline js code.
  2. At HTML you can use {{variable}} for $scope interpolation.
  3. There are $watch functions available.

$scope interpolation

So $scope is a glue between you controller and your JS code at controllers. You don't need to place {{$scope.variable}} because $scope becomes the global variable at markup.

This works great for app logic, useful when using ng-repeat, for example or just for fast debugging.

$watch functions

You could have, at your controller:

$scope.$watch('metric', function(newValue, oldValue){
  console.log("$scope.metric just changed from " + oldValue + " to " + newValue);
});

This is really useful for more sofisticated app logic, workflow and control. But you shouldn't do it for debugging.


About your question at last comment on what's being executed first, please check the docs on data binding and digest cycle.

1 Comment

$watch was something I missed completely. Great addition to the post.
1

When your controller first run, the $scope.metric variable was not created nor assigned to anything. You may also prefer not to use logic in your view, use functions instead.

Directive:

 <a href ng-click="setMetric('Distance')" >
 <a href ng-click="setMetric('Time')">

 <a href ng-click="getMetric()">

Now In your controller:

$scope.setMetric = function (type) {
  $scope.metric = type;
}

$scope.getMetric = function () {
  console.log($scope.metric);
}

Working Plunker with some additions

4 Comments

Woah... This has the same approach as above and gives a much cleaner way to do it. +1 right away
Wow, thanks. I've discovered plnkr.co/ yesterday. I will make one for you. :)
Well that would be great. It was tough call between fridjon and you. For the answer. You earned it.
Here is it: Working Plunker. I won't touch the answer, btw, the Plunker is a little more difficult to understand.
1

Late to the party, but according to your original code, I have created the similar situation.

 <a href ng-click="metric('Distance')" >
 <a href ng-click="metric('Time');">



 <script>
    $scope.metric = function(_parm){
        switch(_parm){
            case 'Distance': 
                console.log('Distance');
                $scope.metricshow = false;
                break;
            case 'Time' :
                console.log('Time');
                $scope.metricshow = false;
                break;
        }
    }
 </script>

For your reference, use ng-click to call function, THEN change the variables there. More readable, prettier on HTML side!

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.