0

When page is loading first time, I'm getting my thingsList filled. But then I need choose option with ng-click, it triggers function doSomething() which is getting new thingsList. I can see at debug mode that there is a new list, but there's no binding and datatables still showing me the old thingsList.

I'd really like to solve this without dtOptions is it's possible.

I'm using pretty simple "angular way" with datatables:

<tr ng-repeat="thing in thingsList">
   <td>{{thing.id}}</td>
   <td>{{thing.name}}</td>
</tr>

and my controller looks like:

.controller('ThingsController', ['$http', '$scope', function ($http, $scope) {

    this.getThing = function () {
        $http.get(....).then(
            function success(response) {
                $scope.thingsList = response.data;
            },
            function error(data) {
                console.log(data);
            }
        );
    };

    this.getThings();


    this.doSomething = function (id) {
        $http.get(....).then(
            function success(response) {
                $scope.thingsList = response.data;
            },
            function error(data) {
                console.log(data);
            }
        );
    };

}]);
ottercoder
  • 852
  • 1
  • 12
  • 31

2 Answers2

2

Try using

$scope.thingsList.splice(0);   // clears the array without losing reference
Array.prototype.push.apply($scope.thingsList, response.data); // inserts new data to existing array

instead of $scope.thingsList = response.data; in doSomething function.

PJDev
  • 951
  • 5
  • 20
  • well, as I said I get a new `thingsList` array when ng-click triggers the function. But it's not binding to the datatable. But thanks anyway. – ottercoder Jul 06 '16 at 07:42
  • I thought your problem might be actually connected with **replacing** `$scope.thingsList` with a new array. Although you can see new data in debugger, it doesn't mean that view knows about the change. It might still be referenced to the old array. My solution ensures that reference to the array doesn't change - only the data inside it is updated. – PJDev Jul 06 '16 at 10:14
  • ok, used your solution and put `getThings` to ng-init. Now it works – ottercoder Jul 06 '16 at 10:36
  • Personally, I don't like the use of `ng-init` in this way. Also, Angular documentation advices against it as someone mentioned in comments in the link provided by Vishal Rao. I find a private `initialize` function declared and executed at the bottom of the controller more readable. But it's a matter of taste I guess :-) I'm glad I could help a bit. – PJDev Jul 06 '16 at 10:45
1

So I'm guessing the reason its happening is because the getThings() function is being called every time the controller is used. You might want to modify your controller code in this way and try:

.controller('ThingsController', ['$http', '$scope', function ($http, $scope) {

$scope.getThing = function () {
    $http.get(....).then(
        function success(response) {
            $scope.thingsList = response.data;
        },
        function error(data) {
            console.log(data);
        }
    );
};


$scope.doSomething = function (id) {
    $http.get(....).then(
        function success(response) {
            $scope.thingsList = response.data;
        },
        function error(data) {
            console.log(data);
        }
    );
};

}]);

Now this will solve your problem of the list not updating when you choose your option with ng-click but your list won't get loaded by default when you load the page since getThings() isn't being called.

My suggestion for that would be to use use ng-init as described in the answer to this question: How to execute angular controller function on page load?

or better yet use $scope.on in this manner in your code:

.controller('ThingsController', ['$http', '$scope', function ($http, $scope) {

$scope.getThing = function () {
    $http.get(....).then(
        function success(response) {
            $scope.thingsList = response.data;
        },
        function error(data) {
            console.log(data);
        }
    );
};

$scope.$on('$viewContentLoaded', function() {
   $scope.getThing();
})

$scope.doSomething = function (id) {
    $http.get(....).then(
        function success(response) {
            $scope.thingsList = response.data;
        },
        function error(data) {
            console.log(data);
        }
    );
};

}]);

In case you're using routing you can change the '$viewContentLoaded' to '$routeChangeSuccess' for ng-route or '$stateChangeSuccess' if you're using ui-router. (Don't worry about this unless you're using routes to change views)

Community
  • 1
  • 1
Vishal Rao
  • 872
  • 1
  • 7
  • 18
  • there's a lot of things. But put `getThings` to `ng-init` really helped, thanks. One thing I don't understand, in debug mode (F12) I don't see any calls of `getThings` after init of Controller anyway. What did it change actually? – ottercoder Jul 06 '16 at 08:18
  • One easy way to find out if it was actually calling it multiple times is just placing a console.log() inside the function so you can see how many times it was called. I suggest you try that and see if the statement inside the log is printed every time you trigger the ng-click. – Vishal Rao Jul 06 '16 at 14:29