Search code examples
angularjsngtableangular-promise

AngularJS reloading ngTable from ng-change event


I am populating ngTable using the following which works fine:

      $scope.data = ClientService.query(
        {
            state: $scope.currentStateId,
            parentId: $scope.parentId
        });

    $scope.data.$promise.then(function (data) {
        $scope.tableParams = new ngTableParams(
            {
                page: 1,                        // show first page
                count: $scope.pageCount,        // count per page
                sorting: { Name: 'asc' },
                filter: { Name: ''}
            },
            {
                total: data.length,
                getData: function ($defer, params) {
                    var orderedData = params.filter() ? $filter('filter')(data, params.filter()) : data;
                    orderedData = params.sorting() ? $filter('orderBy')(orderedData, params.orderBy()) : orderedData;
                    params.total(orderedData.length); // set total for recalc pagination

                    $scope.accounts = orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count());
                    $defer.resolve($scope.accounts);
                }
            });
    });

I now wish to update the ngTable from an ng-change event which sets a new $scope.currentStateId as follows:

 $scope.stateChange = function () {
        //$state.go('root.account.clients.list', { state: $scope.currentStateId, parentId : $scope.parentId }, { reload : true })
        //var sel = $scope.currentStateId;
        $scope.data = ClientService.query(
            {
                state: $scope.currentStateId,
                parentId: $scope.parentId
            });
       $scope.tableParams.reload();
    };

The ClientService.query hits the server with the correct parameters and returns the correct data but the ngTable is not updated.

Can someone please help.


Solution

  • Update (correct answer)

    Promises, by design, can be resolved only once. As a result, nesting new ngTableParams inside of $scope.data.$promise.then(function (data) { limits your ability to update the data at a later point.

    Instead, put the callback inside of the getData function so that you can reset $scope.data with a new promise before calling $scope.tableParams.reload():

    $scope.data = ClientService.query({
        ...
    });
    
    $scope.tableParams = new ngTableParams({                     
        ...
        getData: function ($defer, params) {
            $scope.data.$promise.then(function (data) {
                var orderedData = params.filter() ? $filter('filter')(data, params.filter()) : data;
                ...
                $defer.resolve($scope.accounts);
            });
        }
    });
    
    $scope.stateChange = function () {    
        $scope.data = ClientService.query({
            ...
        });
    
        $scope.tableParams.reload();
    };
    

    Previous Answer (incorrect)

    You have a synchronous function call (your ngTable update) following an asynchronous call (the ClientService query). So, the table update executes before the data comes back.

    Wrap the table update call in callback that fires once the promise is resolved:

    $scope.data = ClientService.query(
    {
        state: $scope.currentStateId,
        parentId: $scope.parentId
    });
    
    $scope.data.$promise.then(function (data) {
        $scope.tableParams.reload();
    };