angularjsangularjs-ng-repeatbrowser-refreshangularjs-timeout

AngularJS $timeout sometimes works sometimes doesn't


I'm experiencing some problems with AngularJS and $timeout.
I need to run some code, after the page is loaded. Http.get() loads items and ng-repeat displays them in table. Then I need to run the code to highlight row when I click it.

I found a solution for that using $timeout.

$timeout(function () {
    console.log('in timeout');
    $scope.highlightRows();
});

this does work, but not every time. In the function I log number of rows in the table and sometimes I get 0, therefore the click handler is not registered and it highlighting doesnt work.

$scope.highlightRows = function () {
    console.log($("#tripsTable").children("tbody").children("tr").length);
    $("#tripsTable").children("tbody").children("tr").children().click(function () {
        console.log('row click');
        $("#tripsTable").children("tbody").children("tr").removeClass("focusedRow");
        $(this.parentNode).addClass("focusedRow");
    });
};

when try to simulate I have to refresh by Ctrl + F5.

console log:

in timeout tripsController.js:14
0 

I couldn't find any solutions to this problem, any suggestions will be appreciated :)
Thanks
Mark

EDIT: this is my HTML

<table class="table table-bordered" id="tripsTable">@*table-hover*@
    <thead>
        ....
    </thead>
    <tbody>
        <tr ng-repeat="trip in tripsVM.tripsList | orderBy: 'startDate'" ng-class="(trip.tripID == 0) ? 'newRow' : ''" class="row">
            ....

Solution

  • This looks like a timing issue. As you are not providing a duration parameter to the $timeout function it is executing straight away. This might be executing before the ng-repeat has finished rendering the data so nothing appears to be happening. As a test you could try adding a large delay to the $timeout function to see if that makes a difference. If it does you will then need to think of a way of triggering this once you know the items have been displayed.

    $timeout(function () {
        console.log('in timeout');
        $scope.highlightRows();
    }, 2000);
    

    Also I would strongly advise you don't do any JQuery in your controller - in fact I strongly advise you don't use JQuery at all!

    You could do all of this logic simply using angular directives such as ng-click & ng-class.

    <table><tbody><tr ng-repeat="item in items" ng-click="selectItem(item)" ng-class={'focusedRow': item === selectedItem}"><td>{{item.Name}}</td></tr></tbody></table>
    

    Then in your controller have the selectItem method

    $scope.selectItem = function (item) {
        $scope.selectedItem = item;
    }