user1735940
user1735940

Reputation: 143

AngularJS view doesn't update when ng-model value changed

Please check this codepen, when clicked on the button click me to reset name, the name input should be reset to empty, when I do console.log on the directive scope, I do see name is set to empty string, but the value in the view not get updated. What's wrong?

CodePen example

angular.module('mainApp', [])
  .directive('myTab', function() {
    return {
      restrict: 'E',
      template: 'name: <input type="text" ng-model="name">',
      controller: function($location, $scope) {
        $scope.name = 'myname';
        $('#clickMeToReset').on('click', function() {
          $scope.name = '';
        })
      }
    };
  })
  .directive('myMenu', function() {
    return {
      restrict: 'E',
      template: '<button id="clickMeToReset">click me to reset name</button>'
    };
  });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>


<div ng-app="mainApp">
  <my-menu></my-menu>
  <my-tab></my-tab>
</div>

Upvotes: 2

Views: 2048

Answers (4)

Ahmad Mobaraki
Ahmad Mobaraki

Reputation: 8178

When you use other libraries like jquery in angular, changes to variables like $scope should manually broadcast.

 $('#clickMeToReset').on('click', function(){
        $scope.name = '';
        $scope.$apply();
})

so $scope.$apply(); will do the trick!

Upvotes: 2

Shashank Agrawal
Shashank Agrawal

Reputation: 25797

Modify your controller code with the following:

controller: function($location,$scope, $timeout){
  $scope.name = 'myname';
  $('#clickMeToReset').on('click', function(){
    $timeout(function() {
       $scope.name = '';
    });
  })
}

angular.module('mainApp', [])
  .directive('myTab', function() {
    return {
      restrict: 'E',
      template: 'name: <input type="text" ng-model="name">',
      controller: function($location, $scope, $timeout) {
        $scope.name = 'myname';
        $('#clickMeToReset').on('click', function() {
          $timeout(function() {
            $scope.name = '';
          });
        })
      }
    };
  })
  .directive('myMenu', function() {
    return {
      restrict: 'E',
      template: '<button id="clickMeToReset">click me to reset name</button>'
    };
  });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app="mainApp">
  <my-menu></my-menu>
  <my-tab></my-tab>
</div>

Since you are using jQuery to change the value, which is out of the Angular's context, so Angular is unaware of the change. So you need to tell Angular that something has changed. So we are using $timeout service to achieve this. We can also use $scope.$apply() but that may fail when the digest cycle is already in progress.

Important

You should use ng-click instead and remove dependency of jQuery if possible since jQuery is also a big library in itself like Angular (see a working example below):

angular.module('mainApp', [])
  .directive('myTab', function() {
    return {
      restrict: 'E',
      template: 'name: <input type="text" ng-model="name">',
      controller: function($scope) {
        $scope.name = 'myname';
        $scope.clearName = function() {
          $scope.name = '';
        }
      }
    };
  })
  .directive('myMenu', function() {
    return {
      restrict: 'E',
      template: '<button ng-click="clearName()">click me to reset name</button>'
    };
  });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>

<div ng-app="mainApp">
  <my-menu></my-menu>
  <my-tab></my-tab>
</div>

Upvotes: 1

VjyV
VjyV

Reputation: 334

I hope According to my thinking this code help you . Only change Js code remaining HTML code is proper.

   var mainApp = angular.module('mainApp', []);
   mainApp.directive('myTab', function() {
   return {
    template: 'name: <input type="text" ng-model="name">',
    controller: function($location,$scope){ debugger;
      $scope.name = 'myname';
      $('#clickMeToReset').on('click', function(){
        $scope.name = '';
      })
    }
  };
})
.directive('myMenu', function() {
  return {
    name:"clickMeReset",
    template: '<button id="name" ng-click="clear()">click me to reset name</button>',
    controller:
    function($location,$scope){
      $('#name').on('click',       function(){
        $scope.name = '';
      })
    }
  };
});

Upvotes: 0

Vinod Bhavnani
Vinod Bhavnani

Reputation: 2225

After

$scope.name = '';

Do a

$scope.$apply();

Upvotes: 2

Related Questions