javascriptangularjsangularjs-directiveangularjs-ng-repeatangularjs-compile

How to use ng-bind on html that is inserted with innerHTML inside a directive


I made a custom directive that had two ng-repeats inside of it. One ng-repeat was nested inside the other one. I got the code to work, and it performs well in chrome but on the iPad and iPhone it is sluggish.

There are 10 sections with 5 rows each and it needs to be very fast when it comes to scrolling and changing the bindings. I think the slowdown comes from all the loops through the bindings but only one array needs to be changed on user input. The rest of the bindings never change after the page loads.

So I am trying to figure out a way to load nested unordered lists while only binding one variable. This is pseudo code for my directive.

.directive('myDirective', function($compile) {
  return {
    restrict: 'A'
    link: function(scope, elm, attrs) {
      outerList = '<ul><li>statically generated content that does not change'
      outerList += '<ul><li ng-bind="I only need to bind one thing"><li></ul>'
      outerList += < /ul>'
      elm[0].innerHTML = outerList
    }
  }
});

As you can see I am trying to generate the html content, and then insert it with innerHTML. The problem is the ng-bind isn't working when I do it this way. I tried to $compile it again but that didn't change anything.

Does anyone have a better way? I don't care how hideous the solution is I just really need this part of the app to be super fast. The main thing is I don't want ng-repeat unless there is a way to make it do its thing on load and then never loop through anything again.

I would like to do this in the most Angular way possible but I realize I might have to do something that goes completely against Angular philosophy


Solution

  • Here is an example of how to modify your code in order to bind some variable in a directive from a scope outside of it. I've used $compile to ensure that your directive DOM manipulation has its own directives compiled. I've used replaceWith to replace the directive element with your compiled DOM:

    HTML

    <div ng-app="myApp">
        <div ng-controller="ctrlMain">
            <div my-directive="bindMe"></div>
        </div>
    </div>
    

    JavaScript

    var app = angular.module('myApp',[]);
    app.controller('ctrlMain',function($scope){
        $scope.bindMe = {id:1,myvar:"test"};
    });
    app.directive('myDirective', function($compile){
      return{
        restrict: 'A',
        scope: {
            varToBind: '=myDirective'     
        },
        link: function(scope, elm, attrs){
          outerList = '<ul><li>statically generated content that does not change'
          outerList += '<ul><li ng-bind="varToBind.myvar"><li></ul>'
          outerList += '</ul>';
          outerList = $compile(outerList)(scope);
          elm.replaceWith(outerList);
        }
      }
    });
    

    Here is a demo