AngularJs Service with NgResource and custom methods combined - angularjs

Is it possible to have a service with custom methods AND the NgResource functionality?
Or do I have to create and manage 2 objects throughout the application? One for $resource (a factory), another one for other things like keeping values after routing (a .service for example).
I mean, all the examples I read implementing NgResource like a service shows a factory object returning only ONE thing, the $resource component. Like this:
.factory('User', function($resource){
return $resource(URL + ':id', {}, {
edit: {method:'PUT'}
....
....
});
This is useful and clear. Just call: User.edit(...);
What if I need a custom method to do some process, like:
User.calculateSomethingAboutTheUser()
What if I need to remember the user values after routing? I'm accomplishing this using a service (.service), called User, like this in the controller:
$scope.user = User;
I can't do that with the factory example because it's always returning the $resource object.

actually $http and it's abstraction $resource are just for loading data from server side, it's data layer. and it's better to declare additional service for calculations (store some state and so on) and it will be business logic layer. then you declare some directives which help you to display/get data (eg user input). and it's presentation layer. those directives call methods on your business logic services and BL services call data layer if needed.

Related

What is best practice in angular when it comes to the seperation of data and logic

Currently I have a bunch of controllers that seems a little too bulky for my liking in that they manage both the logic and the storing of data.
For instance let us take a over simplified register controller:
$scope.username = "";
$scope.password = "";
$scope.validateUsername= function(){
......
}
$scope.validatePassword= function(){
......
}
$scope.updateUserConfig = function(){
//a rest call here
}
ok so to me this seems like it is wrong because the controller is storing data, performing logic and making calls to a rest service.
I thought the controller should be the logic for the view it is used for while the "model" i.e. username and password should be somewhere else as well as the call to the rest service.
I have looked about and have seen people employing factories that are injected into the controller for the rest calls; as these factories will not store state they can be shared across the entire application, so this seems like a good idea ?
I am unsure about the data aspect though, is it normal for data to be stored within the controller or is there a better practice for this?
It is important to remember that your view must bind to the data/methods in the controller, so it must be exposed in such a way for this to be possible. In other words, there's nothing wrong with having these properties in your controller.
That being said, this data often comes from an external source or is needed in multiple views/controllers so it's common for a factory/service to return an object to a controller and then assign that object to a $scope property. This way you can abstract that layer away and share the data across your application without repeating yourself.

Angular instantiate factories

I'm a bit confused with Angular. I have two factories, with code looks almost the same, because they performs CRUD operations on two different objects in db, and I want to make them DRY.
So I have idea to move common logic to separate service, and I want it to works something like that :
angular.module('app').factory('first',['commonService',function(commonService){
return new commonService('someSpecificVariable');
}])
and service :
angular.module('app').service('commonService',['someDep1',function(someDep1,someSpecificVariable){
var something = someSpecificVariable;
}]);
I looked at providers, but i need something to instantiate. How can I achieve this?
In another words I want create factory responsible for all crud operation requests for all app modules, because writing many factories just to handle http/crud don't looks ok for me.
Ok i descriped it quite bad.
SOLUTION Is it possible and in good form to reuse the same data factory in Angular?
Factories
They let you share code between controllers as well as making http calls to your API. They are really about making some reusable code that you can instantiate in your controllers to make your life easier and your controllers cleaner.
Simple Example
.factory('FindFriend', function ($http, $rootScope) {
return {
find: function (phone) {
return $http.get('http://130.211.90.249:3000/findFriend', { params: {phone:phone}})
},
add: function (id) {
return $http.get('http://130.211.90.249:3000/addFriend', { params: {friendid:id, user_id: $rootScope.session} })
},
deleteFriend: function (id) {
return $http.get('http://130.211.90.249:3000/deleteFriend', {params:{idfriends: id}})
}
}
})
Explanation
So above we can see a factory called FindFriend. The factory has 3 methods find add and delete. these are different http calls (in your code they shouldn't be all get methods but this is some old code I wrote).
They can be instantiated by adding them into the top of the controller and then calling there functions like FindFriend.add
Hope this sheds some light on factories for you.
I know how factories works, but i dont want to add bunch of functions responsible for each module. I wish to make service, which will replace patches to $http calls based of provided module name in constructor. ex 'orders' will make request :
$http.post('/api'+'orders'+'/lazy')...

Call an API in every angular controller if data not yet loaded

I am building a single page app using angular and .net backend.
Aside from the individual restful resources that the controllers call, I also have a System Resource which provides the app with system wide information that is used/needed by most of my controllers.
I call the system service and store the data in the rootScope when the user first logs on.
However if for some reason the user refreshes the page which will lose the rootScope then the system data is lost and no longer available to the controller.
I have managed to get the System Service to trigger if a page reload happens BUT the problem is that in many cases the services running from the controller happen BEFORE the system service call which means that the data is not always available when the controller runs.
Whats the correct way to handle this in angular? Is there a way to make my controllers dependent on a certain rootScope state which if necessary will cause my system service API to be called before the controller makes its own service calls?
Thanks
One approach could be creating a factory/service which is injected to and called by every controller needing this information. This way you don't have to mess with $rootScope.
The request to get information should be cached so that you don't have to fire off a get everytime you switch controller. If you want to persist the information even after a page refresh you could use localstorage to store your data.
Example factory:
angular.module('appName')
.factory('Settings', ['$http', function ($http) {
function getData() {
var url = 'url/to/endpoint';
return $http.get(url, {cache: true});
}
return {
promise: getData()
};
}]);
By returning a promise from the factory we ensure that the getData() call is only run once. While in this particular instance it makes almost no difference (since it is returning an inner promise already), it is a pattern to follow for best practice.
This pattern also means that getData() is called on first use regardless of if the consuming controller accesses the promise. This allows for data to be exposed easily (data binding) without the need to use the promise in some use cases.
Used in controller:
angular.module('appName')
.controller('VeryNiceCtrl', ['$scope','Settings', function ($scope, Settings) {
Settings.promise.success(function(response){
var appSettings = response;
// do stuff
})
}])

Same Angular controller for different view

I have a requirement to list, edit and delete an entity. I have different views for each of this operations. I want to know if it is a good practice to use the same Angular just controller for these operations that works with each of the operation or should there be a separate controller for each?
Also if using same controller for these operations, is it possible to call different function when different views are loaded? So when user goes to the list view, a list method is called on page load and when he goes to the edit view, an edit method of the controller is called on edit view's load. I manage to achieve this by calling the methods using ngInit but apparently that is not recommended in v1.2 and should only be used with ngRepeat.
My question is similar to this one. Angular - Using one controller for many coherent views across multiple HTTP requests
However I also want to know if there is a way to call different initialisation methods of the same controller depending on the view the controller is used by.
A better approach could be to write a utility service which can be used across the controller. Use this service in your different controllers.
Your service will look something like this:
(function() {
'use strict';
// this function is strict...
angular
.module('myapp.services', [])
.service('Utility', function() {
var Utility = {};
Utility.edit = function(id, dataset) {
//perform edit related task here
};
Utility.delete = function(id, dataset) {
//perform edit related task here
};
return Utility;
})
}());
I have got my answer here: Using same controller for all CRUD operations (Rails-alike)
Apparently it is a good practice to use a different controller for each view, and it shouldn't work as a service. This is quite different for someone coming from MVC/WebAPI into angular.

Angular controller repeating the same if statement

All of the controllers in my app share a dependency on a data provider type service I created. This service consists of functions to retrieve various bits of data, and almost all of these methods allow for an optional parameter. The ability to enter in this optional parameter is role based. The problem is my controllers are now full of code similar to:
// Initializing controller.
dataservice.getRole().then(function(role) { $scope.isAdmin = role.isAdmin; });
// After a button press or some other event.
if($scope.isAdmin) {
dataservice.getData($scope.param1, $scope.param2, $scope.optionalText);
} else {
dataservice.getData($scope.param1, $scope.param2);
}
It seems a code smell to me that I have to keep repeating this code throughout the controllers, but I can't think of a way to construct my controllers where I don't have to.
That's how I've realized that: Controller Inheritance.
Basically:
Create your service (factory) with your Base Controller logic and
return the Constructor (example)
Use $injector.invoke in your derived Class (to implement your
base controller) in order to enrich the actual controller $scope
(example)
There's no an official "angular way" to implement this features, but I hope the angular team will work on it

Resources