Странное поведение при использовании трансклюзии без клонирования

Немного поэкспериментировав с включением, я хотел посмотреть, сможет ли включенная директива, для которой требуется определенный контроллер родительской директивы, найти ее после включения под требуемым родителем. Директивы, которые я использовал, следующие: Существует директива ParentOfParent, которая имеет значение transclude:true. Существует директива Parent, которая встроена в шаблон директивы ParentOfParent. Существует директива Child, которая требует родительского контроллера и включается ParentOfParent как дочерняя директива Parent.

    'use strict';
angular
    .module('angularlabApp', [
    'ngRoute',
])
    .config(function ($routeProvider) {
    $routeProvider
        .when('/', {
        templateUrl: 'main.html',
        controller: 'MainCtrl'
    })
        .otherwise({
        redirectTo: '/'
    });
});

'use strict';
angular.module('angularlabApp')
    .directive('parent', function () {
    return {
        controller: function () { },
        restrict: 'EA',
        link: function postLink(scope, element, attrs) {
            console.log('Parent Link');
        }
    };
});

'use strict';

angular.module('angularlabApp')
  .directive('parentOfParent', function () {
    return {
      template: '<div id="prnt" parent></div>',
      transclude: true,
      restrict: 'EA',
      link: function(scope, element, attrs,_,transcludeFn){
        console.log('POP Link');
        element.find('#prnt').append(transcludeFn());

      }
    };
  });


'use strict';

angular.module('angularlabApp')
  .directive('child', function () {
    return {
      template: '<div></div>',
      restrict: 'EA',
      require:'^parent',
      link: function postLink(scope, element, attrs) {
        console.log('Child Link');
      }
    };
  });


'use strict';
angular.module('angularlabApp')
    .controller('MainCtrl', function ($scope) {
});

То, с чем я столкнулся, было странным несоответствием между использованием функции трансклюзии с клонированием и без него. Когда я использую вывод функции включения (без передачи cloneFn), я получаю сообщение об ошибке, что дочерняя директива не может найти родительский контроллер над ним. http://plnkr.co/edit/JteQpPMc6nbVNjRDHVZ2

Однако, когда я использую его, передавая cloneFn, все работает.

Возможно ли, чтобы включенная директива нашла требуемый контроллер после вставки ниже директивы, которой принадлежит контроллер?


person Boris Litvinsky    schedule 31.07.2015    source источник
comment
Да, это поведение - потому что в момент включенного контента ссылки, он не находится под требуемым родителем, поэтому require: "parent" выдает ошибку. Хотя в чем вопрос? Очевидно, что это возможно, как вы упомянули - поместите элемент в cloneAttachFn, что происходит до связывания   -  person New Dev    schedule 31.07.2015
comment
Я пытаюсь понять разницу между использованием клона и исходного контента. Почему это работает с клонированным контентом, но не с оригинальным   -  person Boris Litvinsky    schedule 01.08.2015
comment
Это не вопрос клонирования или оригинала — это вопрос предварительно связанного контента и пост-ссылки. Вот мой ответ на аналогичный вопрос - stackoverflow.com/a/29911348/968155   -  person New Dev    schedule 01.08.2015
comment
@NewDev отличный ответ, хотя не могли бы вы уточнить немного подробнее? Возможно, объясните, где в обоих случаях ищется родительский контроллер? Насколько я понимаю, при передаче cloneFn содержимое связывается ПОСЛЕ завершения обратного вызова, в отличие от случая, когда используется вывод функции включения. В более позднем случае возвращаемый шаблон уже связан. Правильный?   -  person Boris Litvinsky    schedule 02.08.2015
comment
Не уверен, правильно ли я понял ваш вопрос, но, судя по вашему самостоятельному ответу, вы, кажется, понимаете проблему. Контроллер ищется во время линковки. cloneFn — это возможность разместить клонированное содержимое в DOM до того, как оно будет слинковано, чтобы такие вещи, как require, работали корректно.   -  person New Dev    schedule 02.08.2015
comment
круто.спасибо за подтверждение.   -  person Boris Litvinsky    schedule 02.08.2015


Ответы (1)


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

Когда используется вывод функции transclude (без передачи обратного вызова clone), вывод уже скомпилирован и СВЯЗАН.

var linkedClone = $transcludeFn();

Поскольку связывание уже произошло, скопированная директива уже искала контроллер родительской директивы. Поскольку скопированный узел DOM все еще отсоединен, его невозможно найти.

Напротив, когда скопированное поддерево DOM получено через обратный вызов клона, как описано в статье:

Скомпилируйте клон в дочерней области действия директивы и передайте клон перед вызовом всех его функций связывания.

Следовательно, вы получаете возможность присоединить скопированное поддерево DOM ДО того, как оно будет связано, что позволит ему искать контроллер над ним, когда он уже находится в DOM.

person Boris Litvinsky    schedule 02.08.2015