I offloaded the call to the Twitter API from my controller into a service:
angular.module('main')
.service('Tweet', function ($log, $http, Config, $ionicLoading) {
this.show = function () {
$ionicLoading.show({
template: '<ion-spinner></ion-spinner><br>Loading'
}).then(function () {
$log.log("The loading indicator is now displayed");
});
};
this.hide = function () {
$ionicLoading.hide().then(function () {
$log.log("The loading indicator is now hidden");
});
};
var consumerKey = encodeURIComponent(Config.TWITTER.CONSUMERKEY);
var consumerSecret = encodeURIComponent(Config.TWITTER.CONSUMERSECRET);
var tokenCredentials = btoa(consumerKey + ':' + consumerSecret);
this.getToken = function () {
this.show();
return $http({
method: 'POST',
url: 'https://api.twitter.com/oauth2/token',
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
'Authorization': 'Basic ' + tokenCredentials
},
data: 'grant_type=client_credentials'
})
.then(function (result) {
if (result.data && result.data.access_token) {
$http.defaults.headers.common.Authorization = 'Bearer ' + result.data.access_token;
}
})
.catch(function (error) {
console.log(error);
});
};
this.getTimeline = function () {
$log.log($http.defaults.headers.common.Authorization);
return $http({
method: 'GET',
url: 'https://api.twitter.com/1.1/search/tweets.json?q=%40postbank',
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
}
})
.then(function (result) {
return result.data.statuses;
})
.catch(function (error) {
console.log(error);
});
};
this.analyzeResult = function (input) {
this.tweets = input;
this.hide();
};
var that = this;
this.getTweets = function () {
this.getToken()
.then(this.getTimeline)
.then(function (result) {
that.analyzeResult(result);
});
}
});
I inject the service into my main controller and call the getTweets() function:
angular.module('main')
.controller('MainCtrl', function ($log, Tweet) {
Tweet.getTweets();
});
I can see that all the promises are executed through the console, but this.tweets stays empty. How do I send the data that is coming from the service/promise to the controller?
this within service constructor is service's context, not controller's. And services shouldn't operate on the scope.
Unwrap service promise in controller:
var self = this;
Tweet.getTweets().then(function () {
self.tweets = input;
});
Related
Im trying to get initialize the scope variable via http get request in page load in first function but then when trying to use the scope variable in other function in the same page load, it is undefined.
app.controller('GradeAndSectionCtrl', function ($scope, $http) {
$scope.GetCategories = function () {
$http({
method: 'GET',
url: '/GradeAndSection/GetCategories'
}).then(function (response) {
$scope.categories = response.data;
if (response.data != null) {
$scope.drpCategory = $scope.categories[0].categoryID;
}
});
};
$scope.GetGrades = function () {
\\$scope.drpCategory; here; is; undefined;
$http({
method: 'GET',
url: '/GradeAndSection/GetGrades?categoryID=' + $scope.drpCategory
}).then(function (response) {
$scope.grades = response.data;
});
};
$scope.GetCategories();
$scope.GetGrades();
});
You are making asynchronous call using promises in your code therefore $scope.drpCategory may not be loaded when you call GetGrades function. You can call your GetGrades function when GetCategories is resolved.
$scope.GetCategories = function () {
$http({
method: "GET",
url: "/GradeAndSection/GetCategories"
}).then(function (response) {
$scope.categories = response.data;
if (response.data != null) {
$scope.drpCategory = $scope.categories[0].categoryID;
$scope.GetGrades();
}
});
}
Try to call the function GetGrades in then()
$scope.GetCategories = () => {
$http
({
method: 'GET',
url: 'categories.json',
})
.then(data => {
$scope.categories = data.data;
$scope.drpCategory = $scope.categories[0].category
$scope.GetGrades($scope.drpCategory)
}, function errorCallback(response) {
console.log(response);
console.log('error');
});
}
$scope.GetGrades = (drpCategory) => {
$http
({
method: "GET",
url: "categories_" + drpCategory + ".json"
}).then(function (response) {
$scope.grades = response.data;
console.log($scope.grades)
});
}
$scope.GetCategories()
Working example: http://plnkr.co/edit/ZN8nI7OhAyWiJWlqeJsU?p=preview
i have the following code for save operation:
here is my angular service: this already returns the promise
factory('customersaveService', function ($http, $q) {
var factoryObject = {};
factoryObject.SaveNewUserSrv = function(data) {
var deffered = $q.defer();
$http({
url: 'CustomerTest1/SaveNewUser',
method: 'POST',
headers: { 'content-type': 'application/json' },
data: JSON.stringify({ 'cust': data }),
})
.success(function (d) {
deffered.resolve(d);
})
.error(function (e) {
deffered.reject(e);
});
}
return factoryObject;
});
in here the promise is returned. therefore it shoudl not throw the error
"TypeError: Cannot read property 'then' of undefined"
the error comes from the controller's code:
$scope.SaveCustomer = function (data)
{
if ($scope.ButtonText == 'Save')
{
$scope.message = "";
$scope.submitted = true;
$scope.User = data;
console.log($scope.User);
customersaveService.SaveNewUserSrv($scope.User).then(function (d) { <=== error line
console.log('before success part');
if (d == 'success')
{
console.log('im in success part');
clearform();
}
},
function (e) {
});
}
}
why this throws the error when the promise was returned?
1.Create service like below :
2.No need of $q service.
factory('customersaveService', function ($http) {
var factoryObject = {};
factoryObject.SaveNewUserSrv = function(data) {
return $http({
url: 'CustomerTest1/SaveNewUser',
method: 'POST',
headers: { 'content-type': 'application/json' },
data: JSON.stringify({ 'cust': data }),
})
}
return factoryObject;
});
factory('customersaveService', function ($http) {
var SaveNewUserSrv = function(data) {
return $http({
url: 'CustomerTest1/SaveNewUser',
method: 'POST',
headers: { 'content-type': 'application/json' },
data: { 'cust': data }
});
};
return {
SaveNewUserSrv: SaveNewUserSrv
};
});
And in the controller, sure you inject the service customersaveService
I have tried to build a service that will return a $resource after the service has authenticated.
I have done it like this:
.factory('MoltinApi', ['$q', '$resource', '$http', 'moltin_options', 'moltin_auth', function ($q, $resource, $http, options, authData) {
var api = $resource(options.url + options.version + '/:path', {
path: '#path'
});
var authenticate = function () {
if (!options.publicKey)
return;
var deferred = $q.defer();
var request = {
method: 'POST',
url: options.url + 'oauth/access_token',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data: "grant_type=implicit&client_id=" + options.publicKey
};
$http(request).success(function (response) {
authData = response;
deferred.resolve(api);
});
return deferred.promise;
};
return authenticate();
}])
But I can not call the resource in my controller:
.controller('HomeController', ['MoltinApi', function (moltin) {
var self = this;
moltin.get({ path: 'categories' }, function (categories) {
console.log(categories);
});
}]);
it just states that 'undefined is not a function'.
Can someone tell me what I am doing wrong?
Update 1
So after playing with the solution that was suggested, this is the outcome.
angular.module('moltin', ['ngCookies'])
// ---
// SERVICES.
// ---
.factory('MoltinApi', ['$cookies', '$q', '$resource', '$http', 'moltin_options', function ($cookies, $q, $resource, $http, options) {
var api = $resource(options.url + options.version + '/:path', {
path: '#path'
});
var authenticate = function () {
if (!options.publicKey)
return;
var deferred = $q.defer();
var authData = angular.fromJson($cookies.authData);
if (!authData) {
console.log('from api');
var request = {
method: 'POST',
url: options.url + 'oauth/access_token',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data: "grant_type=implicit&client_id=" + options.publicKey
};
deferred.resolve($http(request).success(function (response) {
$cookies.authData = angular.toJson(response);
setHeaders(response.access_token);
}));
} else {
console.log('from cookie');
deferred.resolve(setHeaders(authData.access_token));
}
return deferred.promise;
};
var setHeaders = function (token) {
$http.defaults.headers.common['Authorization'] = 'Bearer ' + token;
}
return authenticate().then(function (response) {
return api;
});
}]);
and to call it I have to do this:
.controller('HomeController', ['MoltinApi', function (moltin) {
var self = this;
moltin.then(function (api) {
api.get({ path: 'categories' }, function (categories) {
console.log(categories);
self.sports = categories.result;
});
});
}]);
but what I would like to do is this:
.controller('HomeController', ['MoltinApi', function (moltin) {
var self = this;
moltin.get({ path: 'categories' }, function (categories) {
console.log(categories);
}, function (error) {
console.log(error);
});
}]);
As you can see, the service is checking to see if we have authenticated before returning the API. Once it has authenticated then the API is returned and the user can then call the api without having to authenticate again.
Can someone help me refactor this service so I can call it without having to moltin.then()?
You are returning the authenticate function call in the MoltinApi factory, so you are returning the promise. And the method get doesn't exist in the promise
myapp.factory('serviceName', function( $http, webStorage){
var factory = {};
var resoureurlBase=some base url;
factory.genericService = function(method, payload, methodName, callbackFn, callbackError, param) {
var httpRequest = null;
if (param && param == true) {
httpRequest = $http({
url: resoureurlBase+methodName,
method: method,
params: payload,
headers: {
'Content-Type': 'application/json'
}
});
} else {
httpRequest = $http({
url: resoureurlBase+methodName,
method: method,
data: payload,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
});
}
httpRequest.then(function(response) {
if (callbackFn && callbackFn.call) {
callbackFn.call(null, response);
}
},
function(response) {
if (callbackError && callbackError.call) {
callbackError.call(response);
}
});
httpRequest.error(function(data, status, headers, config) {
});
};
return factory;
});
/*
I have written service like above how can i handle in controller
i mean
how to write call back function in controller
how to inject
etc..
*/
Simple DI(dependency injection) it into your controller:-
myapp.controller('myCtrl',['$scope','serviceName',function($scope,serviceName){
// use serviceName to call your factory function
}]);
Ref:- https://docs.angularjs.org/guide/di
You need to call service like
serviceName.genericService(--parmas--).then(function(d){
//success
})
because from service serviceName, you're returning a promise that need to resolved using .then only.
Controller
var mainController = function($scope, serviceName) {
var callbackFn = function() {
console.log('Success');
}
var callbackError = function() {
console.log('Error');
}
var parameter = {
param1: 1
},
method = 'something', payload = 100, methodName = 'something';
serviceName.genericService(method, payload, methodName, callbackFn, callbackError, parameter).then(
//success function
function(data) {
//call after call succeed
},
//error function
function(error) {
//call after call error
});
};
myapp.controller('mainController', ['$scope', 'serviceName', mainController()];
Hope this could help you. Thanks.
I am stuck here, I don't know what I am missing or how to debug this further. I continue to get this error: 'updateMemberServiceFactory is undefined' when I call it from an ng-click event. Please advise. If this is a simple typo I apologize I just can't see what's wrong. I'm trying to call into a PUT method on my controller but it never gets called. New to AngularJS. Thank you.
securityApp.factory('updateMemberServiceFactory', function ($http) {
function update(memberServiceID) {
$http({ method: 'PUT', url: 'http://localhost:62791/api/MemberServices/', data: { memberServiceID: memberServiceID } })
.then(function (result) {
alert('success');
}, function (errorResponse) {
});
};
});
securityApp.controller('memberServicesController', function ($scope, $http, $routeParams, $location, getTokenFromServer, updateMemberServiceFactory) {
var id = $routeParams.memberID;
$scope.username = 'aharris1#test.com';
$scope.password = 'SuperPass1!';
getTokenFromServer.getToken($scope.username, $scope.password).then(function (data) {
$scope.token = data;
$http({ method: 'GET', url: '/api/MemberServices/' + id + '?access_token=' + $scope.token, headers: { 'Authorization': 'Bearer ' + $scope.token } })
.success(function (response) {
$scope.memberServices = "";
$scope.memberServices = response;
$http({ method: 'GET', url: '/api/Members/' + id + '?access_token=' + $scope.token, headers: { 'Authorization': 'Bearer ' + $scope.token } })
.success(function (response) {
$scope.member = response;
});
$http.get('/api/ServiceTypes/')
.then(function (response) {
$scope.serviceTypes = response.data;
});
});
});
$scope.updateMemberService = function () {
updateMemberServiceFactory.update( { memberServiceID: memberServiceID }, null, function () {
alert('update called');
});
};
});
<i class="fa fa-save"></i>
When you use someApp.factory(someFunction) the some someFunction should return an object that will be injected when needed.
In your case:
securityApp.factory('updateMemberServiceFactory', function ($http) {
function update(memberServiceID) {
$http({ method: 'PUT', url: 'http://localhost:62791/api/MemberServices/', data: { memberServiceID: memberServiceID } })
.then(function (result) {
alert('success');
}, function (errorResponse) {
});
};
return { // <---- this object will get injected, when required
update : update
}
});