From what I have seen with Angular 2.0, I have a feeling I am going to be using Angular 1.x for a while. It has all the building blocks that I think I need, the only downside is that it does have performance issue with dirty checking so I am trying to think about that more. Now ng-repeat can be an issue because of the number of watchers it adds.
So I have this part of a template (in jade):
li(ng-repeat='topMenuItem in sideMenu.topMenu', ng-class='{"is-active": topMenuItem.display === sideMenu.activeTopMenu}')
a(href='{{ topMenuItem.href }}') {{ topMenuItem.display }}
ul(ng-if='sideMenu.secondMenu.length > 0 && topMenuItem.display === sideMenu.activeTopMenu')
li(ng-repeat='secondMenuItem in sideMenu.secondMenu', ng-class='{"is-active": secondMenuItem.display === sideMenu.activeSecondMenu}')
a(href='{{ secondMenuItem.href }}') {{ secondMenuItem.display }}
When this displays 22 menu items the number of watchers is 90 (using this bookmark snippet).
I decided to play around with trying to use $interpolate to generate that menu. I ended up with a directive with this for the compile function:
compile: function(element, attributes) {
var topLevelExpression = $interpolate('<li{{ cssClass }}><a href="{{ topMenuItem.href }}">{{ topMenuItem.display }}</a>{{ secondLevelMenuHtml }}</li>');
var secondLevelExpression = $interpolate('<li{{ cssClass }}><a href="{{ secondMenuItem.href }}">{{ secondMenuItem.display }}</a></li>');
var updateMenu = function() {
var html = '';
sideMenu.topMenu.forEach(function(topMenuItem) {
var cssClass = topMenuItem.display === sideMenu.activeTopMenu ? ' class="is-active"': '';
var secondLevelMenuHtml = '';
if(sideMenu.secondMenu.length > 0 && topMenuItem.display === sideMenu.activeTopMenu) {
secondLevelMenuHtml += '<ul>';
sideMenu.secondMenu.forEach(function(secondMenuItem) {
var cssClass = secondMenuItem.display === sideMenu.activeSecondMenu ? ' class="is-active"': '';
secondLevelMenuHtml += secondLevelExpression({
secondMenuItem: secondMenuItem,
cssClass: cssClass,
});
});
secondLevelMenuHtml += '</ul>';
}
html += topLevelExpression({
topMenuItem: topMenuItem,
cssClass: cssClass,
secondLevelMenuHtml: secondLevelMenuHtml
});
});
element.find('.application-navigation').html(html);
};
return function($scope) {
$scope.$watchCollection('sideMenu', function() {
updateMenu();
});
}
}
From my testing, this code functions exactly the same as the ng-repeat, the output look as it should. This version only has 16 watchers and that number does not increase when more elements are shown where the ng-repeat does.
Since this code is only doing the bare minimum that is needed for this piece of code to work, I imagine the javascript itself is just as efficient (if not more efficient) than the code that executes for ng-repeat.
Is that assumption correct?
Are there any issues with doing looping DOM generation in this way vs using ng-repeat?