Search code examples
javascriptangularjsif-statementangularjs-scopeangularjs-watch

AngularJS $watch not working in if-block


I figured out, that my angular script is working:

$scope.CurrentUser = null;
$scope.DatePicker = new Date();
$scope.$watch('DatePicker', function (newValue, oldValue) {
    if (newValue > new Date())
        $scope.DatePicker = new Date();
}, true);
<div>
    <input data-ng-model="DatePicker" type="date" id="datepicker" />
</div>

but not if I add an if-statment:

<div data-ng-if="!CurrentUser">
    <input data-ng-model="DatePicker" type="date" id="datepicker" />
</div>

Try it: http://codepen.io/anon/pen/jWBEVM

But I don't understand why. Is there a known issue? Can anybody help?


Solution

  • from doc

    This directive creates new scope.

    so, in your case

    <div data-ng-if="!CurrentUser">
        <input data-ng-model="DatePicker" type="date" id="datepicker" />
    </div>
    

    DatePicker here added in ng-if scope and not scope from controller.

    for solving, you can use $parent property

    <div data-ng-if="!CurrentUser">
        <input data-ng-model="$parent.DatePicker" type="date" id="datepicker" />
    </div>
    

    Or apply "dot rule"

    <div data-ng-if="!CurrentUser">
        <input data-ng-model="data.DatePicker" type="date" id="datepicker" />
    </div>
    

    and in js

    $scope.data = { DatePicker : new Date() };
    $scope.$watch('data.DatePicker', function (newValue, oldValue) {
    ...
    

    See a bit more about inheritance scope in wiki

    Sample

    var app = angular.module('myApp', []);
    
    app.controller('BodyCtrl', function($scope, $http) {
      $scope.CurrentUser = null;
      $scope.DatePicker = new Date();
      $scope.data = { DatePicker : new Date() } ;
      $scope.$watch('DatePicker', function(newValue, oldValue) {
        if (newValue > new Date())
          $scope.DatePicker = new Date();
      }, true);
      $scope.$watch('data.DatePicker', function(newValue, oldValue) {
        if (newValue > new Date())
          $scope.data.DatePicker = new Date();
      }, true);
    
    });
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.min.js"></script>
    <div data-ng-app="myApp" data-ng-controller="BodyCtrl">
      <div>
        <span>scope id: {{$id}}</span>
        <input data-ng-model="DatePicker" type="date" id="datepicker" />
      </div>
      <div data-ng-if="!CurrentUser">
        <span>scope id: {{$id}}</span>
        <input data-ng-model="DatePicker" type="date"  />
      </div>
      <div data-ng-if="!CurrentUser">
        <span>scope id: {{$id}}</span>
        <input data-ng-model="$parent.DatePicker" type="date" />
      </div>
      <hr/>
      <div>
        <span>scope id: {{$id}}</span>
        <input data-ng-model="data.DatePicker" type="date" />
      </div>
      <div data-ng-if="!CurrentUser">
        <span>scope id: {{$id}}</span>
        <input data-ng-model="data.DatePicker" type="date"  />
      </div>
      
    </div>