Почему область ng-transclude не является дочерним элементом своей директивной области - если директива имеет изолированную область видимости?

Учитывая директиву (container1) с transclude и изолированной областью действия, когда директива связана, я имею следующие области:

Scope 004           <-- scope of the body
    Scope 005       <-- scope of directive container1
    Scope 006       <-- scope of the ng-transclude

Я ожидал:

Scope 004            <-- scope of the body
    Scope 005        <-- scope of the directive
         Scope 006   <-- scope of the ng-transclude

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

Это вызывает у меня проблему, потому что, если транслируемый контент содержит другую директиву (component1) с изолированной областью, я получаю:

Scope 004             <-- scope of the body
    Scope 005         <-- scope of the directive
    Scope 006         <-- scope of the ng-transclude
          Scope 007   <-- scope of directive component1

Я хочу использовать такие директивы, как это:

<container1>
   <component1 data="objectExposedInContainer1"/>
</container1>

Но это не работает, внутри component1, $scope.data есть undefined, потому что objectExposedInContainer1 не находится в правильной области.

У меня есть два вопроса:

  • Почему область ng-transclude не является дочерним элементом своей области директивы, если директива имеет изолированную область видимости? Это ошибка?
  • Если это не ошибка, как директива контейнера может передавать данные в контент, если не путем установки таких атрибутов, как я пытался.

Вот пример, где он не работает: http://plnkr.co/edit/NDmJiRzTF9e5gw8Buht2?p=preview. Поскольку Plunker построен с Anguar, его трудно отлаживать с Batarang. Я рекомендую загрузить код локально. Комментируйте line 10 of app.js, чтобы он работал с использованием общей области.

Ответ 1

Почему область ng-transclude не является дочерним элементом своей области директивы, если директива имеет изолированную область видимости?

ng-transclude, предназначенный для разрешения директив работать с произвольным контентом, а изолированные области предназначены для того, чтобы директивы могли инкапсулировать свои данные.

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

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

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

Если директива контейнера должна вводить содержимое в область содержимого дочерних элементов (например, ng-repeat), тогда вы не должны использовать изолированную область.


Документация angular достаточно понятна для того, как должно выглядеть поведение:

"В типичной настройке виджет создает область изоляции, но переключение - это не ребенок, а родственник изолята. Эта позволяет виджету иметь личное состояние, а переход должен быть привязан к родительскому (предварительно изолированному) объему."

Ответ 2

вы можете вручную перенести дочерний элемент

link: function(scope, element, attrs, ctrl, transclude) {
    transclude(scope, function(clone, scope) {
        element.find('.transclude-placeholder').append(clone);
    });
}

Ответ 3

Верхний ответ верен только для Angular до v1.2.

Так как Angular v1.3, поведение изменилось, и теперь оно ведет себя точно так, как описано в части "Я ожидал" вопроса, сделав этот вопрос устаревшим для Angular v1.3 +.

Источник: https://github.com/angular/angular.js/commit/fb0c77f0b66ed757a56af13f81b943419fdcbd7f