0

I have a huge table of data displayed with AngularJS (1.7.x). The amount and complexity of data dictated that the data is bound-once inside an ng-repeat like this:

<div ng-repeat="item in [{...}, {...}, ...] track by $index">
  <div>{{ ::item.col1 }}</div>
  <div>{{ ::item.col2 }}</div>
  ...
  <div>{{ ::item.colx }}</div>
</div>

The problem comes when I try to update some cells, say, column 5 in row 233. It is done by dynamically recompiling and reinserting the very same HTML markup into the right DOM node but I just cannot find a way to get it compiled within the current context.

I followed Angularjs: Compile ng-repeat dynamically but I just cannot reproduce the "recompile" effect. Everything is evaluated with the scope I provide at $compile() which, obviously, cannot see "item" from the ng-repeat.

Edit: I formatted the HTML above a bit and added some sample code. I did not include it in the original post as I feared it's far from how it should be done but you are right, it may provide you more insight.

Directive (taken from the directive mentioned in the linked answer):

app.directive('recompile', function ($compile) {
  return {
    restrict: 'A',
    compile: function (element) {
      element.removeAttr('recompile');
      var compile = $compile(element);
      return function (scope, element) {
        compile(scope);
      }
    }
  }
});

Code that tries to make AngularJS rebind a cell:

// by now, column 5 of row 233 got removed from DOM
// $prevnode points column 4 of row 233
var nodest = '<div recompile>{{ ::item.col5 }}</div>';
var comp = $compile(nodest)($scope);
$prevnode.after(comp);

The result is always an empty cell as "item" resolves to undefined. No matter if I use the "recompile" directive or not. $scope variables are resolved fine.

1
  • What does your angular code look like? Commented Mar 16, 2020 at 13:46

1 Answer 1

2

Finally, I managed to solve my problem. For some reason, I did not know I can access the current scope by DOM using angular.element(...).scope()! No directive or other trickery needed, it's this simple:

// get current item's $scope
var $itemscope = $prevnode.scope();
var nodest = '<div>{{ ::item.col5 }}</div>';
// compile with the said scope
var comp = $compile(nodest)($itemscope);
$prevnode.after(comp);

item is correctly resolved now and the cell reflects the value that has been changed in the datasource of the ng-repeat.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for posting your solution, this will help in case some other folks are stumbling into the same issue. Welcome to SO ! This is the right mindset !

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.