0

I can't seem to work out how to redraw my Angular-Datatable after I delete a record from my database. I don't get any errors, but the table never seems to redraw unless I manually refresh the page. I have been trying to work with many examples from the website documentation.

I have my datatable:

            $scope.dtInstance = {};
            $scope.selectedItems = [];
            $scope.toggleItem = toggleItem;
            $scope.reloadData = reloadData;

            // Build the User table
            $scope.dtOptions = DTOptionsBuilder
                .fromFnPromise(function() {
                    var deferred = $q.defer();
                    deferred.resolve(users); 
                    return deferred.promise;
                })
                .withBootstrap() // Style with Bootstrap
                .withOption('responsive', true) 
                .withDisplayLength(15) // Show 15 items initially
                .withOption('order', [0, 'asc']) // Sort by the first column
                .withOption('lengthMenu', [15, 50, 100]) // Set the length menu items
                .withOption('createdRow', function(row, data, dataIndex) {
                    // Recompiling so we can bind Angular directive to the DT
                    $compile(angular.element(row).contents())($scope);
                })
                .withOption('headerCallback', function(header) {
                    if (!$scope.headerCompiled) {
                        // Use this headerCompiled field to only compile header once
                        $scope.headerCompiled = true;
                        $compile(angular.element(header).contents())($scope);
                    }
                })              
                .withOption('fnRowCallback', formatCell);
            $scope.dtColumns = [
                DTColumnBuilder.newColumn(null).withTitle('Username').withClass('col-md-2').renderWith(createUsernameHyperlink), 
                DTColumnBuilder.newColumn('Email').withTitle('Email'), 
                DTColumnBuilder.newColumn('Level').withTitle('Role').withClass('col-md-2'),
                DTColumnBuilder.newColumn('LastConnected').withTitle('Last Accessed'), 
                DTColumnBuilder.newColumn('Verified').withTitle('Account Verified').withClass('col-md-2'), 
                DTColumnBuilder.newColumn(null).withTitle('')
                    .notSortable()
                    .renderWith(function(data, type, full, meta) {
                        return '<input type="checkbox" ng-click="toggleItem(' + data.Id + ')" />';
                    }).withClass("text-center")     
            ];

        // Reload the datatable
        function reloadData() {

            var resetPaging = false;
            $scope.dtInstance.reloadData(callback, resetPaging);

        };  

        function callback(json) {
            console.log(json);
        };

And then I have my delete function that sits in the same controller. Calling reloadData() on a successful response from the service. I can see from the console.log that it is calling the function correctly, but nothing happens.

$scope.deleteUser = function( selectedItems ) {

            swal({
                title: 'Are you sure?', 
                text: 'Are you sure you want to delete the selected account profile(s)? This process cannot be undone...', 
                type: 'warning', 
                showCancelButton: true, 
                confirmButtonText: 'Delete', 
                confirmButtonColor: "#DD6B55", 
                closeOnConfirm: false, 
                allowEscapeKey: true, 
                showLoaderOnConfirm: true
            }, function() {

                setTimeout( function() {

                    // Delete user
                    UsersService.deleteUser( selectedItems.toString() )
                        .then(function( data ) {
                            // Show a success modal
                            swal({
                                title: 'Success', 
                                text: 'User has been deleted!', 
                                type: 'success', 
                                confirmButtonText: 'Close', 
                                allowEscapeKey: false
                            }, function() {

                                reloadData(); //<== Calls the function but doesn't do anything
                                //$state.go('users');

                            });
                        }, function() {
                            // Show an error modal
                            swal({
                                title: 'Oops', 
                                text: 'Something went wrong!', 
                                type: 'error', 
                                confirmButtonText: 'Close', 
                                allowEscapeKey: true
                            });
                        }); 

                }, 1000);   

            });

        };

Just wondering if I have missed some step?

Riples
  • 1,167
  • 2
  • 21
  • 54

2 Answers2

4

As suggested by @davidkonrad in a previous comment and more so from the Angular-Datatable's author, I was not reloading my content when attempting to redraw my table. Even though I was referencing my data (users) from an injected service, it was never getting updated within the controller and so my table content was never differing.

The author suggested that it is preferable to load the data from a promise that makes a HTTP request, thus allowing further calls to the promise each time the table redraws.

So instead of this:

// Build the User table
            $scope.dtOptions = DTOptionsBuilder
                .fromFnPromise(function() {
                    var deferred = $q.defer();
                    deferred.resolve(users); 
                    return deferred.promise;
                })
                .withBootstrap() // Style with Bootstrap

I changed it to this:

// Build the User table
            $scope.dtOptions = DTOptionsBuilder
                .fromFnPromise(function() {
                    return UsersService.getUsers();
                })
                .withBootstrap() // Style with Bootstrap

Which now updates my table fine upon each redraw event with a call to $scope.dtInstance.reloadData();

My Github post can be found here

Riples
  • 1,167
  • 2
  • 21
  • 54
0

setTimeout function works from outside of the angular digest cycle since it's async. If you want actions you take inside a timeout to apply to the angular digest cycle you should use $timeout instead.

Another option is to use $scope.apply(), but this will just mimic the $timeout function.

Please note that you'll need to inject $timeout to your controller.

Asaf David
  • 3,167
  • 2
  • 22
  • 38
  • Do I put this inside the `deleteUser()` function or the `reloadData()` function? – Riples May 05 '16 at 11:30
  • Just replace your setTimeout function with $timeout. You can read about it here - https://docs.angularjs.org/api/ng/service/$timeout – Asaf David May 05 '16 at 11:32
  • I have tried adding both a `$timeout` to my `deleteUser()` method and a `$scope.apply()` to the `reloadData()` method and nothing seems to change. However, I can see that the checkbox against my deleted item clears after a second so the `$timeout` seems to be working. Just not reloading the data. Is there something else wrong maybe? – Riples May 05 '16 at 11:42
  • can you add a JSFiddle? – Asaf David May 05 '16 at 11:43
  • Sorry for the delay, but I have never worked with JSFiddle and seem to be having some issues getting one working correctly. – Riples May 06 '16 at 03:04