Tahsis Claus
Tahsis Claus

Reputation: 1929

Run directive code after ng-src

I have a video player directive that uses an ng-src in its template. How do I run directive code after the ng-src has been evaluated so the video is actually loaded?

Here is the directive code:

return {
        restrict: 'A',
        replace: false,
        transclude: false,
        scope: true,

        templateUrl: "/modules/didyouknow/views/slideshow-frame.directive.client.view.html",

        link: {
            pre: function() {
                console.log('a');
            },
            post: function(scope, element, attrs) {
                /**
                 * scope.frame - frame information
                 */
                scope.frame = scope[attrs.slideshowFrame];
            }
        }
    };

both link functions execute before {{expr}} has been evaluated in the template.

The whole point of post link is it that it's executed after child post-links, in reverse order as pre links. So why isn't it executing last? It executes immediately after the prelink function so why are they even separate functions?

Upvotes: 0

Views: 199

Answers (2)

Estus Flask
Estus Flask

Reputation: 223104

There is a couple of recipes to execute the code in link at the moment when directive DOM 'is there'. One is using zero-delayed timeout

$timeout(function () {
  ...
});

It is is generally preferable if you're after rendered DOM or interpolated values. It is not an option here, because templateUrl is used and directive template is loaded asynchronously, and the template is not available during the linking phase.

Another recipe is using scope watchers/attribute observers (one-time if you don't care about data bindings).

var unobserveNgSrc = attrs.$observe('ngSrc', function (ngSrc, oldNgSrc) {
  if (!ngSrc) return;
  unobserveNgSrc();
  ...
})

It executes immediately after the prelink function so why are they even separate functions?

This behaviour suggests what it can be used for. In parent preLink some things can be done that must precede child preLinks or the latter could benefit from, which you will rarely find useful for simple directives. And parent postLink executes last, and that's a good moment for 'ok, all of my children are already compiled and linked, let's do something at last'.

Upvotes: 0

Pankaj Parkar
Pankaj Parkar

Reputation: 136184

You could have $observe inside your directive that will work same as that of the $watch but the difference is it evaluates {{}} interpolation expression.

Inside $observe you could see if the ng-src has value the only call the directive method. otherwise wait.

link: function(scope, element, attrs){
   attrs.$observe('ngSrc', function(newVal, oldVal){
       if(newValue){
           //call desired code when `ng-src` have value
       }
   });
}

Upvotes: 1

Related Questions