Search code examples
javascriptarraysangularjsangular-resource

Sorting an array that is the result of a $resource call in AngularJS


I'm trying to get the results of an API call and save it to $scope.segments, so that later I can sort the array using $scope.segments.sort()

However, since $scope.segments = SegmentsService.getSegments(jobId); does an async call, $scope.segments is undefined and the sorting never works.

Struggling with this the full day. How can I resolve this?

Here's my controller:

angular.module('appApp')
  .controller('MainCtrl', function ($scope, $routeParams, $filter, JobsFactory, SegmentsFactory, SegmentsService) {

    var jobId = $routeParams.id;

    // gets the segments from the API
    $scope.segments = SegmentsService.getSegments(jobId);

    // returns 'undefined', because $resource has not populated the 'segments' array yet
    console.log($scope.segments);

    // returns "TypeError: Cannot read property 'sort' of undefined", because $scope.segment doesn't exist (yet)
    $scope.segments.sort(function(a, b) {
      return a.sequence - b.sequence;
    });

  });

Here's my service:

angular.module('appApp')
  .service('SegmentsService', function (SegmentsFactory) {

    var segments = [];

    this.getSegments = function(jobId) {
      SegmentsFactory.query({ job_id: jobId }).$promise.then(function(data) {
        segments = data;
        return segments;
      }, function(err) {
        //fail
      });
    };

  });

And last, here's my factory:

angular.module('appApp')
  .factory('SegmentsFactory', function ($resource) {
    return $resource('http://localhost:3000/api/v1/segments/:id');
  });

Solution

  • You need to understand how promises work :)

    I'm a big fan of Promises in AngularJS, Explained as a Cartoon for that matter :)

    Here is working code for your use case.

    // service: return the promise
    .service('SegmentService', function (...) {    
         this.getSegments = function(jobId) {
             return SegmentsFactory.query({ job_id: jobId }).$promise;
         };
    });
    
    // controller
    .controller('MainCtrl', function (...) {
        SegmentsService.getSegments(jobId).then(function(segments) {
            segments.sort(function(a, b) { return ...; });
            $scope.segments = segments;
        });
    
    });