简体   繁体   中英

AngularJS ngModel doesn't work inside a ui-bootstrap tabset

The following code illustrates the problem:

<!DOCTYPE html>
<html ng-app="plunker">
  <head>
    <title>AngularJS Plunker</title>
    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" />
    <script src="https://code.angularjs.org/1.3.6/angular.js"></script>
    <script src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.12.0.min.js"></script>
    <script>
angular.module('plunker', ['ui.bootstrap'])
.controller('MainCtrl', function($scope) {
  $scope.changes = 0;
  $scope.updateValueInScope = function () {
    $scope.valueInScope = $scope.value;
    $scope.changes++;
  }
});
    </script>
  </head>

  <body ng-controller="MainCtrl">
    <tabset>
      <tab heading="Tab A">
        <div class="panel">
          <input type="text" ng-model="value" ng-change="updateValueInScope()" />
          <br />
          <tt>value: {{value}}</tt><br />
          <tt>valueInScope: {{valueInScope}}</tt><br />
          <tt>changes: {{changes}}</tt>
        </div>
      </tab>
    </tabset>
    <input type="text" ng-model="value" ng-change="updateValueInScope()" />
    <br />
    <tt>value: {{value}}</tt><br />
    <tt>valueInScope: {{valueInScope}}</tt><br />
    <tt>changes: {{changes}}</tt>
  </body>

</html>

Plunker here:

http://plnkr.co/edit/dJc009csXVHc7PLSyCf4?p=preview

This creates two textboxes, one inside the tabset, and one outside. They are both bound to the value scope variable. Updating the contents of the textbox inside the tabset does not update the value variable in the scope. Updating the textbox outside the tabset does. Changes to either of the textboxes will result in a call to updateValueInScope() via ngChange.

Can someone explain to me why this behaves this way? Is there some way to "fix" the behavior so that the textbox inside the tabset will modify the model in the scope?

Almost certainly the issue is that you are trying to bind to a primitive (in this case a float). Something like this should fix it.

$scope.data = {}
$scope.updateValueInScope = function () {
  $scope.data.valueInScope = $scope.data.value;
  $scope.changes++;
}

Basically in angular, if you bind to a primitive the value of the variable is passed around, and not the reference to it, which can break 2-way binding. I'm guessing that the tabset directive creates its own scope, so the valueInScope variable defined in the controller loses its binding in the child scope of the tabset because its a primitive. Anyway, don't bind to primitives and it should work.

Here is a fixed version of plunk

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