0

As we known, the angular have performance if there are more than 2000 records in the page, because only some of the records need add some behavior , so I would prefer to dynamically add attribute to element according model value in link function, as there will be less watches.

So I use $compile to recompile the element like below:

mainApp.directive("popoverSetting", function ($compile) {
    return {
        restrict: "A",
        link: function (scope, element, attrs) {
            if (scope.item.isTrue) {
                element.attrs("ns-popover-trigger", "mouseenter");
                element.attrs("ns-popover-timeout", "0.01");

                $compile(element)(scope);
            }
        }
    }
})

Because there are about 1000 records, so the speed is very slow, is there some other way to add attribute and compile quickly? although there only 5 records need to add these attribute, it still increase about twofold time than before.

7
  • If it was me i would delegate the mouse events to the main parent of all of these elements and trigger the popover from that single event listener. Then there is nothing to compile at element level, just add a class instead on the ones that have popover Commented May 6, 2015 at 3:50
  • @charlietfl,I think like what you do, you need control popover operation yourself. but here there is an directive to support and I just need to add the attribute it can work immediately. Commented May 6, 2015 at 3:58
  • Well that's all fine and good if that simple directive wasn't causing serious performance problems Commented May 6, 2015 at 4:02
  • what is controlling the popovers? Wouldn't it be better to include the logic internally in the directive rather than trying to update the entire DOM to add or remove logic? Commented May 6, 2015 at 4:03
  • @charlietfl, the simple directive is great. but there are more than 1000 records, if I add these attribute related to the directive to element, and determine whether this element should show the popover information, it need 1000 watches at least, so it will cause performance issue. I think use dynamic compile to add attribute as necessary. but it also make it more slow. Commented May 6, 2015 at 5:13

2 Answers 2

0

The problem with trying to do this is that nested compiles are slow (an understatement), especially when you are talking thousands of them. It just isn't the way to go.

I could see where some may consider this ugly, and depending on your needs, this solution may NOT work for you, but it does get everything compiled pretty quickly, with the attributes applied. I ended up building a compiler directive that would generate markup based on the dataset, adding the necessary attributes if isTrue was true, and then compiling the whole thing once. The ugly part is that it doesn't generate bindings. So if you need to change something or update something, you'll have to recompile the whole thing.

It's running right now at about 200-300ms to compile the whole thing with 2000 items in the dataset.

Plunker

Directives:

app.directive('nsPopoverTrigger', function($timeout) {
  return {
    restrict: 'A',
    link: function(scope, element, attrs) {
      element.on(attrs.nsPopoverTrigger, function() {
               console.log('popover triggered')
             })  
    }
  }
})
app.directive('compiler', function($compile) {
  return {
    restrict: 'A',
    link: function(scope, element, attrs) {
      var i = 0, template = '<ul>'
      scope.generateMarkup = function() {
        for (i; i < scope.data.length; i++) {
          if(scope.data[i].isTrue) {
            template = template + "<li ns-popover-trigger='mouseenter' ns-popover-timeout='0.01'>" + scope.data[i].key + "</li>"
          } else {
          template = template + '<li>' + scope.data[i].key + '</li>'
        }
        }
      var $template = angular.element(template)
      $compile($template)(scope)
      element.append($template)
      }
    }
  }
})
Sign up to request clarification or add additional context in comments.

5 Comments

the reason it is necessary to recompile is that there is a directive to realize the requirement. basically the angular will compile these attribute to add behaviors to the element, so it can work right? but in link function ,if I add these attribute without the compile this popover directive can't work
see my updated solution... I am curious to see if there is a way to get it compiled that quickly with the bindings intact.
yeah, I also curious, and I don't know the cost of the $compile function. if I add the popoverSetting directive to li element, of course li also have ng-repeate directive. when one item need add the popover attributes, after I called the $compile(element)(scope), what will happen? just compile current element? if the scope is root scope, what will happen?
You could compile it again, but i think it would be costly, especially for just updating one element.
Lots person had met this issue. Actually if there are more than 1000 records, it also cost not much time. but it cause infinite loop after call the compile function. so need to remove the directive from the element or determine whether need to compile again. here is the url stackoverflow.com/questions/21315312/…, it's useful
0

because I don't remove the directive so it makes the angular compile element over and over again. so i need to remove the directive or set a flat to determine if it is necessary to compile again.

function groupPopoverDirective($compile) {
    return {
        restrict: "A",
        scope:true,
        link: function ($scope, $element, $attrs) {

            $scope.groupPopoverData = $scope.$eval($attrs.groupPopoverData);

            if ($scope.groupPopoverData.isTrue) {
                if ($element.attr("ns-popover")) {
                    return;
                }

                $element.attr("ns-popover", "true");
                $element.attr("ns-popover-template", "popover-template.html");
                $element.attr("ns-popover-trigger", "mouseenter");
                $element.attr("ns-popover-placement", "right|top");
                $element.attr("ns-popover-mouse-relative", "x");
                $element.attr("ns-popover-theme", "ns-popover-tooltip-theme");
                $element.attr("ns-popover-timeout", "0.01");

                //element.removeAttr('popover-info');

                var linkFn = $compile($element);
                var pp = linkFn($scope);
            }
        }
    };
};

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.