2

I´m trying to build a delayed message box. I observe that apply is called when the app is started, as describe in the API docs. But when the observed value is changed, it isn´t called. The MessageCtrl is inner controller. Why isn´t watch called after changing message var?

angular.module('myApp',[]).controller('MessageCtrl', function($scope) {

  $scope.getMessage = function() {
    setTimeout(function() {
      $scope.$parent.message = {text : ""}; 
      $scope.$apply(function() {        
        console.log('message:' + $scope.$parent.message.text);
      });
    }, 2000);
  }
  $scope.getMessage();    
})
.controller('MainCtrl',function($scope){
  $scope.message={text:"oi"};
  $scope.$watch("message", function(newValue, oldValue){
      console.log("watch " + $scope.message.text);
  });
});

The inner controller MessageCtrl will get the text message and show it for 2 seconds.

<body ng-app="myApp" ng-controller="MainCtrl">
  <div ng-controller="MessageCtrl">
    Message:{{message.text}} 
  </div>
</body>

3 Answers 3

2

As far as I can tell your code does work. You are however using $apply incorrectly. $apply lets you inform angular that you are changing state outside of the usual methods and that is should thus re-evaluate bindings etc. So you should be using

$scope.$apply(function() { $scope.$parent.message = {text: 'new message'}; });

angular.module('myApp', []).controller('MessageCtrl', function($scope) {

    $scope.getMessage = function() {
      setTimeout(function() {
        $scope.$apply(function() {
          $scope.$parent.message = {
            text: "new message"
          };
          console.log('message:' + $scope.$parent.message.text);
        });
      }, 2000);
    }
    $scope.getMessage();
  })
  .controller('MainCtrl', function($scope) {
    $scope.message = {
      text: "oi"
    };
    $scope.$watch("message", function(newValue, oldValue) {
      console.log("watch " + $scope.message.text);
    });
  });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app="myApp" ng-controller="MainCtrl">
  <div ng-controller="MessageCtrl">
    Message:{{message.text}}
  </div>
</div>

One thing of note, you should really use the angular $timeout service which allows you to set timeouts in your app, but you don't have to handle calling $apply.

angular.module('myApp', []).controller('MessageCtrl', function($scope, $timeout) {

    $scope.getMessage = function() {
      $timeout(function() {
        $scope.$parent.message = {
          text: "new message"
        };
        console.log('message:' + $scope.$parent.message.text);
      }, 2000);
    }
    $scope.getMessage();
  })
  .controller('MainCtrl', function($scope) {
    $scope.message = {
      text: "oi"
    };
    $scope.$watch("message", function(newValue, oldValue) {
      console.log("watch " + $scope.message.text);
    });
  });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app="myApp" ng-controller="MainCtrl">
  <div ng-controller="MessageCtrl">
    Message:{{message.text}}
  </div>
</div>

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

Comments

1

You need to use $scope.apply method because setTimeout function is not angular native function :

    setTimeout(function() { 
$scope.apply({
$scope.$parent.message = {text : ""}; $scope.$apply(function() { console.log('message:' + $scope.$parent.message.text); });}) ;}, 2000);

Alternatively you can also use $timeout inbuilt-service in angular like this :

angular.module('myApp',[]).controller('MessageCtrl', function($scope, , $timeout) { $scope.getMessage = function() { $, $timeout(function() { $scope.$parent.message = {text : ""}; $scope.$apply(function() { console.log('message:' + $scope.$parent.message.text); }); }, 2000); } $scope.getMessage(); })

Comments

0

use $timeout instead $apply that executes $apply implicity

angular.module('myApp',[]).controller('MessageCtrl', function($scope, $timeout) {
$scope.getMessage = function() {
   $timeout(function() {
      $scope.$parent.message = {text : ""}; 
      $scope.$apply(function() {        
        console.log('message:' + $scope.$parent.message.text);
      });
    }, 2000);
  }
  $scope.getMessage();    
})

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.