balteo
balteo

Reputation: 24679

Issue with passing arguments to a named callback function in angularjs/javascript

I want to factor out the angularjs $http success callback function so that instead of having two (or N) anonymous callback functions I have one named callback function.

Here are the two controllers:

function CreateCurriculumCtrl($scope, $http, $location, select2Options){

    $scope.curriculumInfo = {};
    $scope.curriculumInfo.statusOK = true;
    $scope.select2Options = select2Options; 

    $scope.saveCurriculum = function(){
        $http.post('bignibou/curriculum/new', $scope.curriculumInfo).success(function(curriculumInfo) {
            if(curriculumInfo.statusOK == true){
                $scope.curriculumInfo.statusOK=true;
                $location.path('/view/'+curriculumInfo.curriculum.id);
            }
            else{
                $scope.curriculumInfo.statusOK = false;
                $scope.curriculumInfo.errors = curriculumInfo.errors;
            }           
        });
    };
}

function EditCurriculumCtrl($scope, $http, $location, select2Options, $routeParams){

    $scope.curriculumInfo = {};
    $scope.curriculumInfo.statusOK = true;
    $scope.select2Options = select2Options;
    $scope.id = $routeParams.id;

    $http.get('/bignibou/utils/findCurriculumById.json',{params: {id: $routeParams.id}}).success(
            function(curriculum){
                $scope.curriculumInfo.curriculum = curriculum;
            });

    $scope.editCurriculum = function(){
        $http.post('bignibou/curriculum/edit/'+$routeParams.id, $scope.curriculumInfo)
        .success(function(curriculumInfo) {
            if(curriculumInfo.statusOK == true){
                $scope.curriculumInfo.statusOK=true;
                $location.path('/view/'+curriculumInfo.curriculum.id);
            }
            else{
                $scope.curriculumInfo.statusOK = false;
                $scope.curriculumInfo.errors = curriculumInfo.errors;
            }           
        });
    };
}

I am not sure how to do that because what will become the named callback function has a couple of dependencies (i.e. $scope and $location).

If I extract the function (named callback) out of the angularjs controllers, then the named callback has no longer access to its dependencies.

Can anyone please help with factoring out the success callback function and making sure the dependencies are satisfied?

Upvotes: 1

Views: 3855

Answers (3)

slebetman
slebetman

Reputation: 113964

Just pass them as arguments.

First, $http.post expects the callback to accept one argument. So we write the function that post expects:

function (curriculumInfo) {
    // .....
}

But the body of the function needs access to $scope and $location. So we write a function that accepts those and return the function that post expects:

function (scope,location) {
    return function (curriculumInfo) {
        // ... use scope and location in here
    }
}

Now we can name the function appropriately. Lets see, it's handling the response to new curriculum so I'd call it either new_curriculum_callback or new_curriculum_callback or handle_new_curriculum to indicate that it's a callback:

function handle_new_curriculum (scope,location) {
    return function (curriculumInfo) {
    }
}

Now you can call it to return the callback function to post:

$http
    .post('bignibou/curriculum/new',$scope.curriculumInfo)
    .success(handle_new_curriculum($scope,$location));

Upvotes: 7

bekite
bekite

Reputation: 3444

Create a Curriculum service and refactor every call to the backend into it. Your controllers shouldn't care on how to getting the data. Inject the Curriculum service into your controllers. Your controllers then simply call functions on the Curriculum service and get the data.

angular.module('resources.curriculum', ['..'])
.factory('Curriculum', function ($http, $q) {
  return {
    create: function(dataToSave) {
      var deferred = $q.defer()

      http.get('...').success(function(data) {
        deferred.resolve(data)
      }).error(function(err) {
        deferred.reject(err)
      })
      return deferred.promise
    }
  }
})
.controller('SomeCtrl', function($scope, Curriculum) {
  $scope.someValue = Curriculum.create($scope.someDataToSave)
})

Upvotes: 2

Aditya Sethi
Aditya Sethi

Reputation: 10586

You would probably want to create angularjs service and call particular request on click of some button. This way you call requests in a synchronous way.

Upvotes: 0

Related Questions