0

I'm using angularjs and angular-ui-bootstrap to make a table and page some data, which I get from an API.

I've made sure my service receives the correct data and that the requests are built properly. My pageChange function is properly triggered and my first page gets loaded successfully.

So I have the following controller setup:

    (function () {
'use strict';


initContacts.$inject = ['$scope', '$http'];

angular.module('app')
    .config(function ($locationProvider) {
        $locationProvider.html5Mode(true);
    });

angular.module('app', ['ui.bootstrap']).controller('contactSearchController', initContacts);

function initContacts($scope, $http) {

    $scope.contacts = [];
    $scope.totalItems = 0;
    $scope.pages = 0;
    $scope.currentPage = 0;
    $scope.maxPageLinksShown = 5;

    if (window.location.hash !== '') {
        $scope.currentPage = window.location.hash.replace('#', '');
    }

    $http.get("/api/ContactApi/GetPage?pageIndex=" + ($scope.currentPage - 1)).success(function (data) {

        $scope.contacts = data.Contacts;
        $scope.totalItems = data.Count;
        $scope.PageSize = data.Contacts.length;
        $scope.pages = Math.ceil((data.Count / $scope.PageSize));

    });

    $scope.pageChanged = function () {
        $http.get("/api/ContactApi/GetPage?pageIndex=" + ($scope.currentPage - 1))
         .success(function (data) {
             $scope.contacts = data.Contacts;
         });
    };
}

}

})();

And in my view I have:

<div ng-app="app" ng-controller="contactSearchController">
<table class="table table-striped table-hover contact-search-table">
    <thead>
        <tr>
            <td class="contact-title">
                Titel
            </td>
            <td class="department">
                Afdeling
            </td>
            <td class="name">
                Navn
            </td>
            <td class="work-phone">
                Telefon
            </td>
            <td class="mobile">
                Mobile
            </td>
            <td class="email">
                Email
            </td>
        </tr>
    </thead>
    <tbody>
        <tr ng-repeat="(key, value) in contacts">
            <td class="contact-title">{{value.Title}}</td>
            <td class="department">{{value.Department}}</td>
            <td class="name">{{value.FullName}}</td>
            <td class="work-phone">{{value.WorkPhone}}</td>
            <td class="mobile">{{value.WorkMobile}}</td>
            <td class="email">{{value.Email}}</td>
        </tr>
    </tbody>
</table>
<div class="col-xs-12 pager-container">
    <ul uib-pagination total-items="totalItems" ng-model="currentPage" ng-change="pageChanged()" max-size="maxPageLinksShown" class="pagination-sm" boundary-links="true" num-pages="pages"></ul>
</div>

Now this works to some extent.

My problem

When I click the page links, the pageChanged() function is called, I get the data from my api and it's all correct, the list in the scope appears to be updated fine, but the table in my view doesn't change.

This solution works fine ONLY in IE ! (who would have thought huh...)

No exceptions get thrown.

I swear this was working yesterday.

Any help is much appreciated!

EDIT

What I've tried:

-Putting the assignment of the contacts in an $apply like so:

$scope.pageChanged = function () {
    $http.get("/api/ContactApi/GetPage?pageIndex=" + ($scope.currentPage - 1))
     .success(function (data) {                 
         $scope.$apply(function () {  // apply
              $scope.contacts = data.Contacts;
         });
     });
};

I got a "$digest already in progress" error from this.

  • tried to wrap the apply in a timeout like so:

    $timeout(function(){ //any code in here will automatically have an apply run afterwards });

Got rid of the error but the DOM still won't update.

Martin K
  • 346
  • 5
  • 15

3 Answers3

0

I had such a problem and I solved it using $scope.$apply:

$scope.pageChanged = function () {
        $http.get("/api/ContactApi/GetPage?pageIndex=" + ($scope.currentPage - 1))
         .success(function (data) {                 
             $scope.$apply(function () {  // apply
                  $scope.contacts = data.Contacts;
             });
         });
    };
Alex K
  • 2,613
  • 1
  • 20
  • 31
  • I tried that and got this error "$digest already in progress". Adding it to the question. – Martin K Sep 14 '16 at 12:01
  • You can try to use $timeout: $timeout(function(){ //any code in here will automatically have an apply run afterwards }); see good topic about digest already in progress here http://stackoverflow.com/questions/12729122/angularjs-prevent-error-digest-already-in-progress-when-calling-scope-apply – Alex K Sep 14 '16 at 12:35
  • I tried that too, I get rid of the error, but my DOM still won't update. – Martin K Sep 14 '16 at 12:50
0

You should use $scope.$applyAsync instead. It will be applied to the next digest cycle.

If you need to target all the $scopes of your AngularJS application, use $rootScope.$applyAsync instead.

Official doc

BabarConnect
  • 167
  • 6
0

Okay so what worked in this situation was changing the way I'm visualizing the ng-repeat like so:

<tr ng-repeat="contact in getContacts()">
            <td class="contact-title">{{contact.Title}}</td>
            <td class="department">{{contact.Department}}</td>
            <td class="name">{{contact.FullName}}</td>
            <td class="work-phone">{{contact.WorkPhone}}</td>
            <td class="mobile">{{contact.WorkMobile}}</td>
            <td class="email">{{contact.Email}}</td>
</tr>

And heres the getContacts() function:

  $scope.getContacts = function () {
        var data = $scope.contacts;
        if (data instanceof Array) {
            return data;
        } else {
            return [data];
        }
    }

I don't really know why that works, but it does.

Martin K
  • 346
  • 5
  • 15