Is it possible to create a directive that acts like a single?

We have a directive as part of our large single page application. We use the same directive in several places on the page and every time it is in effect it looks exactly the same. The main problem we see is that this directive has an ng-repeat that creates several hundred DOM elements.

Is it possible to create a directive that acts like a singleton? That is, only one watch per collection, not a watch each time the directive is used, or caches the creation of DOM elements to improve speed. Or is there a better way to use the same DOM elements multiple times on the same page.

I was thinking about using a custom ng-repeat that will cache the generated and reused html, would that be the best approach?

+3


source to share


3 answers


Angular has a singleton concept in a "service" component. You cannot make directives monochromatic (no hackers), but you can completely do it because they are already there. The way I would like to approach this would be for the service to do data work and expose it to the directive (s). The directives just access the service, and since the services are already single-point, they will all share a common object / collection / data model.



+2


source


Of course it is possible in some way. Here's a sample script :

app.directive('sample', function ($compile, $timeout) {
  var cached;

  return {
    scope: { sampleData: '@', sampleArray: '=' },
    // simple counter for bindings
    controller: function ($scope) {
      $scope.getSampleData = function () {
        console.log('getSampleData');
        return  $scope.sampleData;
      };
    },
    // no overhead for nested directives
    terminal: true,
    template: '<div ng-repeat="n in sampleArray">{{n}} {{::getSampleData()}}</div>Hi! {{::getSampleData()}}',
    compile: function (element) {
      // keeping it wrapped into single element may save you from surprises
      var contents = angular.element('<div>').append(element.contents());
      element.empty();

      return function (scope, element, attrs, ctrl) {        
        cached = cached || $compile(contents)(scope);

        // there no interpolated template available in post-link, so
        $timeout(function () {
          element.append(cached.clone().contents());
        });

      };
    }
  };
}); 

      



There is no control over the compilation phases, but a cached template can be provided to a directive whenever possible. You might also consider using a cache service instead of a local variable.

No one can guarantee that this will not cause problems. If you have not reached the performance problems and did not use other optimizations (I personally tricks found these are quite inspiring ), said the approach should be considered as a special case of premature optimization (that is a mortal sin).

+2


source


If you have a problem with the number of hours generated by ng-repeat you should use bindOnce (was built in angular 1.3).

If you have a rendering issue, you might want to consider an alternative rendering like ReactJS

+1


source







All Articles