Angularjs: двухсторонняя привязка не работает в включенном шаблоне

Я думаю, что я пропустил что-то простое (и важное) здесь. Я использую включенный шаблон, который содержит вход, который отображается на некоторое значение:

<div ng-controller="Ctrl">
    <div ng-include src="'template.html'"></div>
</div>

<!-- template -->
<script type="text/ng-template" id="template.html">
    <input ng-model="testvalue" />
</script>

Контроллер:

function Ctrl($scope) {    
   $scope.testvalue= "initial value";
}​

Предупреждение значения $scope.testvalue всегда показывает начальное значение, а не обновленное значение (при вводе ввода). Помоги мне Оби-Вану. Вы - наша единственная надежда.

Fiddle: http://jsfiddle.net/h5aac/

Ответ 1

Это слишком распространенная привязка к примитиву, а не к объекту. Значение строки передается, а не ссылка на объект. Если вы используете объект вместо примитива, он отлично работает. Что-то вроде этого в вашем объеме.

$scope.foo = {testvalue: "initial value"};

См. http://jsfiddle.net/h5aac/2/

также:

Использование` ng-model` в директиве transcluded в AngularJS

проблема с привязкой к директиве в ngRepeat

AngularJS - обновление значения области с асинхронным ответом

Я уверен, что есть еще...

Ответ 2

Альтернативой ссылаться на свойство объекта в родительской области является использование $parent для доступа к примитиву в родительской области:

<input ng-model="$parent.testvalue" />

ng-include создает дочернюю область. Этот объем прототипически наследуется от родительской области Ctrl. Вот как работают 3 варианта:

  • $parent.testvalue привязывает модель к свойству в родительской области
  • testvalue сам по себе связывает модель с новым свойством, которое будет создано в области дочерних объектов. Это свойство "теней/скрывает" свойство родительской области с тем же именем.
  • foo.testvalue(например, см. ответ @dnc253) также связывает модель с родительским свойством. Он работает следующим образом: Javascript не видит/не находит "foo" в области содержимого, поэтому он ищет его в родительской области (из-за прототипического наследования) и находит его там.

Чтобы увидеть, как выглядит область доступа к ребенку, используйте свою оригинальную скрипту и добавьте этот код в свой шаблон где-нибудь:

<a ng-click="showScope($event)">show scope</a>

И добавьте этот код в свой Ctrl:

$scope.showScope = function(e) {
   console.log(angular.element(e.srcElement).scope());
}

Прежде чем вводить текстовое поле, нажмите ссылку "показать область". В консоли (я использую Chrome) вы можете расширить область "Ребенок" и увидеть, что она еще не содержит свойства testvalue (что мне кажется удивительным, потому что я не знаю, как он отображает "начальное значение", в текстовом поле). Вы можете развернуть $parent, и вы увидите свойство testvalue - свойство с этим именем отображается только в родительской области на данный момент.

Теперь очистите консоль, введите в текстовое поле и снова нажмите ссылку "показать область". Вы увидите, что область "Child" теперь имеет новое свойство testvalue. Он скрывает/скрывает родительское свойство. Таким образом, вещи в области дочерних объектов видят свойство testvalue дочернего объекта, а объекты в родительской области - свойство testvalue родительской области.

Обновление: FYI, я недавно написал обширный ответ/статью о прототипном наследовании области, которая более подробно объясняет приведенные выше концепции с большим количеством фотографий: Каковы нюансы объема прототипа/прототипного наследования в AngularJS?