how to create new DataService Layer for $http call in angularjs - angularjs

If I user factory in angularjs for $http call then I would use it like below,
app.factory('myDataService', function($http){
return{
getProducts:function()
{
return $http.get('api/Product');
}
}
});
and use it in controller like this,
app.controller('appCtrl',function($scope,myDataService){
//Get Products
myDataService.getProducts().success(function(data,status){
//some stuff
}).error(function(data,status){
//some stuff
})
});
This is a simple way to make call to web api......
But
here i want is to add new layer called myDataService layer which will be helpful to define get, put ,post, delete methods in simple way like this,
Note:(Here I'm giving only concept. I dont know real implementation of it.
I dont know what should i use here .factory .service or javascript simple function. But let's say I'm using factory as below
myDataService
app.factory("myDataService", function (myHttPLayer) //myHTTPLayer is injected
{
//below code is not correct (I want to connect it to myHTTPLayer somehow)
return{
var myVar={
get:{
products:'/api/Product',
companies:'/api/Companies'
},
post:{
product:'/api/Product',
company:'/api/Companies'
}
}
}
});
here what i want is to introduce new layer like this which only gives information about get,put,post methods and api calls....
I don't want to write $http.get, $http.post and all everytime in angular controller. I want to write them at one place only one time. like this,
some.js...
myHTTPLayer
app.factory('myHttPLayer',function($http){
return {
get:function()
{ return $http.get(url);},
post:function(obj)
{ return $http.post(url,obj)
}
});
I want to connect both factories and by using them or writing them at angular controller side, i want to make web api call.
Note: This is just a concept.
please help me ....
In my mind what i want to implement is,
in angular controller something like,
app.controller("appCtrl",function($scope,myDataService){
//Connect myDataService to myHTTPLayer internally so I can use them as below....
//I want my api to be called when i write myDataService.getProducts() shown as below ....
myDataService.getProducts().success(function(){})
.error(function(){});
})
A big note : edit
Dont consider single line of code of myDataSevice. Its totally wrong. Just consider that i have all posible http methods in one factory with their proper prototyes which can return promise in myHTTPLayer. I will not temper it , once it is written correctly. What i want to do is to write myDataService code such a way that i can use it in angular controller without using myHTTP layer stuff in controller. When i use myDataService in controller, it must use httplayer behind the scene and it must make angular http call to defined web api. This is just a concept to be implemented.I want to develop such architecture. But unable to find the answer.

#stackg91 posted a great answer, but I believe it can be simplified further with regard to the else block. The below will work no matter what your 'variable' is ('products', 'company', etc.).
app.factory('myHttPLayer',function($http){
return {
get: function(variable) {
if(variable == null){
return $http.get(url);
} else {
return $http.get(url + '/api/' + variable);
}
}
}
});
Then you could simply call myHTTPLayer.get(products) in your controller for example. I don't believe you need three layers to get the functionality you're looking for here. I think a controller which passes a parameter to a service making '$http calls' utilizing that parameter is enough.

I normally do it like that, hope this helps you
app.factory('myDataService',function($http){
return {
getProducts:function(variable, callback) // this variable can be products or companies
{
if(variable == null){
return $http.get(url).success(callback).error(callback);
}else if(variable == products){
return $http.get(url+'/api/Product').success(callback).error(callback);
}else if(variable == companies){
return $http.get(url+'/api/Companies').success(callback).error(callback);
}
}
});
In COntroller it would look like this
$scope.test = myHttPLayer.get(products).onsuccess(function(){
Do Something ....
});

Related

How to share a model between different controllers through a service in Angular?

I am very new in Angular and I would like to share my problem, just in case someone could help me or guide me to
figure it out the best solution.
How do I share retrieved data from a promise (it can be called only once) between different controller through a service or a factory?
I think I should avoid if it is possible emit or broadcasting more on, either timeouts or similar
Anyway, I am sure it has to exist a pattern to do this properly
service('Service', function(...) {
function ----------(....) {
return myasyncfunction('..............')
.then(function(data) {
return data;
});
}
function getSomething {
return some operation with DATA;
}
return {
getSomething: getSomething
}
}
.controller('CtrlA', function (...) {
Service.getSomething ---> Doesn't work if don't put a delay
}
.controller('CtrlB', function (...) {
}
My code always has dependencies regarding to the fact that I need a promises at the beginning to retrieve the data. I don't
know the proper way to create an architecture in which I don't need a watch, timeout or emit/broadcast & on.
I suspect it is possible to do in another way
The promise should be called only once
Thx in advance
I should also have to use .then on promise(inside your controller) returned by service like -:
Service.getSomething.then(function(result){
//your promise resolve code
},function(error){
//your promise reject code
})

How can i make multiple http requests in a factory

I was wondering if we can load multiple json files using a factory and a controller.
Im pulling classifieds.json and myWords.json.
Im seeing content from the former, but the content from the latter is not being displayed
This is how i tired to incorporate it. I've checked the propriety of myWords.json against a json formatter, so i know for sure that its all right.
I guess, im doin sthg wrong here. Id appreciate if you could guide me in the right direction.
Factory
Controller
In order to fetch data from multiple sources, the currect way is to use one method for each data source.
Factory:
function getClassified() {
return $http.get('data/classified.json');
}
function getMyWords() {
return $http.get('data/myWords.json');
}
return {
getClassified : getClassified,
getMyWords : getMyWords
}
Controller
classifiedsFactory.getClassified().then(function(data) {
$scope.classified = data;
};
classifiedsFactory.getMyWords().then(function(data) {
$scope.myWords = data;
}
If you have more than 2 source that you want to get together, you can use $q service in your factory:
function getAllData() {
var source1 = $http.get('source1.json');
var source2 = $http.get('source2.json');
...
...
return $q.all([source1, source2, ...]);
}
This will resolve only when all data have been recieved and you can get it in your controller.
Don't forget to include $q in your factory function dependencies
Demo link
Hi Ashim09,
Here I added sample for multiple json call in factory..

Angular - reusing code (service or controller)

I'm using Angular to develop commenting functionality for a web app.
Currently there are two sections in the application were a user can comment:
Category
Product
About 90% of the commenting functionality is the same for both sections and as such I would like to make this reusable - i.e write some service or controller that I can reference/use as a base.
So far, my research seems to point to using a factory service but unfortunately this doesn't seem to work (I've spent the whole day running through various tutorials).
It is quite possible that I am over thinking this and making it far too complicated but I honestly don't know which way to turn anymore.
Herewith a quick and dirty overview of what I have so far:
HTML view for the category
Controller for the category (receives data from service and posts data to service in order to bind data to model)
Service for the category (retrieve and stores all the necessary
data)
The product uses the same logic and a lot of the code in the service and controller will be duplicated.
I've merged the two services into one service successfully but I'm having trouble doing the same for the controller.
Do I:
Write a base controller that will communicate with the above mentioned service and that will hookup with the two existing controllers
OR
Write a factory/provider service that hooks up to the two existing controllers as well as the above mentioned service.
If you go the route of using a factory, you could put all the common functionality into its return object and reference that from your controllers.
Factory
angular.module('myModule').factory('CommonFunctions', function(){
return {
foo : foo,
bar : bar
}
function foo(){
console.log('foo');
};
function bar (){
console.log('bar');
};
}
Controller
angular.module('myModule')
.controller('myController', ['CommonFunctions', function(CommonFunctions) {
var vm = this;
vm.foo = CommonFunctions.foo();
vm.bar = CommonFunctions.bar();
}
angular's separation of service types ie:
for specific values
constant
value
(constant for specific values needed before other services are created)
for functions
factory
service
provider
(provider for specific instances when you need a services before other services are created, usually taking advantage of constants)
allow the ability to share data and ways to process that data between controllers and or directives, anything that can be a value can also be a constant, the only difference there being where they can be injected. Similarly any service can be rewritten to a factory or a provider, it is more your specific use case / what your more comfortable writing that would determine which to use, but really the best way to think about it is if you have a value that needs to be shared but is not needed inside angular.module.config then use value, otherwise use constant, now if you have a single function that you want to share, (maybe it processes that value in some way or maybe it just does something else) you should write it as a factory, then when you have a few of those factory's that deal with either that value, or anything else, you can combine them into a service or configure and combine them using a provider. here is a simple example (note i am using the recommended syntax for writing angular services):
'use strict';
var app = angular.module('test.app',[]);
app.constant('configureableValue',{defaultValue:55});
app.value('editableValue',{defaultValue:100,editedValue:null});
app.provider('configureValue',configureValueProvider);
configureValueProvider.$inject - ['configureableValue'];
function configureValueProvider(configureableValue){
var defaultVal = configureableValue.defaultValue,
originalVal = defaultVal;
return {
getValue:getValue,
setValue:setValue,
resetValue:resetValue,
'$get':providerFunc
};
function getValue(){
return defaultVal;
}
function setValue(val){
defaultVal = val;
}
function providerFunc(){
return {
get:function(){ return getValue(); },
reset:function(){ resetValue(); }
};
}
function resetValue(){
defaultVal = originalVal
}
}
// this factory is an example of a single function service, this should almost always be defined as a factory
app.factory('getEditableValue',getEditableValue);
getEditableValue.$inject = ['editableValue'];
function getEditableValue(editableValue){
return function(){
return editableValue.editedValue ? editableValue.editedValue : editableValue.defaultValue;
};
}
// same with this one
app.factory('setEditableValue',setEditableValue);
setEditableValue.$inject = ['editableValue'];
function setEditableValue(editableValue){
return function(val){
editableValue.editedValue = val;
}
}
// now this is an example of a service service collecting the factorys for an object with all the related behavior we need
app.service('editableService',editableService);
editableService.$inject = ['getEditableValue','setEditableValue'];
function editableService(getEditableValue,setEditableValue){
var self = this;
self.setVal = setEditableValue;
self.getVal = getEditableValue;
}
app.config(appConfig);
appConfig.$inject = ['configureValueProvider'];
function appConfig(configureValueProvider){
configureValueProvider.setValue('i changed '+ configureValueProvider.getValue() +' to this!!!!');
}
app.run(appRun);
appRun.$inject = ['configureValue','editableService'];
function appRun(configureValue,editableService){
console.log('before editing: ',editableService.getVal());
editableService.setVal('changed!!!');
console.log('after editing: ',editableService.getVal());
console.log('we changed this in the config func: ',configureValue.get());
configureValue.reset();
console.log('and now its back to the original value: ',configureValue.get());
}
i know thats a lot for a simple example, but there are a lot of features provided by angular, and many ways to use them, hopefully this helps.

Accessing factories in the same Angular module

In my Angular app, I have some resource modules, each containing some cache factories.
For example,
projectRsrc.factory('getProjectCache', ['$cacheFactory', function($cacheFactory){
return $cacheFactory('getProjectCache');
}]);
I have a few of these to cache values received from the servers.
The problem is that at times I'd like to clear all the caches. So I want to put all the cacheFactories into one CacheCentralApp module and delete all the caches with a single call.
The trouble is, I don't know of any way to access other factories inside my module. So for instance, if I create a module CacheCentralApp, and in it, declare factories that provide cacheFactorys, how can I create a function in there that calls removeAll() on every cacheFactory?
I don't think it is possible to target all the factories of a certain module. I think however that another solution to your problem is to send a event that all factories has to be cleared. This will prevent that you will have to loop through all your factories and call a .clear() function on everyone.
You could send a event request with the following code:
$scope.$broadcast('clearAllCaches');
And listen to this event in every factory with:
$scope.$on('clearAllCaches', function() {
clearCache();
}
In a separate module you might create a factory for that:
var cacheModule = angular.module('CacheCentralApp', []);
cacheModule.factory('MyCacheFactory', ['$cacheFactory', function($cacheFactory) {
var cacheKeys = [];
return {
clearAll: function() {
angular.forEach(cacheKeys, function(key) {
$cacheFactory.get(key).removeAll();
});
},
get: function(key) {
if(cacheKeys.indexOf(key) == -1) {
cacheKeys.push(key);
return $cacheFactory(key);
} else {
return $cacheFactory.get(key);
}
}
}
}]);
To create new or get existing Cache you simply call MyCacheFactory.get(cacheName). To clear all the caches ever created in the factory you call MyCacheFactory.clearAll().
Note: I am not quite sure that Array.indexOf is available in every browser, you might want to use Lo-Dash or another library to make sure your code works.

how to make library of primary functions in AngularJS

I want to develop set of functions(sort of library) for CRUD in AngularJS so I can reuse them for couple of entities of my project. For server communication I made factory of $resource and using accordingly. $resource factory looks like this:
Model File:
var get_entity_model = angular.module("app.getentity", []).factory('getEntity', ['$resource', function($resource) {
return{
entity_view: $resource(baseurl+'/rest/'+serviceName+'/entity/:id/?app_name='+appName+'&fields=*', null, {'update': { method:'PUT' }})
}
}]);
And here how I'm using it in controller
Controller File:
getEntity.entity_view.get(
function(entity_list){
},
function(error){
}
)
Here entity_view is the table name. I'm passing all related functions like pagination and sub request to get the data of related tables etc code I put into success function of above request.
Now I want to make a library where I can define all this stuff and simply by calling the function I should be able to get all this stuff like:
entity.getEntity()
Should return same result as above code.
I tried with creating factory for above task but seems it need callback function and function at factory will return only data which I'm already getting from my model file so I need to make it compact and easy to use.
Factory Code at factory file:
var api = angular.module("app.entity_api", []).factory('entity_factory', ['$resource','getEntity',function($resource,getEntity) {
var entity_factory = {};
entity_factory.get_entity = function(callback){
getEntity.entity_view.get().$promise.then(
function(data){
callback(data.record);
}
);
}
return entity_factory;
}]);
And here how I call the function in controller:
Controller code:
api.controller("sample",['entity_factory','getEntity','$scope',function(entity_factory,getEntity,$scope){
$scope.init = function(){
entity_factory.get_entity(
function(data){
console.log(data);
}
);
}
$scope.init();
}])
Problem is that my entity_factory code will return only the data from server rest of the additional code I've to do in callback function which seems not much difference than my current exercise. So, the question is how can I achieve my goal to make a library of functions with additional code which return complete compiled result to make the code reusable for other entities and compact.
I like that you're a thinking of making a library but in this case, don't reinvent the wheel and save your precious time. Check out Restangular and your task will be a lot easier. Restangular is an AngularJS service that simplifies common GET, POST, DELETE, and UPDATE requests with a minimum of client code. It's a perfect fit for any WebApp that consumes data from a RESTful API.

Resources