ng-grid not binding with latest data after async XMLHttpRequest's response

Viewed 131

I have a AngularJS web application, I'm trying to upload a file to a server and while the upload is complete, I have to update ng-grid with the last uploaded file's entry. The following is my grid html,

<div class="gridholder" data-ng-grid="viewmodel.gridOptions">                
            </div>

The following is my controller logic.

vm.gridOptions = {
            data: 'gridData',            
            enableColumnResize: true,            
            enablePaging: true,
            columnDefs: [
                { field: 'FileName', displayName: 'File Name', width: 250 }
                { field: 'UploadedDate', displayName: 'Uploaded Date'}
            ],
            multiSelect: false,
            enableSorting: true,
            showFooter: true,
        };

The requirement is that I show the progress of file upload and the entire application to be responsive when upload is in progress, I have achieved this but my ng-grid not is updating in a particular scenario.

If I remain in the same page until the file is uploaded and the response comes, the grid is refreshing but when I move to another page of my application and come back to the file upload page, and the response comes after, my grid is not getting refreshed.

This is my file upload js code,

var data = new FormData();
data.append('file', file);
var xhrRequest = Factory.uploadFileRequest('UploadFile');
xhrRequest.upload.addEventListener("progress", progressHandler, false);                

xhrRequest.onreadystatechange = function (e) {
};

xhrRequest.onload = function (e) {
    if (JSON.parse(e.currentTarget.responseText).Success == true) {
        $timeout(function () {
            $scope.LoadGrid();
            //showing success message here
        }, 2000);
    }
    else
    {
        //showing error message here                    
    }

};
xhrRequest.onerror = function (e) {                    
   //showing error message here                 
};
xhrRequest.send(data);

$scope.LoadGrid = function () {            
    Factory.callGet("Files").then(function (d) {

            $scope.gridData = d.data;
        }               
        $scope.totalItems = $scope.gridData.length;
    }, function error(err) {
        //Error Message
    });
}

gridData is my data-ng-grid value. I'm calling my LoadGrid method inside a $timeout already but still the grid is not refreshing with latest data. Any help would be much appreciated.

1 Answers

Possible Problem

You implemented upload logic inside the controller. When you switch to another view, angularjs destroys your controller and therefore no one listens on file upload response.

Possible solution:

1) Use a service (or Factory) kind of singleton to manage upload process there.
For example MyService.upload(data).then(function (response) {/**/});

2) By default MyService.upload(data) returns a promise on a regular basis but also stores the result inside the Service, for example, upload_results:

app.service('MyService',['$q',function ($q) {

    var self = this;

    var upload_results = [];

    self.upload = function (_data) {
        return // <YOUR_PROMISE> 
          .then(function (response) {

              upload_results.push({
                    id: new Date().getTime(), 
                    data: response.data
               })              
            }
            , function (error) {
              console.error(error);
              return $q.reject(error);
            });
      };

    self.getResults() = function(){
      return upload_results;
    }

    self.resetResults() = function(){
      upload_results = [];
    }
}

When you initialize the controller on start or go back to the previous controller, you ask the service if it has something for you:

   var results = MyService.getResults();

   if(results.length > 0){
    $scope.gridData = results[0].data; // or use timestamp to manage it
    MyService.resetResults();
   }

Hope it will give you some insight,

Related