angular-bootstrap (tabs): data binding works only one-way

angular-ui, angularjs, angularjs-scope

Solution

The problem is the same as in ng-repeat when you edit a primitive - the `<pane>` directive creates a new scope which inherits from the parent.

Now, given the way Javascript inheritance works the `<pane>` directive has its own copy of the `foo` string primitive, and when you edit it you are only editing it on the pane child scope.

A simple solution would be to put `foo` in an object on your parent Ctrl:

function Ctrl($scope) {
  $scope.data = { foo: 42 };
}

Then you can do this in your HTML:

<tabs><pane><input ng-model="data.foo"></pane></tabs>

Why does it work with an object? Because when `<pane>` inherits the parent's scope, its reference to `data` will refer to the same object in memory as on the parent Ctrl. Primitives like strings and numbers are copied in inheritance, and objects simply create a new pointer to the same object.

TL;DR: `<pane>`'s new scope inherits the `foo` string primitive as a new copy of `foo` which when edited won't change on the parent Ctrl. `<pane>`'s new scope would inherit an object like `data` as a reference to the same object, and when edited on the `<pane>` scope the same object would be referenced on the parent scope.

Helpful article: https://github.com/angular/angular.js/wiki/The-Nuances-of-Scope-Prototypal-Inheritance

Problem

I prepared a little fiddle and boiled it down to the minimum: http://jsfiddle.net/lpeterse/NdhjD/4/ ``` <script type="text/javascript"> angular.module('app', ['ui.bootstrap']); function Ctrl($scope) { $scope.foo = "42"; } </script> <div ng-app="app" ng-controller="Ctrl"> 1: {{foo}}<br /> 2: <input ng-model="foo" /> <tabs> <pane heading="tab"> 3: {{foo}}<br /> 4: <input ng-model="foo" /> </pane> </tabs> </div> ``` In the beginning all views reference the model `Ctrl.foo`. If you change something in input `2:` it properly updates the model and this change gets propagated to all views. Changing something in input `4:` only affects the views included in the same pane. It behaves like the scope somehow forked. Afterwards changes from `2:` don't get reflected in the tab anymore. I read the angular docs on directives, scopes and transclusion, but couldn't find an explanation for this undesired behaviour. I would be grateful for any hints :-)

Original source

Related problems