43

I am trying to set the value of a $scope property using ng-init, and I am unable to access that value in the controller's javascript. What am I doing wrong? Here is a fiddle: http://jsfiddle.net/uce3H/

markup:

<body ng-app>
    <div ng-controller="testController" >
        <input type="hidden" id="testInput" ng-model="testInput" ng-init="testInput='value'" />
    </div>
    {{ testInput }}
</body>

javascript:

var testController = function ($scope) {
     console.log($scope.testInput);
}

In the javascrippt, $scope.testInput is undefined. Shouldn't be 'value'?

Rishabh
  • 3,752
  • 4
  • 47
  • 74
TimH
  • 1,012
  • 1
  • 14
  • 24
  • all the answers are wrong about why this doesn't work. your code is fine, you are just binding to `testInput` outside of its scope, which is limited to the div above it. move `{{ testInput }}` up into the div, or move `ng-controller="testController"` up into the body tag. – omikes Mar 27 '18 at 23:27

6 Answers6

46

You are trying to read the set value before Angular is done assigning.

Demo:

var testController = function ($scope, $timeout) {
    console.log('test');
    $timeout(function(){
        console.log($scope.testInput);
    },1000);
}

Ideally you should use $watch as suggested by @Beterraba to get rid of the timer:

var testController = function ($scope) {
    console.log('test');
    $scope.$watch("testInput", function(){
        console.log($scope.testInput);
    });
}
AlwaysALearner
  • 43,759
  • 9
  • 96
  • 78
  • 8
    You problably will want to use `$scope.$watch` in this case. – Beterraba Nov 14 '13 at 15:33
  • 1
    You could also use a `$watch` but keep in mind that the controller will run multiple times so whether you use a timeout or watch, it could run many times. – Manny D Nov 14 '13 at 15:46
  • 1
    Thank you for this. Somewhat surprising that angular allows this kind of race to happen in the first place, but I suppose it's hard to guard against! – TimH Nov 14 '13 at 16:59
39

Just set ng-init as a function. You should not have to use watch.

<body ng-controller="MainCtrl" ng-init="init()">
  <div ng-init="init('Blah')">{{ testInput }}</div>
</body>

app.controller('MainCtrl', ['$scope', function ($scope) {
  $scope.testInput = null;
  $scope.init = function(value) {
    $scope.testInput= value;
  }
}]);

Here's an example.

Plunker

Rob
  • 2,721
  • 1
  • 20
  • 27
4

HTML:

<body ng-app="App">
    <div ng-controller="testController" >
        <input type="hidden" id="testInput" ng-model="testInput" ng-init="testInput=123" />
    </div>
    {{ testInput }}
</body>

JS:

angular.module('App', []);

testController = function ($scope) {
    console.log('test');
    $scope.$watch('testInput', testShow, true);
    function testShow() {
      console.log($scope.testInput);
    }
}

Fiddle

lukpaw
  • 1,603
  • 2
  • 26
  • 31
1

Like CodeHater said you are accessing the variable before it is set.

To fix this move the ng-init directive to the first div.

<body ng-app>
    <div ng-controller="testController" ng-init="testInput='value'">
        <input type="hidden" id="testInput" ng-model="testInput" />
       {{ testInput }}
    </div>
</body>

That should work!

monzonj
  • 3,659
  • 2
  • 32
  • 27
eXaminator
  • 353
  • 1
  • 8
  • 2
    Your {{ testInput }} is outside the scope of the controller and will most likely still be null :/ consider moving it up into the div – O'Mutt Aug 29 '14 at 14:37
  • Yep, @Mutmatt it's a typo. I coded it directly here without much tought. Sorry – monzonj Mar 28 '16 at 12:45
  • i am honored to be the first to upvote the first actual answer to this question. – omikes Mar 27 '18 at 23:21
1

Try this Code

var app = angular.module('myapp', []);
  app.controller('testController', function ($scope, $http) {
       $scope.init = function(){           
       alert($scope.testInput);
   };});

<body ng-app="myapp">
      <div ng-controller='testController' data-ng-init="testInput='value'; init();" class="col-sm-9 col-lg-9" >
      </div>
</body>
zeeshan Qurban
  • 387
  • 1
  • 3
  • 15
-1

I had some trouble with $scope.$watch but after a lot of testing I found out that my data-ng-model="User.UserName" was badly named and after I changed it to data-ng-model="UserName" everything worked fine. I expect it to be the . in the name causing the issue.

Manfred Radlwimmer
  • 13,257
  • 13
  • 53
  • 62
ewil
  • 1
  • 1