简体   繁体   中英

Call Javascript After Directive Renders DOM for ShareThis

In an Angular (1.3) app, I am displaying list of records using ng-repeat. There is a directive with a template inside the ng-repeat. Within the template I'm using ShareThis controls which are activated after the DOM is loaded.

On initial load of the app, the ShareThis Javascript works correctly and activates the buttons. On route change it does not activate. I've found to references to activate the controls manually via stButtons.makeButtons() or stButtons.locateElements(); , but I'm unsure where to call this function in the directive or page cycle. I've tried within:

  1. the directive link function - using $timeout or scope.$watch
  2. the template <script>stButtons.locateElements();</script> - activates before model binding
  3. the controller after binding - activates before DOM rendered

My understanding is the function to activate needs to be called after binding and after DOM rendering, but Angular does not know when the DOM is ready. There is a method to dynamically render the ShareThis controls using only Javascript, but I want the HTML defined in the template not Javascript for this case.

I've seen several questions out there related, but none of the answers seem to work 100% for my scenario (and many are broken as of Angular 1.3).

item-list.html (view)

<div ng-repeat="item in vm.itemList">
    <item-directive item="item"></item-directive>
</div>

item-list.cs (controller)

{ ... vm.itemList = getItems(...) ... }

item-directive.js (directive)

(function () {
    angular.module('app');
    function itemDirective() {
        var directive = { templateUrl: 'item.html', link: linkFunc, controller: ItemDirective };
        return directive;
        function linkFunc(scope, element, attr, ctrl) { var item = scope.item }
    }
    ItemDirective.$inject = ['$scope'];
    function ItemDirective($scope) { ... }
}

item.html (directive template)

...
<div class="item-share-section">
    <span class='st_sharethis_large' st_url="{{vm.item.url}}" st_title="{{vm.item.name}}"></span>
</div>
...

if I understood well, you want to call the function after the dom is completely render, right? Try this inside the postLink of your directive:

$scope.$watch('viewContentLoaded', stButtons.locateElements())

While my solution is a little hackish, I still prefer it over using $watch, since that is inefficient. Instead, I initialize the function which loads the buttons when the particular view you want to load the buttons with is rendered. The technique is as follows:

Here is the function which you should put in your controller:

  $scope.loadShareThis = function() {
    stButtons.makeButtons();
  }

You'd then add to your item-list.html as such:

<div ng-repeat="item in vm.itemList" ng-init="loadShareThis()">
    <item-directive item="item"></item-directive>
</div>

The dynamic URL's might give you additional problems, but that's another issue all together.

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