0

Colleagues, in the directive trying to get descendants. The question is, if the descendants of the parent are added via ng-repeat, then element.children () returns an empty array.

But if I request through setTimeout () I achieve the desired result

const app = angular.module('app', []);

app.directive('example', function() {
  return {
    restrict: "C",
    link: function(scope, element, attrs) {
      scope.myExample = ['Example-1', 'Example-2', 'Example-3', 'Example-4', 'Example-5'];
      setTimeout(() => {
        console.log("TCL: element", element.children());
      }, 0)
    }
  }
});

app.directive('rootElement', function() {
  return {
    restrict: "ECA",
    //templateUrl: './pages/page-main/index.html',
    template: '<header>header</header><main>main</main><footer>footer</footer>',
    link: function(scope, element, attr) {
      console.log("rootElement", element.children());


    }
  }
});
<html ng-app="app">
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.8/angular.min.js"></script>
<menu class="example">
  <li class="li-example" ng-repeat="example in myExample"
      ng-click="active = !active" ng-class="active ? '' : 'li-example-active'">
     <span>{{example}}</span>
  </li>
</menu>
<hr/>
<root-element></root-element>
<html>

Question - Is the correct decision to use setTimeout () or is there a more elegant and correct solution?

georgeawg
  • 48,608
  • 13
  • 72
  • 95
Air
  • 181
  • 3
  • 15
  • Why does the code use a class (`restrict: 'C'`) directive to initialize scope data? The structured best practice is to use a controller. – georgeawg May 15 '19 at 13:17
  • @georgeawg, Thanks for the advice. I will take this into account, but I also tried to implement it through `controller`, and it also doesn’t work without `setTimeout ()`. – Air May 15 '19 at 13:27
  • @georgeawg, Is this the right solution to use setTimeout ()? – Air May 15 '19 at 13:28
  • This is typically how directives have to be coded when you need to access other elements in the view because the DOM has not necessarily completely rendered when the link function is called. However, I would switch to using `$timeout` with no delay parameter since that is the AngularJS version of javascript's `setTimeout`. See [this question](https://stackoverflow.com/q/11125078/548997) for more details. – Lex May 15 '19 at 13:56
  • Using `$timeout` or `setTimeout` is not the best choice in this situation because if you intend more DOM manipulation users are likely to see unpleasant flickering. I am reluctant to write an answer because of your choice to do both model manipulation and DOM manipulation in a class (`"C"`) directive. The AngularJS framework is a [MVCish](https://en.wikipedia.org/wiki/Model–view–controller) framework. Hiding Model and DOM manipulation in a class is jQuery mentality. AngularJS uses a declarative style with visible (not hidden) directives in the HTML. – georgeawg May 15 '19 at 14:16

0 Answers0