Есть ли в AngularJS сокращение для создания дочерних областей в разметке?

Использование ng-repeat создает новые дочерние области на лету; Я ищу способ сделать то же самое, но с одним объектом.

Другими словами, вместо этого...

<div ng-controller="SomeController">
    <ul>
        <li>{{foo.bar}}</li>
        <li>{{foo.baz}}</li>
    </ul>
</div>

Я хочу сделать что-то вроде этого:

<div ng-controller="SomeController">
    <ul ng-scope="foo">
        <li>{{bar}}</li>
        <li>{{baz}}</li>
    </ul>
</div>

2 ответа

Я никогда не нуждался в подобных вещах, но вот директива, которая создает дочернюю область.

function RestrictScopeDirective() {
    return {
        scope: {src: "=restrictScope"}
    };
}

Теперь в этой области, $scope.src будет относиться к тому, что вы установите для него.

<div ng-controller="SomeController">
    <ul restrict-scope="foo">
        <li>{{src.bar}}</li>
        <li>{{src.baz}}</li>
    </ul>
</div>

Это позволит вам ограничить область действия, но, тем не менее, вам, возможно, придется переосмыслить свои потребности, как правило, это делается для особых требований, таких как виджеты или тому подобное.

Вот тип решения: http://plnkr.co/edit/Vd4YtCYcZKs9mMQLPK8v?p=preview

Первой идеей было клонирование объекта, указанного в атрибуте, в область действия директивы:

scope.$parent.$watch(attrs.scope, function(nv) {
           angular.extend(scope, nv);
        },true);

Это не слишком эффективно (так как каждый раз, когда объект изменяется, Angular должен копировать его свойства в область видимости), но это простой способ добиться того, чего вы хотите.

Проблема с этой идеей в том, что у вас есть только односторонняя привязка (из внешней области видимости во внутреннюю).

В случае, если у вас есть двустороннее связывание, вам нужно реагировать на изменения области действия директивы, чтобы отразить это на родителе. Вид:

 link: function(scope, element, attrs) {
    var watches = [];
    var unregister = scope.$parent.$watch(attrs.scope, function(nv) {
       watches.forEach(function(w) { w(); });
       watches.length = 0;
       for (var key in nv) {
         if (key) {
            scope[key] = nv[key];
            watches.push(scope.$watch(key, function(key)  { 
              return function(knv) {
              nv[key] = knv;
            };}(key)));
         }
       }
    },true);
    scope.$on('$destroy', function(){
       unregister();
    });
 }

Тем не менее, я думаю, что лучше разбить код на разные партиалы / директивы / и т.д...

Другие вопросы по тегам