简体   繁体   中英

How to modify the transcluded content of a custom directive?

Im using angular 1.x and I have created a custom directive called slider as following code.

I'm trying to transclude the content of slider directive in order to modify it inside the transclude function. But the problem is clone is not giving a collection of .slide elements. Instead it gives a comment which relates to ng-repeat . I cannot get the compiled output of ng-repeat which should be a collection of .slide divs. I want to know how to access the result of ng-repeat inside transclude function so that I can successfully call scope.showCurrent. Now what happens is, $('.slide') call inside scope.showCurrent() doesnt catch any .slide divs because at the time of call there are no .slide elements. But if ng-repeat provided its compiled html inside transclude function, $('.slide') will catch divs.

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);
               })
          },
     }
});

Following is the html usage of this directive.

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

Here is my plunk https://plnkr.co/edit/m7YJBNuDjeLPaKkUYK5S?p=preview

You don't get .slide divs because at the time your code inside transclude is being executed:

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

the linking functions of the inner content, particularly ng-repeat 's linking function, has not been executed yet. It's inside this linking function a watcher is added for the slides .

Even if you wait until the linking functions get executed, as in here:

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 are still not available until the first digest loop runs.

After your update

You definitely don't need this part here

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

because it will be different clone that the one processed by ng-transclude and ng-transclude will take care of compiling and linking the content. You have to wait until digest loops runs and ng-repeat renders the div .slider elements. For that, use $timeout :

$timeout(function() {
    scope.showCurrent(scope.slider.currentIndex);
}); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM