1

So I have an external API which I'm trying to access and extract the data in it using JSONP and $resource service. I want to have a button from ngCsv which makes the request then when the data request completed exports the array to a csv file. but when I click the button it saves an empty csv file because the request takes about 11s to complete. I want to click the button and when the data was ready and received completely, export the csv file.

Here's my app.js

// Initializing Application
angular.module('angelApp',['ngRoute','ngResource','ngSanitize','ngCsv'])

.config(function ($locationProvider,$routeProvider) {
  $locationProvider
  .html5Mode({
    enabled: true,
    requireBase:false
  })
  .hashPrefix('!');
  $routeProvider
  .when('/',{
    templateUrl: 'displays/main.html',
    controller: 'mainController'
  })
  .when('/extract',{
    templateUrl: 'displays/extract.html',
    controller: 'extractController'
  })
  .when('/about',{
    templateUrl: 'displays/about.html',
  })
  .otherwise({redirectTo: '/'});
})

// Defining Controllers
// Main page Controller
.controller('mainController',['$scope',function ($scope) {
  $scope.home = "Home Page!"
}])

// Extract Page Controller
.controller('extractController',['$scope','apiExtractService',function ($scope,apiExtractService) {
  $scope.extract = function () {
    return extractedData = apiExtractService.apiExtract();
  }
}])

// Adding Services To the application
.service('apiExtractService',['$resource',function ($resource) {
  this.apiExtract = function () {
    var apiData = $resource("APIADDRESS",{callback: "JSON_CALLBACK"},{get:{method: "JSONP"}});
    return apiData.get({filter: "FILTER",access_token:"TOKEN"});
  }
}])

Here's my extract.html route.

 <div class="row">
  <div class="col-md-6 col-md-offset-3">
    <button type="button" ng-csv="extract()" filename="test.csv">Export</button>
  </div>
</div>

Thank you

4 Answers 4

2

As you are using $resource which returns a promise. So you need to catch the return value and return to your controller function as below

// Extract Page Controller
 .controller('extractController',['$scope','apiExtractService',function ($scope,apiExtractService) {

     $scope.extract = function () {
       return apiExtractService.apiExtract().then(function(results){
               return results;
             });
     }

  }])
Sign up to request clarification or add additional context in comments.

Comments

2

Edit: Someone basically said the same thing before me, but I'll leave this here just in case it helps anyone :)

When you want to take action after your request has been resolved, it's a perfect case to use promises. Make your apiExtractService.apiExtract method return a promise and take advantage of it. For example:

function apiExtract(){
    var deferred = $q.defer();
    $http("get", "sampleUrl", optionalData)
        .success(function (response) {
            deferred.resolve(response);
        })
        .error(function (err) {
            deferred.reject(err);
        });
    return deferred.promise;
}

and in your controller:

.controller('extractController',['$scope','apiExtractService',function ($scope,apiExtractService) {
  $scope.extract = function () {
    apiExtractService.apiExtract()
    .then(function(response){
     return response;
     }, function(err){
     console.log("something went wrong");
     });
  }

3 Comments

$resource already uses promises! No need to reinvent the wheel
Where should I add function apiExtract() ? Inside my Service?
Yes apiExtract was meant as an example function that returns a promise. the $resource feature you use already uses a promise as @NickNasirpour mentioned which means you can keep using that, the $http service I used is not needed, it's just I'm used to it and never used $resource so I provided the example with something I was more comfortable with :)
1

You're returning a $resource in the apiExtract function, which uses promises. Instead of returning the promise to the extract function, you should return the actual content, which can be done using angularJS's $resource.$promise attribute.

$scope.extract = function() {
    apiExtractService.apiExtract().$promise.then(function(extractedData){
        return extractedData;
    });
};

3 Comments

Thanks for your Answer, but somehow it doesn't work! I don't know why! I'm using angular v1.4.8! what do you think?
Can you show me what your apiExtract function is returning?
Yep, the JSON the API should be returning
1

I too had same issue. I was getting an empty file even after using a promise. I was able to resolve it by passing in the Array instead of entire API response JSON.

API response was

{
    "responseStatus": "001",
        "orderList":
    [{
        "id": 33, "status": null, "lastUpdatedDate": null, "lastUpdatedUser": null,
        "orderId": 1469830, "amount": 96, "discount": 6, "isPaid": "Y"
    }]
}

In the controller

    .controller('extractController', ['$scope', 'apiExtractService', function ($scope, apiExtractService) {
    $scope.extract = function () {
        apiExtractService.apiExtract()
            .then(function (response) {
                //You have to return an array not full JSON
                return response.orderList;
            }, function (err) {
                console.log("something went wrong");
            });
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.