I'm currently working on a project that will need to display editable tables of arbitrary dimensions. I'm using AngularJS, but as the tables can get very large I expect things will get slow if I don't use some form of bind-once. The problem is, as far as I can tell, bind-once is absolute -- I want it to actually keep or at least reinstate all the watchers for rows currently being edited.
Here's the basic idea of how I'm currently doing this.
<tr ng-repeat="row in rows track by key" hackonce>
<td ng-repeat="col in cols">
<div ng-click="editStuff()">{{contents}}
directive('hackonce', function() etc
link: function(scope, elem, attrs) {
if (!scope.row.editing)
setTimeout(function(){ scope.$destroy() }, 0)
}
I'm generating a string key on the row from its various identifiers. When the item is flagged for editing, the controller switches it out for a copy and changes its key to include what will eventually be transaction lock data. This triggers a replacement in the ng-repeat, and the next time the tr is constructed with the replaced row data, the scope is left intact and updates as you edit stuff.
Somehow, it actually works (so far anyway). It drops me from over 500 watchers on a small list to under 100, and what remains is mostly top-level controls, so I hope it will scale well. It also seems to retain and properly clean up ng-click listeners and such even though the scope is gone.
However, it's the sort of hack that I cringed just typing it out in brief, and I get the feeling it may induce vomiting in sane people who know this library better than I do. I was wondering if there was a cleaner and/or safer way to do the same thing. What I'm looking for is a better way to conditionally bind once, or have an element/scope otherwise skip its $digest for itself and all its children based on some exposed flag.
Is there any way to do this that doesn't involve taking a meat cleaver to the scope or manually reattaching all the jQuery garbage I was hoping to avoid with Angular?