0

I need a small help in angularjs, please have a look on this code (chrome browser):

http://jsfiddle.net/Aravind00kumar/CrJn3/

<div ng-controller="mainCtrl">
    <ul id="names">
        <li ng-repeat="item in Items track by $index">{{item.name}} </li>
    </ul>

    <ak-test items="Items">

    </ak-test>
</br>
    <div id="result">

    </div>
</div>


    var app = angular.module("app",[]);
    app.controller("mainCtrl",["$scope",function($scope){
        $scope.Items = [
            {name:"Aravind",company:"foo"},
            {name:"Andy",company:"ts"},
            {name:"Lori",company:"ts"},
            {name:"Royce",company:"ts"},
        ];
        $scope.Title = "Main";

    }]);

app.directive("akTest",["$compile",function($compile){
    return {
        restrict: 'E',
        replace: true,
        scope: {
            items: "="
        },
        link: function (scope, element, attrs) {
//            var e =$compile('<li ng-repeat="item in Items track by $index">{{item.name}} </li>')(scope);
//            $("#names").append(e);

            var lilength = $("#names li").length;
            var html ='<div> from angular ak-test directive: '+lilength+'</div>';
            element.replaceWith(html);
        }
    };
}]);
        $(function(){
            $("#result").html('from jquery:  '+$("#names li").length);
        });

I have created a custom directive and trying to access an element from the view which in the ng-repeat above my custom directive The problem is, in the directive it was saying ng-repeat not rendered yet. Here is the problem I have two elements

<svg>
<g>
List of elements
</g>
<g>

Based on the above rendered elements I have to draw a line between elements like a connection. I have to wait till the above elements to get render then only I can read the x,y positions and can draw a line.
</g>
</svg>   

Both elements and the connections are scope variables. As per my understanding both are in the same scope and execution flow starts from parent to child and finishes from child to parent. How can I force above ng-repeat rendering part to complete before starting the custom directive?

is there any alternative available in angular to solve this dependency?

3 Answers3

0

It's been a while, so my Angular is getting a bit rusty. But if I understand your problem correctly, it's one that I have run into a few times. It seems that you want to delay processing some elements of your markup until others have fully rendered. You have a few options for doing this:

You can use timeouts to wait for the page to render:

$timeout(function() {
    // do some work here after page loads
}, 0);

This generally works ok, but can cause your page to flash unpleasantly.

You can have some of your code render in a later digest cycle using $evalAsync:

There is a good post on that topic here: AngularJS : $evalAsync vs $timeout. Typically, I prefer this option as it does not suffer from the same page flashing issue.

Alternatively, you can look for ways to refactor your directives so that the dependent parts are not so isolated. Whether that option would help depends a lot on the larger context of your application and how reusable you want these parts to be.

Hope that helps!

Community
  • 1
  • 1
Royce
  • 53
  • 6
0

I would create a directive for the whole list, and maybe a nested directive for each list item. That would give you more control I would think.

Lori
  • 1
0

Thanks a lot for your quick response #Royce and #Lori

I found this problem causing because of ng-repeat I have solved it in the following way..

  1. Created a custom directive for list elements and rendered all elements in a for loop before the other directive start. This fix solved the problem temporarily but i'll try the $evalAsync and $timeout too :)

        var app = angular.module("app",[]);
    app.controller("mainCtrl",["$scope",function($scope){
    $scope.Items = [
        {name:"Aravind",company:"foo"},
        {name:"Andy",company:"ts"},
        {name:"Lori",company:"ts"},
        {name:"Royce",company:"ts"},
    ];
    $scope.Title = "Main";
    
    }]);
    
    app.directive("akList",["$compile",function($compile){
    return {
    restrict: 'A',
    replace : false, 
    link: function (scope, element, attrs) {
      var _renderListItems = function(){
        $(element).empty();  
        for(var i=0;i<scope.Items.length; i++)
          {
            var li ='<li> '+ scope.Items[i].name +' </li>';
           element.append(li);
          }
        };
      _renderListItems(scope);
      scope.$watch('Items.length', function (o, n) {
            _renderListItems(scope);
        }, true);
    }};}]);
    
    app.directive("akTest",["$compile",function($compile){
    return {
    restrict: 'E',
    replace: true,
    scope: {
        items: "="
    },
    link: function (scope, element, attrs) {
        var lilength = $("#names li").length;
        var html ='<div> from angular ak-test directive: '+lilength+'</div>';
        element.replaceWith(html);
    }
    };
    }]);
    $(function(){
        $("#result").html('from jquery:  '+$("#names li").length);
    });
    
Community
  • 1
  • 1