I have a question as I am new to angularjs. I have searched alot but unable to understand the concept. I have a basic concept that there should be one controller for one view but we can have multiple controllers for a single view. I have below two controllers in a single view and there is one function let say for example addComma function which I have to use in both controllers but I want to write it one time to make it reusable between all controllers let say 5,6 controllers on the same view. So basically the question is how to make a function in a controller global between all controllers of same view or other views so that I can use it anywhere in my application. Appologies if it is a dumb question I am having a hard time understanding the concepts of angularjs.
app.controller("GetChargesController", function ($scope, GetService, $rootScope) {
$scope.Title = "Charges Details List";
$rootScope.loading = true;
// Calling Serivce Method here
$scope.GetChargesDetails = GetService.GetAll("CommonApi", "GetChargesDetails").then(function (d) {
$scope.ChargesDetails = d;
$rootScope.loading = false;
});
// add comman function goes here
$scope.addComma = function(x) {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
});
app.controller("GetPaymentsController", function ($scope, GetService, $rootScope) {
$scope.Title = "Payments Details List";
$rootScope.loading = true;
// Calling Serivce Method here
$scope.GetPaymentsDetails = GetService.GetAll("CommonApi", "GetPaymentsDetails").then(function (d) {
$scope.PaymentsDetails = d;
$rootScope.loading = false;
});
// add comman function goes here
$scope.addComma = function (x) {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
});
Below is the generic service I've written to get any kind of data from database(using asp.net web api). As I've read that angular services can hold data and we don't need to call the database again and again when we are moving back and forth on links let's say for example I have these 3 links on a page. Home Link, PaymentCharges Link, Orders Link. so Home view will open by default. And when I click on PaymentCharges Link the call will go get data from database and render its view but when I click back on Home Link there should be no call going to database to get the data for the home page or when I click forward again on PaymentCharges Link the second time there should be no call going to database but what I see on firebug console option it is calling the function and going to database to get the data.I think we need to use cache to hold the data to not send the call to database.
app.factory("GetService", function ($http) {
var thisService = {};
// get all data from database
thisService.GetAll = function (controllername, methodName) {
var promise = $http({
method: 'GET',
url: '/api/'+controllername + '/' + methodName
})
.then(function (response) {
return response.data;
},
function (response) {
return response.data;
});
return promise;
};
});
4 Answers 4
Create an utils service and add the addComma function there. Inject the utils service and reuse the addComma in the controllers
app.factory('utils', function() {
return {
addComma: function() {}
}
});
app.controller("GetChargesController", function ($scope, utils) {
$scope.addComma = utils.addComma;
});
app.controller("GetPaymentsController", function ($scope, utils) {
$scope.addComma = utils.addComma;
});
1 Comment
Several ways to manage the service issue:
Re-use the promises by storing them in the service:
// create an object to store promises
var promises = {};
thisService.GetAll = function(controllername, methodName) {
promises[controllername] = promises[controllername] || {};
// if the particular promise doesn't already exist create it as a property of above object
if (!promises[controllername][methodName]) {
promises[controllername][methodName] = $http({...}).then(...;
}
// now return the specific stored promise
return promises[controllername][methodName];
};
or store the data and use $q to return a different promise that resolves with the stored data when it already exists. Make sure to inject $q for this approach
var data = {};
thisService.GetAll = function(controllername, methodName) {
data[controllername] = data[controllername] || {};
if (data[controllername][methodName]) {
// data exists for this controller and method, no need for new request
return $q.resolve(data[controllername][methodName]);
} else {
return $http({...}).then(function(response) {
// store the data for next use
var newData = response.data;
data[controllername][methodName] = newData;
return newData;
});
}
};
4 Comments
Why don't you just store the data in the service?
You could do:
.then(function (resp) {
thisService.controllerName.data = resp.data
}
Then you can reference the variable in your code using GetService.controllerName.data
2 Comments
GetAll makes numerous different method name api endpoint calls also and I think you wanted thisService[controllerName]data = resp.data and then() needs to return the data also.Instead I would suggest you to use something like this which might make it little more generic. Check the below code
- appResources-Factory will contain all the resources that are needed to be exposed.
indexServices-Factory will contain all your services corresponding to your index controller.
(function () { use strict'; var commonServices = angular.module('commonServices', ['ngResource']); commonServices.factory('appResources', ['$resource', function ($resource) { var indexResource=$resource('/api/index/:id'); return { indexResource:indexResource } }]); commonServices.factory('indexService',['appResources', function (appResources){ var getAllIndexes =function(sucesscallback){ appResources.indexResource.query({}).$promise.then( //success function( value ){/*success events and Data is present in the 'value'*/ sucesscallback(value); }, //error function( error ){/*failure events*/} ) } } ]); });Controller Method calling the service and getting the value in $scope variables like
(function () { 'use strict'; angular.module('saniehhaApp') .controller('indexController', indexController); indexController.$inject = ['$location', 'indexService']; function indexController($location, index,indexService) { /* jshint validthis:true */ indexService.getAllIndexes(function(sucesscallback){ $scope.value=sucesscallback; }) //$locaton.qwets=.... } })();
Comments
Explore related questions
See similar questions with these tags.
$scope.addComma = function (x) { return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); }I think a filter is a good option and you can have juste one implementation of this function. But I'm agree this proposition is just for the first part of the question.