1

I have created a directive, ngAfterRender, that I am trying to use to wire up fancybox:

Template

<div ng-after-render="wireUpFancyBox($event)" ng-bind-html="Content"></div>

Directive

.directive('ngAfterRender', ['$timeout', function ($timeout) {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            $timeout(function () {
                scope.$eval(attrs.ngAfterRender, { $element: element });
            });
        }
    };
}]);

Controller

    $scope.wireUpFancyBox = function ($element) {
        $element.find('a').fancybox($.extend(true, {}, fancyboxOptions, {
            scrolling: 'auto',
            type: 'inline'
        }));
    };

Unfortunately, the wireUpFancyBox() method is not called when the HTML Content binding changes.

What can I do here?

John Gietzen
  • 45,925
  • 29
  • 140
  • 183
  • 1
    try `$timout(function(){}, 0);` – Fourth Dec 04 '13 at 20:44
  • @Fourth: That made no difference. It binds on the first render of the page, but on subsequent modifications to the `Content` value, it does not get called. – John Gietzen Dec 04 '13 at 20:48
  • can you make a plunker with the problem? my thought is that you can bind a scope watch to attrs.ngBindHtml and then when it changes, re-eval. The problem, as I see it, is that your directive will only ever run on the first render but isn't paying attention to when the content changes and can't react to that situation. – Fourth Dec 04 '13 at 20:55

1 Answers1

1

If you want wireUpFancyBox called every time the ng-bind changes then you want something like this

myApp.directive('ngAfterRender', ['$timeout', function ($timeout) {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            scope.$watch(function () {
                return scope.$eval(attrs.ngBindHtml);
            },
            function (value) { 
               $timeout(function () {   
                  scope.$eval(attrs.ngAfterRender, { $element: element });
               });
            });
        }
    };
}]);

Here we put a watch on the evaluated ng-bind-html expression and then fire off your eval on a change.

fiddle

KayakDave
  • 24,456
  • 3
  • 62
  • 67
  • Curious- why janky? Feels like normal (although far from obvious- thus your comment?) Angular to me – KayakDave Dec 04 '13 at 21:40
  • It's janky because there is no guarantee that the DOM will have rendered by the time the result of the $timeout is called. Right? – John Gietzen Dec 04 '13 at 22:56
  • 3
    You are guaranteed. Here's a [good discussion on the details of why](http://blog.brunoscopelliti.com/run-a-directive-after-the-dom-has-finished-rendering) – KayakDave Dec 04 '13 at 23:01