I have a controller, "ListController", which needs to be populated with server side data.
app.controller("ListController", function(){
var bar = this;
bar.venues = MyFactory.load();
}
and I wanted to get the json array from the server, so i was thinking to create a factory leveraging "$http" as such:
app.factory("MyFactory", ["$https", function($https){
var myService = {};
myService.load = function(){
$http.get("scripts/Query.php").success( function(rows){
myService.rows = rows;
return myService.rows;
};
};
return myService;
}]);
So, i was thinking that MyFactory would be able to be called from inside the app controller.
app is the same variable, of type: angular.module("BarMe", []);
The error i get in my javascript is: MyFactory is undefined
You didn't inject factory in your controller.
Try like this
app.controller("ListController", function(MyFactory){
}
More over your method has a callback direct assign won't bring you any data
Try like this
MyFactory.load().then(function(data){
bar.venues = data;
});
You also have to return $http with response from factory
myService.load = function(){
return $http.get("scripts/Query.php").success( function(rows){
return rows;
};
};
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.
I have been struggling to figure out the 'angular' way of working for using factories to represent ajax data (I do a lot of sharing between controllers using config). I have done some extensive research and all of the answers seem to fall in to two categories:
Use the factory to represent the data, then in the controller fetch the data and update the factory:
{not intended to be actual runable angular}
var app = angular.module('main', [])
app.factory('data', function($http){
var data = []
return data
})
app.controller('cntrl', [$scope, $http, data]){
$scope.data = data
$http.get('/data').success(
function(idata){
$scope.data = idata
)
}
Use the factory to represent a http request with a promise and then assign that data to the $scope
var app = angular.module('main', [])
app.factory('data', function ($http, $q){
var factory = {};
factory.getdata = function(){
var defer = $q.defer();
$http.get('/data').success(function(idata) {
defer.resolve(idata);
})
return defer.promise;
}
return factory;
});
app.controller('cntrl', [$scope, data]){
$scope.data = []
data.getdata().then(function(idata) { $scope.data = idata });
}
I have several issues with this, in the first category the factory looks mega lame and like its not adding much value and each controller needs to have the code to manipulate the factory. With the second controller, the factory is very complicated and doesn't actually store the data (for sharing between controllers), just represents a long winded way to write a http.get
My question is this:
How can I use a factory to represent my data and manage the manipulation of that data in a clean way? What I would like to do is something like this:
var app = angular.module('main',[])
app.factory('data', function($http){
var factory = {}
factory.data = []
factory.initialise = function(){
$http.get('/data').success(
function(data){
factory.data = data
}
)
}
return factory
})
app.controller('cntrlA', [$scope, data]) {
$scope.data = data.data
$data.initialise()
}
app.controller('cntrlB', [$scope, data]) {
$scope.data = data.data
}
I am working on a project with a similar issue. What I ended up doing is using the service as a repository of the data. Instead of the initialize function getting fresh data each time, it is getting fresh data only if the data repository is empty or a getFresh flag is tripped (manual override). This way each controller can call the same function to get the data and manipulate it as the controller needs without tampering with the original data.
var app = angular.module('main',[])
app.factory('dataService', function($http, $q){
var factory = {}
factory.data = []
factory.getFresh = false
factory.initialise = function(){
var deferred = $q.defer()
if(factory.data.length===0 || factory.getFresh) {
$http.get('/data').success(function(data){
factory.data = data
deferred.resolve(data)
})
}
else{
deferred.resolve(factory.data)
}
return deferred.promise
}
return factory
})
app.controller('cntrlA', [$scope, dataService]) {
$scope.data = []
dataService.initialise().then(function(data){
$scope.data = data
}
}
app.controller('cntrlB', [$scope, dataService]) {
$scope.data = []
dataService.initialise().then(function(data){
$scope.data = data
}
}
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
I am trying to watch changes on an json array defined in an angularj service, but when the change occures, the $watch function is not firing. My controller and service code goes as follows (plunker demo):
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope,cityService) {
//$scope.cities = [];
$scope.service = cityService;
cityService.initCities();
$scope.$watch('service.getCity()', function(newVal) {
$scope.cities = newVal;
console.log(newVal)
});
});
app.service('cityService', function($http) {
this.cities = [];
this.initCities = function() {
$http.get('data.js').success(function(data) {
this.cities = data;
});
};
this.getCity = function() {
return this.cities;
};
});
This is because the callback from get set this to window object. Keep the reference of the service in self.
See this plunker
http://plnkr.co/edit/CrgTWRBsg5wi7WOSZiRS?p=preview
I changed several things to make it work:
http://plnkr.co/edit/PDMaEvmx7hG1fKvAmR7R?p=preview
Function watch instead of variable
In the service, removed the keyword this because this has not the same context inside functions.
Return functions in service
Seems ok