Reputation: 4671
I'm making an app in AngularJs and I'm facing a situation where I need to call the same function in multiple views.
In this case, it's a store system where the same store can be visible in multiple views. In the home, if it's near the user, in a paid ad, in the search result, etc..
I know this function should be in a service, which I already did. But the question is: How should I call this function from the view/html?
I'd like to avoid re-define the same calling over and over in multiple controllers, but until now, didn't found anything related to this specific problem.
This is the code I have:
function mainFactory($http) {
var service = {
addFav: _addFav
};
return service;
function _addFav(data, func) {
return $http.post(baseUrl+func,data).then(
function(res) {return res.data;},
function(err) {alert(_errorMsg);}
);
};
}
function HomeController() {
vm.addFavorites = addFavorites;
function addFavorites(data) {
var func = 'function_name';
mainFactory.addFav(data,func);
}
}
function AdvController() {
vm.addFavorites = addFavorites;
function addFavorites(data) {
var func = 'function_name';
mainFactory.addFav(data,func);
}
}
function SearchController() {
vm.addFavorites = addFavorites;
function addFavorites(data) {
var func = 'function_name';
mainFactory.addFav(data,func);
}
}
As you can see, I need to call the same function in multiple controllers.
I already saw some other examples saying to use this function as a $rootScope function from the .run, but also way more content warning about not being a good practice to define functions as root functions.
Any suggestion on how to solve this?
Edit:
Other solution I'm using right now, is to have a 'MainController' defined in the body tag via directive, so i can use this function in the whole app. But this controller is getting way to complex to maintain, with a lot of functions/process.
Upvotes: 1
Views: 505
Reputation: 4662
Suppose you have an app like that:
<html ng-app="app">
<body ng-controller="MainController">
<div ui-view></div>
</body>
</html>
And then you have app like:
angular.module('app', ['app.models']).controller('MainController', MainController);
function MainController($scope, MyService) {
$scope.addToFav = function (data) {
// suppose data is object
// then
MyService.add({
url: "...",
data: data
}).then(function(result) {
// success
}).catch(function(error) {
// wrong
});
}
}
// this is a service, shared by controller
(function (angular) {
'use strict';
angular.module('app.models')
.factory("MyService", _model);
_model.$injector = ['$http'];
function _model($http) {
var service = {
all: all,
one: one,
update: update,
add: add,
remove: remove
};
return service;
function add(param) {
var url = param.url;
if (url === null) {
return null;
}
$http({
url: url,
method: 'POST',
data: $httpParamSerializerJQLike(param.data),
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}).then(function (result) {
return result;
});
}
})(angular);
Then you can use MyService in any of your controller, and you can use addToFav to any of your view in same app...
<a ng-click="addToFav(...)"></a>
If you concern about the bloat issue of MainController, the better way is use local controller as the vm:
function ExampleController($scope, Product) {
var vm = this;
vm.product = ProductComponent.singleton($scope, Product)
}
var ProductComponet = (function () {
var instance;
var scope;
return {
singleton: function (_scope, Model) {
scope = _scope;
if (!instance) {
instance = createInstance(Model);
console.log(instance);
}
console.log(instance);
return instance;
}
};
function createInstance( Model) {
var vm = {
item: {},
list: [],
addToFav: addToFav
};
return vm;
function addToFav() {
}
}
})();
Then in your view, you can use:
vm.product.item to access current Item
vm.product.list to access all items
Keep all related data and method in one component, and re-use it in different controller.
Then why not use angular service or factory, coz they are all singleton, yes, we can use both, the idea is to build component, and re-use it rather than just use controller
Upvotes: 0
Reputation: 11398
How should I call this function from the view/html?
You shouldn't do it directly from the view.
But, you can nest controllers into other ones. So, if you think that your function deserved to be a "special" one, you can have the following "scenario".
html :
<div ng-controller="appController as app">
<div ng-controller="HomeController as home">
<button ng-click="app.addFavorites();"></button>
</div>
<!-- ... -->
</div>
This can also work with SPA if you put your appController away from the "inner view". Feel free to give this "appController" another name (mine sucks a bit).
Upvotes: 4