i have a problem with angularJS factory and controller
i want to get the http reply in a factory and use the api reply in controller
but i dont know how to handle the factory and inject it in controller
.controller('PlaylistsCtrl', function ($scope, $http) {
$http({ method: 'GET', url: "https://www.googleapis.com/blogger/v3/blogs/1309320265504420965/posts?key=***************" }).
success(function (data, status, headers, config) {
// this callback will be called asynchronously
// when the response is available
for (var i =0; i < data.items.length;i++)
{
var m,
urls = [],
str = data.items[i].content,
rex = /(https?:\/\/.*\.(?:png|jpg))/g;
while ( m = rex.exec( str ) ) {
urls.push( m[1] );
data.items[i].ImageURL = urls[0];
}
//data.items[i].ImageURL = urls[0];
}
$scope.playlists = data.items;
}).
error(function (data, status, headers, config) {
// called asynchronously if an error occurs
// or \\server returns response with an error status.
});
})
I am not exactly sure what you are looking for, but you can always return a promise by returning the http call. then grab that promise in controller and do something with it:
for example:
apiService.js
(function(app) {
"use strict";
app.factory("apiService", ["$http", function($http) {
var get = function(url, config) {
return $http.get(url, config);
};
var post = function(url, data, config) {
return $http.post(url, data, config);
};
var put = function(url, data, config) {
return $http.put(url, data, config);
};
var remove = function(url, config) {
return $http.delete(url, config);
};
return {
get: get,
post: post,
put: put,
remove: remove
};
}]);
})(_app);
and in your controller just inject the service:
(function(app) {
"use strict";
app.controller("MyCtrl", ["$scope", "apiService", function($scope, apiService) {
$scope.getData = function() {
apiService.get("/server/data").success(function(data) {
console.log(data);
}).error(function(err) {
console.log(err);
});
};
}
]);
})(_app);
Optional (app.js):
var _app = _app || {};
(function() {
"use strict";
_app = angular.module("myApp", []);
})();
Related
I have an angularjs factory like this:
'use strict';
angular.module('frontRplApp')
.factory('paymentService', function ($rootScope, $http, config, tools) {
var urlBase = config.baseUrl;
var paymentService = {
response: {},
create: function () {
var args = {};
return $http.post(urlBase + 'api/investor/payment/create', args);
}
});
And I intend to use it inside a controller like this (the important issue is being to do something different if all went well or if there was an error)
$scope.order = function () {
console.log('PaymentCashCtrl.order');
$scope.disabledButtons.submitCashOrder = true;
paymentService.create()
.then(
function (response) {
// do something with response
}, function (error) {
// do something with an error
}));
};
However my issue is that Id like to update some of the paymentService fields as the response of the $http.post is resolved and then return the promise so that the function(response) and function(error) callbacks in the controller keep working.
I tried with something like:
return $http.post(urlBase + 'api/investor/payment/create', args)
.then(function(response){
console.log(response);
this.response = response;
return response;
});
But it doesnt work since the function(error) handler in the controller is never called.
I want to use my handlers in the controller but also make some updates when the $http.post response is resolved.
Thanks.
in the factory, you need to return the functions paymentService object. also, don't resolve the promise inside the factory. resolve it in the controller.
.factory('paymentService', function($rootScope, $http, config, tools) {
var urlBase = config.baseUrl;
var paymentService = {
response: {},
create: function() {
var args = {};
return $http.post(urlBase + 'api/investor/payment/create', args);
}
}
return paymentService;
});
$scope.order = function() {
console.log('PaymentCashCtrl.order');
$scope.disabledButtons.submitCashOrder = true;
paymentService.create()
.then(
function(response) {
// do something with response
},
function(error) {
// do something with an error
}));
};
Use $q
Change your factory code to this:
angular.module('frontRplApp')
.factory('paymentService', function ($rootScope, $http, config, tools, $q) {
var urlBase = config.baseUrl;
var paymentService = {
response: {},
create: function () {
var deferred = $q.defer();
var args = {};
$http.post(urlBase + 'api/investor/payment/create', args)
.then(function(response){
console.log(response);
paymentService.response = response;
deferred.resolve(response);
}, function (error) {
deferred.reject(error);
});
return deferred.promise;
}
};
return paymentService;
});
I've used services once before (still not very good at it) and I've encountered a lot of issues already, so know I'm going to ask (I think my problem is easy AF:) )
I need to get some ChannelDetails with the use of YoutubeApi v3.
My Service:
appApi.factory('ServiceAPI', ['$http', function($http) {
var factory = {};
factory.channelDetails = function(channelname){
return $http.get('https://www.googleapis.com/youtube/v3/channels?part=contentDetails&forUsername='+channelname+'&key=AIzaSyDQv-WpATIWLinCB3H_sH4W1sKx7plyvRA')
.success(function(data) {
return data;
})
.error(function(data) {
return data;
});
}
}]);
then my controller:
var appApi = angular.module('YoutubeAPI', ['ngRoute'])
appApi.controller('youtubeCTRL', ['$scope','$http','$q','ServiceAPI', function ($scope, $http, $q, ServiceAPI) {
$scope.channel = [];
//GET Id on channelname
$scope.saveNewchlName = function () {
var channelname = $scope.newchlName;
$scope.channelDetails = function(channelname){
ServiceAPI.channelDetails(channelname).success(function (data) {
$scope.newchannelNames = {
channelName: $scope.newchlName,
channelId: data.items[0].id,
playlistId: data.items[0].contentDetails.relatedPlaylists.uploads
};
console.log($scope.newchannelNames)
$http({
method: 'POST',
url: 'http://localhost:8080/api/resources/channelNames/',
data: $scope.newchannelNames,
dataType: 'json'
}).success(function (data) {
$scope.channel.push(data);
console.log('SUCCESS!');
$scope.error = null;
}).error(function (data, status) {
if (status == 401) {
$scope.error = "You are not authenticated to Post these data";
return;
}
$scope.error = data;
});
});
}
}
My problem is that I keep encounter problems with injection. Now I got one which says: Provider 'ServiceAPI' must return a value from $get factory method.
I need to implement the channelname within the URL to get the specific details.
This seems to work.
Service:
appApi.factory('ServiceAPI', ['$http', function($http) {
var factory = {};
factory.channelDetails = function(channelname, success, error){
var promise = $http.get('https://www.googleapis.com/youtube/v3/channels?part=contentDetails&forUsername='+channelname+'&key=AIzaSyDQv-WpATIWLinCB3H_sH4W1sKx7plyvRA')
if(success){
promise.success(success);
}
if(error){
promise.error(error);
};
}
return factory;
}]);
controller:
var appApi = angular.module('YoutubeAPI', ['ngRoute'])
appApi.controller('youtubeCTRL', ['$scope','$http','$q','ServiceAPI', function ($scope, $http, $q, ServiceAPI) {
$scope.channel = [];
$scope.video = [];
var pagetokenarr = [];
//GET Id on channelname
$scope.saveNewchlName = function () {
var channelname = $scope.newchlName;
ServiceAPI.channelDetails(channelname, function(data){
$scope.newchannelNames = {
channelName: $scope.newchlName,
channelId: data.items[0].id,
playlistId: data.items[0].contentDetails.relatedPlaylists.uploads
};
console.log($scope.newchannelNames)
$http({
method: 'POST',
url: 'http://localhost:8080/api/resources/channelNames/',
data: $scope.newchannelNames,
dataType: 'json'
}).success(function (data) {
$scope.channel.push(data);
console.log('SUCCESS!');
$scope.error = null;
}).error(function (data, status) {
if (status == 401) {
$scope.error = "You are not authenticated to Post these data";
return;
}
$scope.error = data;
});
});
}
I'm new in angular and I'm working on a project that depends on service and factories. my problem is when I'm using a static jason array for response, the variables are filled correctly and are shown in view, but when I change it to a ajax request and get it from a json file, the response comes successful but the controller variables are not successfully loaded with data.
this is my angular project structure:
'use strict';
angular
.module('mytestapp',['ngRoute'])
.config(config)
.controller('HomeCtrl', HomeCtrl)
.controller('AboutCtrl', AboutCtrl)
.factory('GeneralInit', GeneralInit)
.service('UserSrv', UserSrv);
GeneralInit.$inject = ['UserSrv','$q'];
HomeCtrl.$inject = ['GeneralInit','$timeout','UserSrv'];
and here are my config:
function config($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'template/home.html',
controller: 'HomeCtrl',
controllerAs: 'hmc',
resolve: {
GeneralInit: function(GeneralInit){
return GeneralInit();
}}
})
.when('/about', {
templateUrl: 'template/about.html',
controller: 'AboutCtrl',
controllerAs: 'abc',
resolve: {
GeneralInit: function(GeneralInit){
return GeneralInit();
}}
});
}
here is my service:
function UserSrv($http) {
var User={};
var service = {
getUser: Get,
updateUser: Update,
logoutUser: Logout
};
return service;
function Get() {
//return {"FirstName":"StaticName","LastName":'StaticLastName'}
$http.get('/user.json')
.success(function(data, status, headers, config) {
User = data;
console.log(User);
return User;
})
.error(function(data, status, headers, config) {
})
}
function Update() {
}
function Logout() {
}
}
My controller and initialize item:
function GeneralInit(UserSrv,$q)
{
return function() {
var User = UserSrv.getUser(); //{'FirstName':'FstName','LastName':'LstName'};//
var Base='browser';
return $q.all([User, Base]).then(function(results){
return {
User: results[0],
Base: results[1]
};
});
}
}
function HomeCtrl(GeneralInit,$timeout)
{
var hmc= this;
$timeout(function(){
hmc.User=GeneralInit.User;
console.log(hmc.User);
}
,0);
}
The reason why you don't see any data in the console.log(hmc.User); statement is because by the time this statement executes, the promise is not actually resolved (the request fetching users has not yet returned). Though digest cycle is invoked as a result of using $timeout, hmc.User does not have data yet.
Try invoking the digest cycle after the requests actually return in your GeneralInit method, and you should have the data available.
And also you should probably change your Get method to return a promise:
function UserSrv($http) {
var User = {};
var service = {
getUser: Get
};
return service;
function Get() {
return $http.get('/user.json')
.success(function(data, status, headers, config) {
User = data;
console.log(User);
return User;
})
.error(function(data, status, headers, config) {
})
}
}
Your GeneralInit function is expecting getUser to return a promise, so just change it to this:
function UserSrv($http, $q) {
var User={};
var service = {
getUser: Get,
updateUser: Update,
logoutUser: Logout
};
return service;
function Get() {
var deferred = $q.defer();
//return {"FirstName":"StaticName","LastName":'StaticLastName'}
$http.get('/user.json')
.success(function(data, status, headers, config) {
User = data;
console.log(User);
deferred.resolve(user);
return User;
})
.error(function(data, status, headers, config) {
});
return deferred.promise;
}
}
I'm creating service layers to interact with Rest server, but I've got some problems with ngResource promises.
var grupogestion= angular.module('app.grupogestion.services', ['ngResource']);
grupogestion.factory('Grupogestion', ['$resource', function ($resource){
return $resource('api/grupogestiones/:action/:id.:format',
{
action: '#action', id:'#id', format:'json'
},
{
'get': {method:'GET'},
'post': {method:'POST',headers : {'Content-Type': 'application/x-www-form-urlencoded'}},
'save': {method: 'POST',headers : {'Content-Type': 'application/x-www-form-urlencoded'}}
}
);
}]);
grupogestion.service('GrupogestionService',['Grupogestion', function (Grupogestion){
this.findAll = function (){
Grupogestion.get({action: 'index'},function (data, status, headers, config){
return data;
});
}
this.save = function (grupogestion){
Grupogestion.save({'action':'add'},$.param(grupogestion)).$promise.then(
function(data){
alert('k');
return data;
},
function(error){
alert('j');
return error;
}
);
}
}]);
When I call var response = GrupogestionService.save(data) from angular controller, I don't get the data at the same time I call the function, so the question is: How can I modify GrupogestionService for returning data to the controller?
I've tried to return the promise but I couldn't do it. Thanks for helping.
// service code
grupogestion.service('GrupogestionService', ['Grupogestion', function (Grupogestion) {
this.findAll = function () {
Grupogestion.get({action: 'index'}, function (data, status, headers, config) {
return data;
});
};
this.save = function (grupogestion) {
return Grupogestion.save({'action': 'add'}, $.param(grupogestion));
}
}]);
//run in your controller
var response = GrupogestionService.save(data).$promise.then(
function (data) {
alert('k');
return data;
},
function (error) {
alert('j');
return error;
}
);
I have Employee controller which is having property Id, Name , Specification. I have made one Employee service which is having ajax call and get employee list. But every time getting '' in User.
When i debug the code i found that it call success first and then it goes for Ajax call.
When i do ajax call without service it works fine.
angular.module('EmployeeServiceModule', [])
.service('EmployeeSer', ['$http',function ($http) {
this.Users = '';
this.errors = '';
this.SearchEmployee = function () {
// Ajax call
$http({
method: 'GET',
url: '/Home/GetEmployeeList',
params: { filterData: 'Test' },
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
}).then(onSuccess, onError);
var onSuccess = function (response) {
this.userUsers = response.data;
this.errors = '';
};
var onError = function (reason) {
this.userUsers = reason;
this.errors = "Error in retrieving data.";
};
return this.Users;
}
}]);
angular.module('Employee', ['EmployeeServiceModule'])
.controller('EmployeeController', ['EmployeeSer', '$scope', '$http', function (EmployeeSer, $scope, $http) {
this.Id = '';
this.name = '';
this.expertise = '';
$scope.repoSortOrder = 'id';
$scope.filterField = '';
// Call to service
this.GetAllEmployee = function () {
// Initiates the AJAX call
$scope.User = EmployeeSer.SearchEmployee();
// Returns the promise - Contains result once request completes
return true;
};
this.AddEmployee = function () {
var empData = {
Id: $("#txtId").val(),
Name: $("#txtName").val(),
Expertise: $("#expertise").val()
};
$http({
method: 'POST',
url: '/Home/Create',
params: JSON.stringify(empData),
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
}).then(onSuccess, onError);
// Returns the promise - Contains result once request completes
return true;
};
var onSuccess = function (response) {
$scope.user = response.data;
$scope.error = '';
};
var onError = function (reason) {
$scope.error = "Error in retrieving data.";
};
}]);
It's because you are returning the users before the data is fetched from the server. Also it doesn't seem like you are assigning them correctly.
Here are two ways to solve the problem:
Firstly. You bind your controller user-data to the user-data in the service.
angular.module('EmployeeServiceModule', [])
.service('EmployeeSer', ['$http',function ($http) {
this.Users = '';
this.errors = '';
$http({
method: 'GET',
url: '/Home/GetEmployeeList',
params: { filterData: 'Test' },
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
}).then(onSuccess, onError);
var onSuccess = function (response) {
this.Users = response.data;
this.errors = '';
};
var onError = function (reason) {
this.users = null;
this.errors = "Error in retrieving data.";
};
}
}]);
angular.module('Employee', ['EmployeeServiceModule'])
.controller('EmployeeController', ['EmployeeSer', '$scope', '$http', function (EmployeeSer, $scope, $http) {
this.users = EmployeeSer.users;
EmployeeSer.SearchEmployee();
}]);
And the second way would be to return the promise in the service and unwrap it in the controller.
angular.module('EmployeeServiceModule', [])
.service('EmployeeSer', ['$http',function ($http) {
this.SearchEmployee = function () {
return $http({
method: 'GET',
url: '/Home/GetEmployeeList',
params: { filterData: 'Test' },
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
});
}
}]);
angular.module('Employee', ['EmployeeServiceModule'])
.controller('EmployeeController', ['EmployeeSer', '$scope', '$http', function (EmployeeSer, $scope, $http) {
this.GetAllEmployee = function () {
EmployeeSer.SearchEmployee()
.then(onSuccess, onError)
};
var onSuccess = function (response) {
$scope.user = response.data;
$scope.error = '';
};
var onError = function (reason) {
$scope.error = "Error in retrieving data.";
};
}]);
OFF TOPIC
You should probably consider using ngModel instead of jQuery to get you data to the controller.
Not like this:
var empData = {
Id: $("#txtId").val(),
Name: $("#txtName").val(),
Expertise: $("#expertise").val()
};
// Here serverRequest is my service to make requests to the server
serverRequest.postReq = function(url, data, sucessCallback, errorCallback){
$http({
method: 'POST',
url: urlToBeUsed,
data:data,
headers : {'Content-Type': 'application/x-www-form-urlencoded'}})
.success(function(data, status, headers, config) {
sucessCallback(data);
})
.error(function(data, status, headers, config){
errorCallback(data);
})
}
// In the controller
serverRequest.postReq('urlToBeCalled', dataToBeSent, scope.successCb, scope.errorCb);
scope.successCb = function(data){
// functionality to be done
}
scope.errorCb = function(data){
// functionality to be done
}
Try it this way your problem might be solved
Promise must be unwrapped in your controller if you want to use it