0

I have two controllers both with a save button which essentially does the same thing. So I want to put it in a reusable function that both the controllers can use. I have tried to do this by creating a normal function and passing the model object, as well as $http, but the function is executing before the save button is pressed leading to all the params being set to undefined. What way should I create a function that both these controllers can use?

Here how code looks:

app.controller('addCtlr',['$scope','$http','$location',
    function($scope, $http, $location){
        $scope.save = function(){
        var practices = [];
        var url = "https://maps.googleapis.com/maps/api/geocode/json?address="+$scope.location.address.replace(/ /g,"+");


    //If there are practices
        if($scope.days){
            for(dayName in $scope.days){                                                            //Loop through the days object              
                var day = $scope.days[dayName];                                                     //Gets the day pratice object
                practices.push({day: dayName, start_time: day.startTime, end_time: day.endTime});    //Add the pratice object to the practices array
            }
        }
    //Call to get the lat lng and formatted address from Google Map's service
        $http.get(url)
        .then(function(response){
            locJSON = response.data.results[0];                         //The JSON response

            //createing an object to send to the backend to save
            var locObj = {
                name: $scope.location.name,
                address: locJSON.formatted_address,
                location: locJSON.geometry.location,
                cost: $scope.location.cost,
                practices: practices,                                      
                notes: $scope.location.notes
            };

            //Sending using POST since a new object is being created
            $http.post('/api/locations', locObj)
            .then(
                $location.path('/')                                     
            );
        });//*/
    };
    }]);

This is how my function looked:

function saveLocation(location, days, $http){
    var practices = [];
    var url = "https://maps.googleapis.com/maps/api/geocode/json?address="+location.address.replace(/ /g,"+");


//If there are practices
    if(days){
        for(dayName in days){                                                            //Loop through the days object              
            var day = days[dayName];                                                     //Gets the day pratice object
            practices.push({day: dayName, start_time: day.startTime, end_time: day.endTime});    //Add the pratice object to the practices array
        }
    }
//Call to get the lat lng and formatted address from Google Map's service
    $http.get(url)
    .then(function(response){
        locJSON = response.data.results[0];                         

    //createing an object to send to the backend to save
        var locObj = {
            name: location.name,
            address: locJSON.formatted_address,
            location: locJSON.geometry.location,
            cost: location.cost,
            practices: practices,                                      
            notes: location.notes
        };

    //Sending using POST since a new object is being created
        $http.post('/api/locations', locObj)
        .then(
        //$location.path('/')                                     //Redirects the user back to the homepage 
        );
    });
}

This is how I was calling the function in the new controller:

app.controller('addCtlr',['$scope','$http','$location',
    function($scope, $http, $location){
        $scope.save = saveLocation(location, days, $http);
}]);

3 Answers 3

2

You can use service for this. Service is a singleton so will be created only one instance. And You can inject it by a dependency injector to controllers. You can read more here

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

Comments

1

You can create a service for your shared functionality and can inject it into your controller like below

var app=angular.module('app',[])

app.service('myService',function($http){

  this.saveLocation=function(){
  //Your code
  }

});

and then in your controller you can inject it like below

app.controller('myController',['$scope','myService',function($scope,myService){
 //use myService function to call save functionality
}]);

Also if you are using $http, you should keep this in mind that it returns a promise so you need to write all the code which is dependent on the value of this promise in a success callback otherwise your code will run before this callback and you will have undefined values for those variables.

Comments

0

Use a factory() service. You can define a set of functions and return them as an object. This object can then be injected within any controller:

app.factory('sharedFactory', [function() {
    "use strict";

    return {
        myFunction: function() {
            console.log("sharedFunction");
        }
    };

}]);

app.controller('AnyController', ['sharedFactory', function(sharedFactory) {
    "use strict";

    sharedFactory.myFunction();

}]);

2 Comments

Looks like I cannot use $scope when creating a service. Is there a way to pass the model object as a param to the service?
You can pass the $scope variable as an argument to any function a service returns. Just define $scope as a function parameter of the returned function in the service and pass the object from the controller.

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.