I have two controllers/views, one called member.js which is for displaying a list of members projects:
.controller( 'MemberCtrl', function MemberCtrl( $scope,ProjectsService ) {
$scope.projects = [];
$scope.refresh = function() {
ProjectsService.query()
.then(function (data) {
$scope.projects = data;
});
};
$scope.refresh();
})
.factory('ProjectsService', ['$http', '$q', function($http, $q) {
return {
query: function() {
var deferred = $q.defer();
$http.get('/api/get-projects')
.success(function(data) {
deferred.resolve(data);
})
.error(function(data) {
deferred.reject(data);
});
return deferred.promise;
}
};
}])
The next controller is in add.js and handles creating a new project:
.controller( 'AddprojectCtrl', function AddprojectCtrl( $http,$scope,Session,$location ) {
$scope.addProject = function(project){
return $http
.post('/api/create-project', project)
.then(function (result) {
$location.path("/member");
});
};
})
The issue I have is that once i've added in the new project, $scope.projects on the MemberCtrl is out of date and doesn't show the newly added item. I guess I could use one controller for both actions but was wondering if this is the best approach or what the "anggular" way is?
Your AddprojectCtrl should not be a controller, rather it should be a factory
.factory( 'AddprojectCtrl', function AddprojectCtrl( $http,$location ) {
return {
addProject:function(project) {
$http.post('/api/create-project', project)
//Ideally this can be done inside the controller itself
.then(function (result) {
$location.path("/member");
}
}
})
And then you need to inject the factory inside the controller. In the controller then you can call the addProject function of the factory. Thats the angular way :)
Related
I am creating one sample application, where I have API call for getting classes say
http://localhost:8080/school/4/classes
I have created a service for this
appServices.service( 'classService', ['$http', '$q',
function($http,$q){
this.getClass = function() {
var classes = $q.defer()
$http.get( "http://localhost:8080/school/4/classes" )
.then(function(data) {
classes.resolve(data)
});
return classes.promise
}
}])
I have two controllers say ctrl1 and ctrl2, in both I have code for service as
classService.getClass().then(function(data) {
$scope.classList = data.data.classes
})
My problem is two time api call is happening, can we reduced many api calls to one because my data is not going to be changed. I have already tried with { cache: true } but no luck
Thanks
The simplest way to prevent multiple calls is to use cache option:
app.service('classService', ['$http', function($http) {
this.getClass = function() {
return $http.get('data.json', { cache: true }).then(function(response) {
return response.data;
});
};
}])
Note, that you should not use $q as it's redundant.
In case if you need more control over the cache you can store reference to resolved promise:
app.service('classService', ['$http', function($http) {
var promise
this.getClass = function() {
if (!promise) {
promise = $http.get('data.json').then(function(response) {
return response.data;
});
}
return promise
};
}]);
And one more pattern with the most flexibility:
app.service('classService', ['$http', '$q', function($http, $q) {
var data;
this.getClass = function() {
return data ? $q.when(data) : $http.get('data.json').then(function(response) {
data = response.data;
return data;
});
};
}])
I have a factory, calling the service and getting the response and passing in to the controller and trying to store the response in a variable which is getting undefined
app.factory('Myservice', function (service1, service2) {
return {
getService: function (data) {
service1("user", encodeURIComponent("pass")).then(function (response) {
varSessionData = response.Obj;
var queryString = strURL[1].split("&");
Service2.pageLoad(SessionData).then(function (response) {
var homeScreen = response;
data(homeScreen);
});
});
}
};
});
In Controller:
var Mydata = MyService.geService(function (data) {
Console.log(data);
return data; // getting response
});
$scope.Hello = Mydata; // undefined
Whenever you make any AJAX request they are asynchronous. That is why Angular promises are used (the .then method). So you should change your code like this in your controller:
MyService.geService(function (data) {
Console.log(data);
$scope.Hello = data;
});
Change it to the following, your data isn't defined synchronously.
Controller:
MyService.geService(function(data) {
$scope.Hello = data;
});
i have pass the $scope.Hello in Another Service controller,which means depend upon that taking the result from services.
Not working?
var HomeController = function ($scope, $rootScope, $http, $stateParams, $state, Service3, Myservice)
{
MyService.geService(function (data) {
Console.log(data);
$scope.Hello = data;
});
Not working
Service3.pageLoad($scope.Hello) // not get the value
.then(function (response) {
$scope.ServiceModelobj = response;
console.log(response);
}
Working code
var HomeController = function ($scope, $rootScope, $http, $stateParams, $state, Service3, Myservice)
{
MyService.geService(function (data) {
Console.log(data);
$scope.Hello = data;
Working//
Service3.pageLoad($scope.Hello) // get the value
.then(function (response) {
$scope.ServiceModelobj = response;
console.log(response);
});
}
}
I'm approaching AngularJS and I want to get data from a database. I succeeded in doing this
angular.module("myApp")
.controller("listaUtentiCtrl", function($scope, $http) {
$http.get("backListaUtenti.php").success(function(data) { $scope.utenti=data } )
});
but I'd like to use a factory / service in order use the data from multiple controllers (but is not working)
angular.module("myApp")
.factory("utentiService", function($http,$q) {
var self = $q.defer();
$http.get("backListaUtenti.php")
.success(function(data){
self.resolve(data);
})
.error(function(){
alert("Error retrieving data!");
})
return self.promise;
});
angular.module("myApp")
.controller("utenteCtrl", function($scope, $routeParams, utentiService, filterFilter) {
var userId = $routeParams.userId;
$scope.utente = filterFilter(utentiService.utenti, { id: userId })[0];
});
angular.module("myApp")
.controller("listaUtentiCtrl", function($scope, utentiService) {
$scope.utenti = utentiService.utenti;
});
Where am I failing?
The problem is in your service implementation. Here is your code refactored:
angular.module("myApp")
.factory("utentiService", function($http) {
return {
getData: function () {
return $http.get("backListaUtenti.php").then(function (response) {
return response.data;
});
}
};
});
angular.module("myApp")
.controller("utenteCtrl", function($scope, $routeParams, utentiService, filterFilter) {
var userId = $routeParams.userId;
utentiService.getData().then(function(data) {
$scope.utente = filterFilter(data, { id: userId })[0];
});
});
angular.module("myApp")
.controller("listaUtentiCtrl", function($scope, utentiService) {
utentiService.getData().then(function (data) {
$scope.utenti = data;
});
});
If your data is static you can cache the request and avoid unnecessary requests like this:
$http.get("backListaUtenti.php", { cache: true });
I am trying to create a service to get json and pass it to me homeCtrl I can get the data but when a pass it to my homeCtrl it always returns undefined. Im stuck.
My Service:
var myService = angular.module("xo").factory("myService", ['$http', function($http){
return{
getResponders: (function(response){
$http.get('myUrl').then(function(response){
console.log("coming from servicejs", response.data);
});
})()
};
return myService;
}
]);
My Home Controller:
var homeCtrl = angular.module("xo").controller("homeCtrl", ["$rootScope", "$scope", "$http", "myService",
function ($rootScope, $scope, $http, myService) {
$scope.goData = function(){
$scope.gotData = myService.getResponders;
};
console.log("my service is running", $scope.goData, myService);
}]);
You should return promise from getResponders function, & when it gets resolved it should return response.data from that function.
Factory
var myService = angular.module("xo").factory("myService", ['$http', function($http) {
return {
getResponders: function() {
return $http.get('myUrl')
.then(function(response) {
console.log("coming from servicejs", response.data);
//return data when promise resolved
//that would help you to continue promise chain.
return response.data;
});
}
};
}]);
Also inside your controller you should call the factory function and use .then function to get call it when the getResponders service function resolves the $http.get call and assign the data to $scope.gotData
Code
$scope.goData = function(){
myService.getResponders.then(function(data){
$scope.gotData = data;
});
};
This is an example how I did for my project, it work fine for me
var biblionum = angular.module('biblioApp', []);//your app
biblionum.service('CategorieService', function($http) {
this.getAll = function() {
return $http({
method: 'GET',
url: 'ouvrage?action=getcategorie',
// pass in data as strings
headers: {'Content-Type': 'application/x-www-form-urlencoded'} // set the headers so angular passing info as form data (not request payload)
})
.then(function(data) {
return data;
})
}
});
biblionum.controller('libraryController', function($scope,CategorieService) {
var cat = CategorieService.getAll();
cat.then(function(data) {
$scope.categories = data.data;//don't forget "this" in the service
})
});
In my angular module I wrote a generic http handler for all my ajax requests.'
I was expecting that I could use the service across controllers, but my problem is the promise seems to be global.
Once ControllerOne uses the mapi_loader service, when I load AnotherController (by ng-click="go('/$route_to_load_another_controller')"), AnotherController is loaded a promise that has already returned from ControllerOne even though the URL they fetch are totally different.
So I guess my question is how do I write a service I could use across controllers? Do I really need to write a separate service for each controller where their only difference in code is the URL passed for $http.jsonp?
angular.module('myAppControllers',[])
.service('mapi_loader', ['$http', function($http) {
var promise;
var myService = {
fetch: function(url) {
if ( !promise ) {
promise = $http.jsonp(url)
.then(function (response) {
return response.data.nodes;
});
}
return promise;
}
};
return myService;
}])
.controller('ControllerOne', ['$scope', 'mapi_loader', function ($scope, mapi_loader) {
mapi_loader
.fetch("http://host.com/mapi_data_for_controller_one?callback=JSON_CALLBACK")
.then(function(data) {
$scope.useme = data;
});
}])
.controller('AnotherController', ['$scope', 'mapi_loader', function ($scope, mapi_loader) {
mapi_loader
.fetch("http://host.com/mapi_data_for_another_controller?callback=JSON_CALLBACK")
.then(function(data) {
$scope.useme = data;
});
}])
;
try something like this
angular.module('myAppControllers',[])
.service('mapi_loader', function($http) {
var alreadyLoading = {};
return {
fetch: function(url) {
if ( url in alreadyLoading ) {
return alreadyLoading[url];
}
return alreadyLoading[url] = $http.jsonp(url)
.then(function (response) {
delete alreadyLoading[url];
return response.data.nodes;
});
}
};
})
.controller('ControllerOne', function ($scope, mapi_loader) {
...
})
.controller('AnotherController', function ($scope, mapi_loader) {
...
});