Как изменить включенное содержимое пользовательской директивы?

Я использую angular 1.x, и я создал пользовательскую директиву под названием слайдер в следующем коде.

Я пытаюсь transclude содержимое директивы слайдера, чтобы изменить его внутри функции включения. Но проблема в том, что clone не дает коллекцию элементов .slide. Вместо этого он дает комментарий, относящийся к ng-repeat. Я не могу получить скомпилированный вывод ng-repeat, который должен быть набором .slide divs.. Я хочу знать, как получить доступ к результату ng-repeat внутри функции transclude, чтобы я мог успешно вызвать scope.showCurrent. Теперь происходит следующее: $('.slide') вызов внутри scope.showCurrent() не перехватывает .slide div потому что на момент вызова нет .slide элементов. Но если ng-repeat предоставил свой скомпилированный html внутри функции transclude, $('.slide') поймает div.

app.directive('slider', function ($compile) {
     return {
          restrict: 'EA',
          priority: 1200,
          scope: true,
          controller: function ($scope) {
               $scope.slider = { currentIndex: 0 };
          },
          transclude:'element',
          link: function (scope, el, attrs, ctrl, transclude) {

               scope.showCurrent = function (currentIndex) {
                    console.log('x')
                    $('.slide').hide();
                    $('.slide').eq(currentIndex).show();
               }

               scope.$watch('slider.currentIndex', function (val) {
                    console.log('tst');
                    scope.showCurrent(val);
               });

               transclude(scope, function (clone) {
                    el.after(clone);
                    scope.showCurrent(scope.slider.currentIndex);
               })
          },
     }
});

Ниже приведено использование html этой директивы.

<slider>
  <div ng-repeat="slide in slides" class="slide">
     <div>Image {{img}}</div>
     <img ng-src="img"/>
   </div>
</slider>

Вот мой планк https://plnkr.co/edit/m7YJBNuDjeLPaKkUYK5S?p=preview


comment
почему вы хотите использовать трансклюзию здесь? ваша директива не создает изолированную область, а включение обычно используется для привязки внутренних элементов к внешней области   -  person Max Koretskyi    schedule 09.10.2016
comment
Я объяснил в своем ответе, почему вы не получаете slides. Если вы четко объясните, каково ваше первоначальное намерение, я смогу предоставить решение   -  person Max Koretskyi    schedule 09.10.2016
comment
Спасибо, Максимус, и ты прав. Я хотел изменить содержимое клона внутри функции transclude. Проблема заключалась в том, что я думаю, что это потому, что ngRepeat сам по себе является еще одной включенной директивой, которая не отображается, пока функция ссылки созданной мной директивы ползунка. Обходной путь, который я нашел, заключался в том, чтобы добавить еще одну директиву в ngRepeat, которая сигнализирует о событии завершения рендеринга, которое выдается с помощью области действия. 15207788/calling-a-function-when-ng-repeat-has-finished" title="вызов функции после завершения повторения ng"> stackoverflow.com/questions/15207788/   -  person XPD    schedule 09.10.2016
comment
Есть ли лучший способ изменить включенный клон, если он содержит другую включенную директиву (которая отображается как комментарий)?   -  person XPD    schedule 09.10.2016
comment
подскажите зачем вам трансклюзия?   -  person Max Koretskyi    schedule 09.10.2016
comment
Я пытаюсь добавить содержимое этой директивы в шаблон, который может быть выполнен с помощью templateUrl, но мне нужно было получить доступ к содержимому директивы и изменить его, прежде чем прикреплять его к HTML-коду templateUrl.   -  person XPD    schedule 09.10.2016
comment
вы используете директиву ng-transclude в шаблоне?   -  person Max Koretskyi    schedule 09.10.2016
comment
Давайте продолжим обсуждение в чате.   -  person XPD    schedule 09.10.2016


Ответы (1)


Вы не получаете .slide divs, потому что во время выполнения вашего кода внутри transclude:

el.after(clone);
scope.showCurrent(scope.slider.currentIndex);

функции связывания внутреннего содержимого, особенно функция связывания ng-repeat, еще не выполнены. Внутри этой функции связывания добавляется наблюдатель для slides.

Даже если вы подождете, пока не будут выполнены функции связывания, как здесь:

transclude(scope, function (clone) {
    el.after(clone);
    scope.showCurrent(scope.slider.currentIndex);
})
// here the linking functions of the `clone` have already been executed

.slide divs по-прежнему недоступны, пока не запустится первый цикл дайджеста.

После вашего обновления

Вам определенно не нужна эта часть здесь

transclude(scope, function (clone) { 
    el.after(clone); 
    scope.showCurrent(scope.slider.currentIndex); 
})

потому что будет отличаться clone, что тот, который обрабатывается ng-transclude и ng-transclude, позаботится о компиляции и связывании контента. Вам нужно дождаться, пока циклы дайджеста не запустятся, а ng-repeat отобразит div .slider элементов. Для этого используйте $timeout:

$timeout(function() {
    scope.showCurrent(scope.slider.currentIndex);
}); 
person Max Koretskyi    schedule 09.10.2016