In my project am using factory which returns list of items as per the service URL passed to that.Now i use the same factory method for all the listing items for example list of users,list of items etc.. but what happens is even i send different URLs to that factory the object is overridden.
It doesn't act as individual methods.I need to fetch different lists through different URLs using single factory and need to show in single page.
please help me with this.Thanks in advance.
this is how i would implement a service:
service:
app.factory('MyService', function ($http) {
var MyService = function () {
};
MyService.alertMe = function(message){
alert(message);
};
MyService.getUsers = function(){
return $http.get('/api/users');
};
MyService.createUser = function(user){
var data = angular.toJson(user);
return $http.post('/api/users', data);
};
return MyService;
});
usage:
app.controller('myCtrl', function($scope, MyService) {
$scope.click = function() {
MyService.alertMe('hi from service');
};
});
example: http://plnkr.co/edit/uf0kx41gsiJBLfZt0O8I?p=preview
Related
I've seen several posts about this, but I cannot adapt them to what I want to do.
I have a GET petition to a server to get a JSON response, and works like a charm.
.controller('ListController', ['$scope', '$http', function($scope, $http){
$http.get('js/data.json').success(function(data){
$scope.elements = data;
});
}])
Now I can print in the view with ng-repeat, all the elements within $scope.elements.
But now I need to do two different GETs, depending if has Internet, check online, if has not, check local DB.
I've created a factory like follows:
.factory('AttemptFactory', function($http){
var self = this;
this.elements = [];
this.returnFunction = function() {
$http.get('js/data.json').success(function(data){
self.elements = data;
});
}
}
I've firstly tried to fill this.elements, and then in the first controller access to it with $scope.newList = = AttemptFactory.elements.
Also tried make a return self.elements, and receive it with a AttemptFactory = AttemptFactory.returnFunction ();
I added the dependency injection of AttemptFactory to the .controller().
How can I archieve it??
if (online)
data = Get(from_server);
else
data = Get(from_local_DB);
return data;
Something like this. Thanks a lot.
I think you can try separating your concerns a bit. I'd recommend creating two factories: one that interacts with your server and one that interacts with the local db. Each could have a method that fetches data from the respective data store and returns a Promise for that data.
Then in your controller, you can choose which function to call based on the connection status. The function calls will both return a Promise that you can .then off of to get the data for your view. For example:
.factory('ServerFactory', function($http){
var serverFactory = {};
serverFactory.fetchJson = function() {
// note that we're returning the promise that $http get returns that will resolve with our data
return $http.get('js/data.json').success(function(res){
return res.data;
});
}
return serverFactory;
})
.factory('LocalDbFactory', function() {
var localDbFactory = {};
localDbFactory.fetchJson = function() {
// Return promise for JSON data here
}
return localDbFactory;
})
.controller('ListController', ['$scope', '$http', 'ServerFactory', 'LocalDbFactory', function($scope, ServerFactory, LocalDbFactory){
var result;
if (/* test if online */) {
result = ServerFactory.fetchJson();
} else {
result = LocalDbFactory.fetchJson();
}
result.then(function(data) {
$scope.elements = data;
})
}])
I am trying to use a service to share data between two controllers, but the data is not saved in the service.
My Serice
angular.module('dataservice', []).
factory('DataService', function(){
var item = {};
var addItem = function(newObj) {
item = newObj;
};
var getItem = function(){
return item;
};
return {
addItem: addItem,
getItem: getItem
};
});
My Controller
angular.module('App.controllers', []).
controller('SaveController', function($scope, $routeParams, APIService,DataService){
$scope.id = $routeParams.id;
$scope.book = null;
APIService.getBook($scope.id).success(function(response){
$scope.book = response;
DataService.add($scope.book);//add to service
});
}).
controller('ReadController', function($scope,DataService){
$scope.book = null;
$scope.book = DataService.get();//get from service
})
Using chrome dev tools to inspect when i try to read the data, i just get the object definition i.e DataService = Object {}.
Thanks
First of all you have a factory in another module, so you must inject it to your main module like this:
angular.module('App.controllers', ['dataservice'])
Then, you can call that DataService factory..
Note: You're trying to access the methods add and get, but actually they're named respectively as addItem and getItem, so you should rename them.
What I am trying to achieve:
Pass the parameter specId from the controller to the factory
In the factory: perform a $http.get to get JSON data
Return the JSON data to the controller
Displaying the information by assigning it to the $scope.formData
I tried many different ways but it only returns undefined. Before I created the factory I performed the $http.get directly in the controller without any issues, but now I am trying to structure the app in a better way.
Factory:
app.factory("dataFactory", function($http) {
var factory = {};
factory.getSpec = function(specId) {
return $http.get('getSpec.aspx?specId=' + specId)
};
return factory;
});
Controller
app.controller('EditSpecController', function ($scope, $stateParams, $http, dataFactory) {
$scope.specId = $stateParams.specId;
$scope.formData = [];
if($scope.specId) { //If EDIT MODE
dataFactory.getSpec($scope.specId).then(function(response) {
$scope.formData = response.data;
$scope.use_unit = response.data.use_unit;
});
}
As you noticed $http returns promise already, so you should do something more like this
factory.getSpec = function(specId) {
return $http.get('getSpec.aspx' + specId)
};
and then in controller
dataFactory.getSpec().then(function(response) {
$scope.formData = response.data;
});
I have a basic data Service which will be used across Controllers. But I'm having an issue grabbing some data that's been added via $http.
Service:
angular.module('core').service('FormService', ['$http', function($http) {
var _this = this;
_this.dropdownData = {
contactTimes: ['Anytime','Morning','Afternoon','Evening'],
industries: {},
};
$http.get('/json').success(function(resp){
_this.dropdownData.industries = resp.industries;
});
}]);
Controller:
angular.module('core').controller('SignupController', ['$scope', '$http', '$state', 'FormService', function($scope, $http, $state, FormService) {
console.log(FormService.dropdownData); // Shows full object incl industries
console.log(FormService.dropdownData.industries); // empty object {}
}]);
How do I get FormService.dropdownData.industries in my controller?
Create a service like below
appService.factory('Service', function ($http) {
return {
getIndustries: function () {
return $http.get('/json').then(function (response) {
return response.data;
});
}
}
});
Call in controller
appCtrl.controller('personalMsgCtrl', ['$scope', 'Service', function ($scope, Service) {
$scope.Industries = Service.getIndustries();
}]);
Hope this will help
Add a method to your service and use $Http.get inside that like below
_this.getindustries = function (callback) {
return $http.get('/json').success(function(resp){
_this.dropdownData.industries = resp.industries;
callback(_this.dropdownData)
});
};
In your controller need to access it like below.
angular.module('core').controller('myController', ['$scope', 'FormService', function ($scope, FormService) {
FormService.getDropdownData(function (dropdownData) {
console.log(dropdownData); // Shows full object incl industries
console.log(dropdownData.industries); // object {}
});
} ]);
Given that your console log shows the correct object, that shows your service is functioning properly. Only one small mistake you have made here. You need to access the data attributes in your return promise.
angular.module('core').service('FormService', ['$http', function($http) {
var _this = this;
_this.dropdownData = {
contactTimes: ['Anytime','Morning','Afternoon','Evening'],
industries: {},
};
$http.get('/json').success(function(resp){
//note that this is resp.data.industries, NOT resp.industries
_this.dropdownData.industries = resp.data.industries;
});
}]);
Assuming that you're data is indeed existing and there are no problems with the server, there are quite a few possible solutions
Returning a promise
angular.module('core').service('FormService', ['$http', function($http) {
var _this = this;
_this.dropdownData = {
contactTimes: ['Anytime','Morning','Afternoon','Evening'],
industries: {},
};
_this.dropdownData.industries = $http.get('/json');
}]);
//Controller
FormService.industries
.then(function(res){
$scope.industries = res.industries
});
Resolving with routeProvider / ui-route
See: $http request before AngularJS app initialises?
You could also write a function to initialize the service when the application starts running. At the end of the day, it is about waiting for the data to be loaded by using a promise. If you never heard about promises before, inform yourself first.
The industries object will be populated at a later point in time when the $http call returns. In the meantime you can still bind to the reference in your view because you've preserved the reference using angular.copy. When the $http call returns, the view will automatically be updated.
It is also a good idea to allow users of your service to handle the event when the $http call returns. You can do this by saving the $promise object as a property of industries:
angular.module('core').service('FormService', ['$http', function($http) {
var _this = this;
_this.dropdownData = {
contactTimes: ['Anytime','Morning','Afternoon','Evening'],
industries: {},
};
_this.dropdownData.industries.$promise = $http.get('/json').then(function(resp){
// when the ansyc call returns, populate the object,
// but preserve the reference
angular.copy( resp.data.industries, _this.dropdownData.industries);
return _this.dropdownData.industries;
});
}]);
Controller
app.controller('ctrl', function($scope, FormService){
// you can bind this to the view, even though the $http call has not returned yet
// the view will update automatically since the reference was preserved
$scope.dropdownData = FormService.dropdownData;
// alternatively, you can hook into the $http call back through the $promise
FormService.dropdownData.industries.$promise.success(function(industries) {
console.log(industries);
});
});
I'm using a service to make user data available to various controllers in my Angular app. I'm stuck trying to figure out how to use the $http service to update a variable local to the service (in my case "this.users"). I've tried with and without promises. The server is responding correctly.
I've read several excellent articles for how to use $http within a service to update the scope of a controller. The best being this one: http://sravi-kiran.blogspot.com/2013/03/MovingAjaxCallsToACustomServiceInAngularJS.html. That does not help me though because it negates the benefits of using a service. Mainly, modifying the scope in one controller does not modify throughout the rest of the app.
Here is what I have thus far.
app.service('UserService', ['$http', function($http) {
this.users = [];
this.load = function() {
var promise = $http.get('users.json')
.success(function(data){
// this.users is undefined here
console.log(this.users);
}
};
promise.then(function() {
// this.users is undefined here
console.log('this.users');
});
}]);
Any help is greatly appreciated. Thank you.
Try using
var users = [];
rather than
this.users = [];
and see what
console.log(users);
outputs in each of those cases.
Your service is oddly defined, but if you have a return in it you can access it from any controller:
app.service('UserService', ['$http', function($http) {
var users = [];
this.load = function() {
var promise = $http.get('users.json')
.success(function(data){
// this.users is undefined here
console.log(users);
users = data.data;
}
};
return {
getUsers: function(){
return users;
}
}
}]);
so in your controller, you can use:
var myUsers = UserService.getUsers();
UPDATE to use a service correctly here, your service should return a promise and the promise should be accessed in the controller: Here's an example from another answer I gave
// your service should return a promise
app.service('PickerService', [$http', function($http) {
return {
getFiles: function(){
return $http.get('files.json'); // this returns a promise, the promise is not executed here
}
}
}]);
then in your controller do this:
PickerService.getFiles().then(function(returnValues){ // the promise is executed here as the return values are here
$scope.myDirectiveData = returnValues.data;
});
this does not have scope anymore where you are trying to use it do this instead:
app.service('UserService', [$http', function($http) {
var users = [];
this.load = function() {
var promise = $http.get('users.json')
.success(function(data){
console.log(users);
}
};
promise.then(function() {
console.log(users);
});
}]);
all local variables to a service should just be vars if you assign them to this as a property than they will be included every time the service is injected into a controller which is bad practice.
I think what your asking for is a solution along the lines of defining your service like this:
angular.module('app')
.service('User', function($http, $q) {
var users = null;
var deferred = $q.defer()
return {
getUsers: function() {
if(users) {
deferred.resolve(users);
} else {
$http.get('users.json');
.success(function(result) {
deferred.resolve(result);
})
.error(function(error) {
deferred.reject(error);
});
}
return deferred.promise;
}
};
});
Then in one Each controller you would have to do this:
angular.module('app')
.controller('ACtrl', function($scope, User) {
User.getUsers().then(function(users) {
// Same object that's in BCtrl
$scope.users = users;
});
});
angular.module('app')
.controller('BCtrl', function($scope, User) {
User.getUsers().then(function(users) {
// Same object that's in ACtrl
$scope.users = users;
});
});
NOTE: Because the deferred.promise the same promise passed to all controllers, executing deferred.resolve(users) in the future will cause all then success callbacks in each of your controllers to be called essentially overwriting the old users list.
All operations on the list will be noticed in all controllers because the users array is a shared object at that point. This will only handle updates to the user list/each individual user on the client side of your application. If you want to persist changes to the server, you're going to have to add other $http methods to your service to handle CRUD operations on a user. This can generally be tricky and I highly advise that you check out ngResource, which takes care of basic RESTful operations