1

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?

Waypoint
  • 11
  • 2
  • Have you checked [angular-once](https://github.com/tadeuszwojcik/angular-once)? Even if it doesn't suit your needs entirely, you can learn from how it works. – Estus Flask Mar 24 '15 at 01:30

1 Answers1

1

It's kind of difficult without more implementation detail, but I'm assuming that you're using some mechanism to show/hide the read-only/editable elements for each row? If you use ng-if to do it, it will attach the elements to the DOM and re-bind when the condition is true and detach when false.

So, something like:

<td ng-repeat="col in cols">
  <span ng-if="!isEditing(row)">Read-only stuff here</span>
  <span ng-if="isEditing(row)">Editable stuff here.</span>
</td>

I created a really simple example plunk here: http://plnkr.co/edit/SkdgTuK5UvEEsZmzWat6?p=preview

ach
  • 6,164
  • 1
  • 25
  • 28