AngularJS: scope у transcluded html

2014-09-17

Здесь пойдет речь о scope-е, который виден из html «обернутого» directive-ой.

Допустим, у нас есть директива с некоторым трансклудженным html внутри нее:

HTML:

<div ng-app="App" ng-controller="Ctrl">
<input ng-model="myVar" />
<my-dir>
<input ng-model="myVar" />
</my-dir>
</div>

JavaScript:

angular
.module('App', [])
.controller('Ctrl', function ($scope) {
$scope.myVar = 111;
})
.directive('myDir', function () {
return {
restrict: 'E',
transclude: true,
template: '<hr>[<b ng-transclude></b>]'
}
});

Код можно посмотреть тут: http://jsfiddle.net/x8fcea2k/

И снаружи и внутри директивы у нас есть код <input ng-model=’myVar’ />.
Внутри обеих input мы видим значение ‘111’ и мы ожидаем двустороннюю связку при изменении значения.
Но что происходит на самом деле: при изменении значения верхнего input меняется и значение нижнего, но при измерении нижнего — связка теряется. Если мы попытаемся получить значение с контроллера — оно не будет соответствовать измененному в трансклудженном html.

Почему так происходит?

Дело в том, что трансклудженный html получает новый scope, который наследует scope контроллера. Обратите внимание, что этот scope не является scope-ом директивы. Он создан именно для html внутри директивы.
Когда мы изменяли значение верхнего input-а — значение наследовалось, когда же мы изменили значение нижнего — этот новый экземпляр scope-а создал у себя такую же переменную myVar.

Как же нам обратиться к переменной myVar нашего контроллера из html внутри директивы?

Это можно сделать несколькими путями:

  • Используя объект вместо статической переменной в контроллере $scope.myObject = {myVar: 111}. Когда scope трансклудженного html отнаследует scope контроллера — он получит ссылку на тот же объект и связь не пропадет <input ng-model=’myObject.myVar’ />.
  • Используя ссылку на scope родителя $parent: <input ng-model=’$parent.myVar’ />. Этот способ не самый лучший потому, что при использовании дополнительных оборачивающих директив эта ссылка может быть поломана и нужно всегда отслеживать глубину scope-ов, что не есть хорошо.

Более подробно можно почитать тут:



Добавить комментарий