Muhammad Fawwaz Orabi
Muhammad Fawwaz Orabi

Reputation: 853

Angular: How to compile a template in a directive and then remove watches

I have an array of objects like this:

{
  text: 'Some text',
  translations: ['translation1', 'translation2'],
  direction: 'ltr'
}

I need to render the text and all the translation. Currently I'm looping through the array using an ng-repeat directive which of course creates some watches for each property bound to the $scope, the translations array is also rendered using an ng-repeat. So my ng-view is something like this:

 <div ng-repeat='result in results'>
    {{ result.text }}
    <li ng-repeat='translation in result.translations'>{{ translation }}</li>
 </div>

Actually, this is a simplified version of what I'm rendering. The real subarray also has objects (not strings)... So there are too many watches created that I do not need because my data never changes during the $scope lifecycle. Debugging the app using Angular Batarang shows that the performance is seriously affected by those watches.

I think if I could compile the template using a custom directive and remove the watches the app would perform much better. My question is should I do that and how to do it? Is there a better way to handle this case?

Upvotes: 1

Views: 191

Answers (1)

Problematic
Problematic

Reputation: 17678

If the values that you are binding to in your template do not change, you can try a library like bindonce, which performs a one-off binding.

If you'd like to accomplish this without using a 3rd-party library, you could create a directive whose link function parses an attribute value and sets the element text, no watches required. Something like this:

module.directive('once', function ($parse) {
    return {
        link: function (scope, el, attrs) {
            var deregister = attrs.$observe('once', function (once) {
                if (once === undefined) { return; }
                el.html($parse(once)(scope));
                deregister();
            });
        }
    };
});

Then you'd use it like so:

<span once="model.property"></span>

The html content of the span would be set to whatever model.property evaluates to on your current scope.

Upvotes: 1

Related Questions