I am trying to create a service that passes data to controller.
I cannot see any errors in the console but yet the data won't show. What exactly am I doing wrong?
Service
app.service('UsersService', function($http, $q) {
var url = '/users';
var parsePromise = $q.defer();
$http.get(url).success(function(data) {
parsePromise.resolve(data);
});
return parsePromise.promise;
});
Controller
app.controller('contactsCtrl',
function($scope, $routeParams, UsersService) {
// Get all contacts
UsersService.get().then(function(data) {
$scope.contacts = data;
});
});
success is now deprecated.
app.service('UsersService', function($http) {
var url = '/users';
this.get = function() {
return $http.get(url).then(function(response) {
return response.data;
});
}
});
you are referring to UsersService.get(), so you must define the .get() function to call:
app.service('UsersService', function($http, $q) {
var url = '/users';
this.get = function() {
var parsePromise = $q.defer();
$http.get(url).success(function(data) {
parsePromise.resolve(data);
});
return parsePromise.promise;
}
});
Related
I have a simple app in DNN. Below is my code.
What am I trying to do is create a service which call the GET api once. So when the same data from input were called twice the service will call the same api. I'm using network in inspect element to find the calling functions.
<script type="text/javascript">
'use strict';
var myApp<%=ModuleId%> = {};
var isDlgOpen;
try {
myApp<%=ModuleId%> = angular.module('myApp<%=ModuleId%>', ['ngMaterial', 'ngMessages']);
}
catch (e) {
myApp<%=ModuleId%> = angular.module('myApp<%=ModuleId%>', ['ngMaterial', 'ngMessages']);
}
//Service
myApp<%=ModuleId%>.service('myService', ['$http', '$q', function ($q, $http) {
this.data;
var self = this;
this.submit = function () {
if (angular.isDefined(self.data)) {
return $q.when(self.data)
}
return $http.get($scope.apiGetUrl).then(function (response) {
self.data = response;
})
}
}]);
//Controller
myApp<%=ModuleId%>.controller('myCtrlr<%=ModuleId%>', function (myService, $scope, $http, $mdDialog) {
$scope.submit = function (ev) {
$scope.portalAlias = 'http://<%=PortalSettings.PortalAlias.HTTPAlias %>';
$scope.apiGetUrl = $scope.portalAlias + '/desktopmodules/ORSIModule/api/RepairStatus/getRepair?JobNo=' + $scope.jobNo + '&SerialNo=' + $scope.serialNo;
//form is valid
if ($scope.myForm.$valid) {
$scope.isLoading = true;
return $http.get($scope.apiGetUrl).then(
function (response) {
if (response.data) {
$scope.myForm.$setSubmitted();
$mdDialog.show(
$mdDialog.alert()
.parent(angular.element(document.querySelector('dnnModule<%=ModuleId%>')))
.clickOutsideToClose(true)
.title('title: ' + response.data.status)
.textContent('Thank you.')
.ariaLabel('Status Alert Dialog')
.ok('Close')
.targetEvent(ev)
.hasBackdrop(false)
);
} else {
alert("Not found.");
}
});
}
};
});
// Bootstrap the module
var appDiv = document.getElementById("dnnModule<%=ModuleId%>");
angular.bootstrap(appDiv, ["myApp<%=ModuleId%>"]);
Please somebody help me thanks
You just need to set the cache property to true in the get request:
$http.get(url, { cache: true}).success(...);
Also you can use:
$http({ cache: true, url: url, method: 'GET'}).success(...);
Another approach is to use cachefactory service:
var cache = $cacheFactory('myCache');
var data = cache.get(someKey);
if (!data) {
$http.get(url).success(function(result) {
data = result;
cache.put(someKey, data);
});
}
I have two factories in my angular app.
app.factory('FavoritesArtists',['$http', '$q', 'UserService', function($http, $q, UserService){
var deferred = $q.defer();
var userId = UserService.getUser().userID;
$http.get('http://myurl.com/something/'+userId)
.success(function(data) {
deferred.resolve(data);
})
.error(function(err) {
deferred.reject(err);
});
return deferred.promise;
}]);
And I have a value I get from another factory :
var userId = UserService.getUser().userID;
But I doesn't update when the UserService.getUser() is changed, the view changes with $watch, but I don't know how it work inside a factory.
Any help is welcome, thanks guys !
Anyone ?
app.factory('FavoritesArtists',['$http', '$q', 'UserService', function($http, $q, UserService){
var deferred = $q.defer();
$http.get('https://homechefhome.fr/rise/favorites-artists.php?user_id='+userId)
.success(function(data) {
deferred.resolve(data);
})
.error(function(err) {
deferred.reject(err);
});
return deferred.promise;
}]);
I simply need to make userId variable dynamic..
A better design pattern will be this
app.factory('UserService',
['$http', function($http) {
var getUser = function() {
return http.get("url_to_get_user");
};
return {
getUser: getUser
};
}]);
app.factory('ArtistService',
['$http', '$q', 'UserService', function($http, $q, UserService) {
var getFavoriteArtists = function() {
UserService.getUser().then(function(response) {
var userId = response.data.userID;
return $http.get('http://myurl.com/something/' + userId);
}, function() {
//passing a promise for error too
return $q.reject("Error fetching user");
});
};
return {
getFavoriteArtists: getFavoriteArtists
};
}]);
Now call it in controller like,
ArtistService.getFavoriteArtists().then(function(response) {
//do something with response.data
}, function(response) {
//log error and alert the end user
});
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 attempting to build a mock service so that my unit tests can verify certain functions are called and updated accordingly. Unfortunately I cannot get this to work.
Im currently getting an error undefined is not a function on this line:
spyOn(statusService, 'getModuleStatus').andCallThrough();
My actual service looks like this:
serviceStatusServices.factory('serviceStatusAppAPIservice', function ($http) {
var serviceStatusAppAPI = {};
serviceStatusAppAPI.getModuleStatus = function () {
return $http({
method: 'JSON',
url: '/settings/getservicestatusandconfiguration'
});
}
serviceStatusAppAPI.setModuleStatus = function (module) {
return $http({
method: 'POST',
url: '/settings/setservicestatusandconfiguration',
data: { moduleId: module.ModuleId, configData: module.ConfigValues }
});
}
return serviceStatusAppAPI;
});
My update function
serviceStatusControllers.controller('serviceStatusController', ['$scope', 'serviceStatusAppAPIservice', '$filter', '$timeout', function ($scope, serviceStatusAppAPIservice, $filter, $timeout) {
$scope.update = function () {
$scope.loading = true;
serviceStatusAppAPIservice.getModuleStatus().then(function (response) {
$scope.modules = $filter('orderBy')(response.data.moduleData, 'ModuleName')
...
My tests look like this
describe('ServiceStatusController', function () {
beforeEach(module("serviceStatusApp"));
var scope;
var statusService;
var controller;
var q;
var deferred;
// define the mock people service
beforeEach(function () {
statusService = {
getModuleStatus: function () {
deferred = q.defer();
return deferred.promise;
}
};
});
// inject the required services and instantiate the controller
beforeEach(inject(function ($rootScope, $controller, $q) {
scope = $rootScope.$new();
q = $q;
controller = $controller('serviceStatusController', {
$scope: scope, serviceStatusAppAPIservice: statusService });
}));
describe("$scope.update", function () {
it("Updates screen", function () {
spyOn(statusService, 'getModuleStatus').andCallThrough();
scope.update();
deferred.resolve();
expect(statusService.getModuleStatus).toHaveBeenCalled();
expect(scope.modules).not.toBe([]);
});
});
});
Also, how do I pass any mock data returned from the service to the caller. Currently in my model I do serviceStatusAppAPI.getModuleStatus(data) then use data.Data to get out the returned JSON.
I assume if you are doing something like this in your ctrl
scope.update = function() {
serviceStatusAppAPIservice.setModuleStatus(url).then(function (data) {
scope.modules = data;
})
};
Service which returns promise
.factory('serviceStatusAppAPI', function($http, $q) {
return {
getModuleStatus: function() {
var defer = $q.defer();
$http({method: 'GET', url: '/settings/getservicestatusandconfiguration'})
.success(function(data, status, headers, config) {
// this callback will be called asynchronously
// when the response is available
defer.resolve(data);
})
.error(function(data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
window.data = data;
});
return defer.promise;
}
};
});
So in you controller you will get data like this
serviceStatusAppAPI.getModuleStatus().then(function (data) {
$scope.modules = $filter('orderBy')(data.moduleData, 'ModuleName')
})
This is how you can run your unit test case
beforeEach(function() {
var statusService = {};
module('myApp', function($provide) {
$provide.value('serviceStatusAppAPIservice', statusService);
});
statusService.modalStatus = {
moduleData: [{ModuleName: 'abc'}, {ModuleName: 'def'}]
};
inject(function ($q) {
statusService.setModuleStatus = function () {
var defer = $q.defer();
defer.resolve(this.modalStatus);
return defer.promise;
};
statusService.getModuleStatus = function () {
var defer = $q.defer();
defer.resolve(this.modalStatus);
return defer.promise;
};
});
});
beforeEach(inject(function ($rootScope, $controller, _$stateParams_) {
scope = $rootScope.$new();
stateParams = _$stateParams_;
controller = $controller;
}));
var myCtrl = function() {
return controller('ServiceStatusController', {
$scope: scope,
});
};
it('should load status', function () {
myCtrl();
scope.update();
scope.$digest();
expect(scope.modules).toBe({
status: 'active'
});
});
Trying to return data from the factory and logging within the factory outputs the correct data, but once passed to the controller it is always undefined. If I have my factory logic inside the controller it will work fine. So it must be something simple Im missing here?
Application
var app = angular.module('app', []);
app.controller('animalController', ['$log', '$scope', 'animalResource', function($log, $scope, animalResource) {
$scope.list = function() {
$scope.list = 'List Animals';
$scope.animals = animalResource.get(); // returns undefined data
$log.info($scope.animals);
};
$scope.show = function() {};
$scope.create = function() {};
$scope.update = function() {};
$scope.destroy = function() {};
}]);
app.factory('animalResource', ['$http', '$log', function($http, $log) {
return {
get: function() {
$http({method: 'GET', url: '/clusters/xhrGetAnimals'}).
success(function(data, status, headers, config) {
//$log.info(data, status, headers, config); // return correct data
return data;
}).
error(function(data, status, headers, config) {
$log.info(data, status, headers, config);
});
},
post: function() {},
put: function() {},
delete: function() {}
};
}]);
Log Info
[Object, Object, Object, Object, Object, Object, Object, Object, Object, Object]
200 function (name) {
if (!headersObj) headersObj = parseHeaders(headers);
if (name) {
return headersObj[lowercase(name)] || null;
}
return headersObj;
} Object {method: "GET", url: "/clusters/xhrGetAnimals"}
Your get() method in service is not returning anything. The return inside the success callback only returns from that particular function.
return the $http object
Che this example that is how you use the promises and you return the factory then you access the methods injecting the service on your controller
Use dot syntax to access the function you define on the service
'use strict';
var app;
app = angular.module('app.formCreator.services', []);
app.factory('formCreatorService', [
'$http', '$q', function($http, $q) {
var apiCall, bjectArrarContainer, deferred, factory, webBaseUrl, _getFormElementsData;
factory = {};
deferred = $q.defer();
bjectArrarContainer = [];
webBaseUrl = 'https://tools.XXXX_url_XXXXX.com/XXXXXXX/';
apiCall = 'api/XXXXX_url_XXXX/1000';
_getFormElementsData = function() {
$http.get(webBaseUrl + apiCall).success(function(formElements) {
deferred.resolve(formElements);
}).error(function(err) {
deferred.reject(error);
});
return deferred.promise;
};
factory.getFormElementsData = _getFormElementsData;
return factory;
}
]);
then do it like this for example
'use strict';
var app;
app = angular.module('app.formCreator.ctrls', []);
app.controller('formCreatorController', [
'formCreatorService', '$scope', function(formCreatorService, $scope) {
$scope.formElementsData = {};
formCreatorService.getFormElementsData().then(function(response) {
return $scope.formElementsData = response;
});
}
]);