简体   繁体   中英

Two way binding in Angular JS

I get a problem with follwoing code.

my html page code :

<body ng-app="myapp">

    <div ng-controller="myController">
    The message is {{message}}
        <input type="button" value="Change Message" ng-click="changeMessage()">

   </div>

My Controller code:

app.controller('myController',function($scope)
{              
 $scope.changeMessage=function()
    {
        setTimeout(function(){
        console.log("Message changed");
      $scope.message="Hurray !!! New Message";    

        },3000);

$scope.newMessage=function()
        {
            $scope.message="hello";
            console.log("new message");
        };

But if I use changeMessage function I am not able to see the changed Message property even though the console.log message comes. what is missing here in both cases.

Thanks in advance

you should use $digest() after that the timeout is done:

$scope.changeMessage=function()
{
   setTimeout(function(){
    $scope.message="Hurray !!! New Message";  
    $scope.$digest();
   },3000);
}   

please note that it is much better to use $digest instead of $apply (performance related):

scope.$digest() will fire watchers on the current scope, and on all of its children, too. scope.$apply will evaluate passed function and run $rootScope.$digest()

every change should happen within an angular-digest-cycle. if you change values from the outside (which is exactly what happens, if you use setTimeout instead of angular's $timeout ) angular does not update your view until the next digest-cycle ( https://www.ng-book.com/p/The-Digest-Loop-and-apply/ ). so in your case the message is already set, but the view has not been updated.

try something like this:

app.controller('myController', function($scope, $timeout) {
  $scope.changeMessage = function() {
    $timeout(function(){
      console.log("Message changed");
      $scope.message="Hurray !!! New Message";    
    }, 3000);

  $scope.newMessage=function() {
    $scope.message="hello";
    console.log("new message");
  };

The reason that the change isn't reflected in the view is that because of the assignment is done in the callback in setTimeout which results in angular not noticing the change. This has to do with the so called digest cycle. There are different ways to solve this.

use $scope.$apply() to wrap your assignment

or even better use the existing $timeout service provided by angular instead of the call to setTimeout which already handles the problem above for you.

For details, see https://docs.angularjs.org/api/ng/service/$timeout for usage of $timeout

and https://docs.angularjs.org/api/ng/type/$rootScope.Scope for the reasons behind $apply.

A general explanation of what is happening here is described at http://www.sitepoint.com/understanding-angulars-apply-digest/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM