I found this service (see below) on GitHub and want to know how to use this service on > click of button. I am using this in my Ionic app for log in using Google+ OAuth.
I am new to AngularJS. Help me.
var googleLoginService = angular.module('GoogleLoginService', ['ngStorage']);
googleLoginService.factory('timeStorage', ['$localStorage', function ($localStorage) {
var timeStorage = {};
timeStorage.cleanUp = function () {
var cur_time = new Date().getTime();
for (var i = 0; i < localStorage.length; i++) {
var key = localStorage.key(i);
if (key.indexOf('_expire') === -1) {
var new_key = key + "_expire";
var value = localStorage.getItem(new_key);
if (value && cur_time > value) {
localStorage.removeItem(key);
localStorage.removeItem(new_key);
}
}
}
};
timeStorage.remove = function (key) {
this.cleanUp();
var time_key = key + '_expire';
$localStorage[key] = false;
$localStorage[time_key] = false;
};
timeStorage.set = function (key, data, hours) {
this.cleanUp();
$localStorage[key] = data;
var time_key = key + '_expire';
var time = new Date().getTime();
time = time + (hours * 1 * 60 * 60 * 1000);
$localStorage[time_key] = time;
};
timeStorage.get = function (key) {
this.cleanUp();
var time_key = key + "_expire";
if (!$localStorage[time_key]) {
return false;
}
var expire = $localStorage[time_key] * 1;
if (new Date().getTime() > expire) {
$localStorage[key] = null;
$localStorage[time_key] = null;
return false;
}
return $localStorage[key];
};
return timeStorage;
}]);
googleLoginService.factory('googleLogin', [
'$http', '$q', '$interval', '$log', 'timeStorage',
function ($http, $q, $interval, $log, timeStorage) {
var service = {};
service.access_token = false;
service.redirect_url = 'http://127.0.0.1:81/google_demo/www/';
service.client_id = '1234567890';
service.secret = 'xxxxxxxxxxxxxxxxx';
service.scope = 'https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/plus.me';
service.gulp = function (url, name) {
url = url.substring(url.indexOf('?') + 1, url.length);
return url.replace('code=', '');
};
service.authorize = function (options) {
var def = $q.defer();
var self = this;
var access_token = timeStorage.get('google_access_token');
if (access_token) {
$log.info('Direct Access Token :' + access_token);
service.getUserInfo(access_token, def);
} else {
var params = 'client_id=' + encodeURIComponent(options.client_id);
params += '&redirect_uri=' + encodeURIComponent(options.redirect_uri);
params += '&response_type=code';
params += '&scope=' + encodeURIComponent(options.scope);
var authUrl = 'https://accounts.google.com/o/oauth2/auth?' + params;
var win = window.open(authUrl, '_blank', 'location=no,toolbar=no,width=800, height=800');
var context = this;
if (ionic.Platform.isWebView()) {
console.log('using in app browser');
win.addEventListener('loadstart', function (data) {
console.log('load start');
if (data.url.indexOf(context.redirect_url) === 0) {
console.log('redirect url found ' + context.redirect_url);
console.log('window url found ' + data.url);
win.close();
var url = data.url;
var access_code = context.gulp(url, 'code');
if (access_code) {
context.validateToken(access_code, def);
} else {
def.reject({error: 'Access Code Not Found'});
}
}
});
} else {
console.log('InAppBrowser not found11');
var pollTimer = $interval(function () {
try {
console.log("google window url " + win.document.URL);
if (win.document.URL.indexOf(context.redirect_url) === 0) {
console.log('redirect url found');
win.close();
$interval.cancel(pollTimer);
pollTimer = false;
var url = win.document.URL;
$log.debug('Final URL ' + url);
var access_code = context.gulp(url, 'code');
if (access_code) {
$log.info('Access Code: ' + access_code);
context.validateToken(access_code, def);
} else {
def.reject({error: 'Access Code Not Found'});
}
}
} catch (e) {
}
}, 100);
}
}
return def.promise;
};
service.validateToken = function (token, def) {
$log.info('Code: ' + token);
var http = $http({
url: 'https://www.googleapis.com/oauth2/v3/token',
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
params: {
code: token,
client_id: this.client_id,
client_secret: this.secret,
redirect_uri: this.redirect_url,
grant_type: 'authorization_code',
scope: ''
}
});
var context = this;
http.then(function (data) {
$log.debug(data);
var access_token = data.data.access_token;
var expires_in = data.data.expires_in;
expires_in = expires_in * 1 / (60 * 60);
timeStorage.set('google_access_token', access_token, expires_in);
if (access_token) {
$log.info('Access Token :' + access_token);
context.getUserInfo(access_token, def);
} else {
def.reject({error: 'Access Token Not Found'});
}
});
};
service.getUserInfo = function (access_token, def) {
var http = $http({
url: 'https://www.googleapis.com/oauth2/v3/userinfo',
method: 'GET',
params: {
access_token: access_token
}
});
http.then(function (data) {
$log.debug(data);
var user_data = data.data;
var user = {
name: user_data.name,
gender: user_data.gender,
email: user_data.email,
google_id: user_data.sub,
picture: user_data.picture,
profile: user_data.profile
};
def.resolve(user);
});
};
service.getUserFriends = function () {
var access_token = this.access_token;
var http = $http({
url: 'https://www.googleapis.com/plus/v1/people/me/people/visible',
method: 'GET',
params: {
access_token: access_token
}
});
http.then(function (data) {
console.log(data);
});
};
service.startLogin = function () {
var def = $q.defer();
var promise = this.authorize({
client_id: this.client_id,
client_secret: this.secret,
redirect_uri: this.redirect_url,
scope: this.scope
});
promise.then(function (data) {
def.resolve(data);
}, function (data) {
$log.error(data);
def.reject(data.error);
});
return def.promise;
};
return service;
}
]);
angular
.module('GoogleLoginService')
.controller('SomeController', SomeController);
function SomeController(timeStorage, googleLogin) {
// just call timeStorage and googleLogin
// ex:
var anydata = timeStorage.get("anykey");
}
Related
I have a controller that passes execution to a factory -- controller.getCustomerById -> factory.getCustomerByID. In this case, the factory function is posting and retrieving data via MVC/angular.$http.post. That all works fine but the subsequent actions in my controller function are executing before the .post is finished.
I've tried making either or both async/await but I think I'm not understanding how to do that. I've tried quite a few of the examples here and elsewhere with no luck.
I have a button that calls setOrderFromGrid which calls getCustomerById. I would assume that making controller.getCustomerById an async function would be the best way but I can't get it to work.
angular.module('aps').factory('TechSheetFactory',
function($http) {
return {
//The ajax that is called by our controller
ITS: function(onSuccess, onFailure) {
const rvtoken = $("input[name='__RequestVerificationToken']").val();
$http({
method: "post",
url: "/DesktopModules/MVC/TechSheetMaint/TechSheet/InitializeNew",
headers: {
"ModuleId": moduleId,
"TabId": tabId,
"RequestVerificationToken": rvtoken
}
}).then(onSuccess).catch(onFailure);
},
saveTechSheetAng: function(onSuccess, onFailure, techSheetInfo) {
alert(JSON.stringify(techSheetInfo));
const rvtoken = $("input[name='__RequestVerificationToken']").val();
$http.post("/DesktopModules/MVC/TechSheetMaint/TechSheet/SaveTechSheetAng",
JSON.stringify(techSheetInfo),
{
headers: {
"ModuleId": moduleId,
"TabId": tabId,
"RequestVerificationToken": rvtoken,
'Content-Type': 'application/json'
}
}).then(onSuccess).catch(onFailure);
} ,
getCustomerById: function(onSuccess, onFailure, customerSearchString) {
alert('factory getcustomerbyid: ' + customerSearchString);
const rvtoken = $("input[name='__RequestVerificationToken']").val();
$http.post("/DesktopModules/MVC/TechSheetMaint/TechSheet/GetCustomerById",
{custId:customerSearchString},
{
headers: {
"ModuleId": moduleId,
"TabId": tabId,
"RequestVerificationToken": rvtoken,
'Content-Type': 'application/json'
}
}).then(onSuccess).catch(onFailure);
}
};
});
angular.module('aps').controller('TechSheetCtl', ['TechSheetFactory','$scope', '$rootScope', '$http', '$interval', '$modal', '$log','uiGridConstants',
function (TechSheetFactory,$scope, $rootScope, $http, $interval, $modal, $log) {
/* -----------------SaveTechSheet ------------*/
$scope.saveTechSheet = function() {
if (!$scope.dvTechSheet.$valid) {
$scope.Message = "Form not complete.";
$scope.Status = false;
$scope.showErrors=true;
return;
}
alert($scope.TechSheetInfo.Customer.CustomerID);
if (JSON.stringify($scope.TechSheetInfo.Customer) !== JSON.stringify($scope.TechSheetInfoStatic.Customer) &&
$scope.TechSheetInfo.Customer.CustomerID !== 0) {
if (confirm("You've made changes to this Customer. Save them?") !== true) {
return;
}
}
if (JSON.stringify($scope.TechSheetInfo.WorkOrder) !== JSON.stringify($scope.TechSheetInfoStatic.WorkOrder) &&
$scope.TechSheetInfo.WorkOrder.WorkOrderID !== 0) {
if (confirm("You've made changes to this Work Order. Save them?") !== true) {
return;
}
}
successFunction = function(response) {
var data = response.data.Data;
alert(data);
var techSheet = data.techSheet;
alert(data.status);
if (data.status) {
alert("looks good");
$scope.Message = "";
$scope.showErrors = false;
$scope.TechSheetInfo = techSheet;
alert($scope.TechSheetInfo);
$scope.TechSheetInfoStatic = angular.copy(techSheet);
$rootScope.customerInfo = techSheet.Customer;
createpdf($scope);
} else {
if (response.message !== null) {
$scope.Status = datae.status;
$scope.showErrors = true;
$scope.Message = data.message;
}
}
};
failureFunction = function(data) {
console.log('Error' + data);
};
TechSheetFactory.saveTechSheetAng(successFunction, failureFunction,$scope.TechSheetInfo);
};
/* ----------End SaveTechSheet ---------*/
//------------Initialize a new tech sheet. This is the default action for the page load/refresh/discard changes/clear form
$scope.initializeTechSheet = function() {
$scope.TechSheetInfo = [];
$scope.TechSheetInfoStatic = [];
$scope.customerIDDisabled = false;
$scope.orderIDDisabled = false;
$rootScope.customerInfo = [];
$scope.WindowsPassword = "";
$scope.EmailPassword = "";
const successFunction = function(response) {
$scope.TechSheetInfo = response.data;
$rootScope.customerInfo = response.data.Customer;
$scope.TechSheetInfoStatic = angular.copy(response.data);
};
const failureFunction = function(response) {
//console.log('Error' + response.status);
};
TechSheetFactory.ITS(successFunction, failureFunction);
};
//end initializeTechSheet
$scope.getCustomerById = function(custId) {
const successFunction = function(response) {
alert("success");
$scope.TechSheetInfo.Customer = response.data;
$scope.TechSheetInfoStatic.Customer = angular.copy(response.data);
$rootScope.customerInfo = response.data;
$scope.customerIDDisabled = true;
};
const failureFunction = function(data) {
alert('getcustomer fail');
console.log('Error' + JSON.stringify(data));
};
TechSheetFactory.getCustomerById(successFunction, failureFunction, custId);
};
$scope.setOrderFromGrid = function(woInfo) {
$scope.getCustomerById(woInfo.CustomerID);
$scope.TechSheetInfo.WorkOrder = woInfo; //this line and the next are occurring before getCustomerById has completed
$scope.TechSheetInfoStatic.Customer = angular.copy($scope.TechSheetInfo.Customer);
$scope.orderIDDisabled=true;
$scope.dvTechSheet.$setPristine();
};
$scope.resetForm = function() {
if (!$scope.dvTechSheet.$pristine) {
if (!confirm("Discard Changes?")) {
return;
}
}
$scope.initializeTechSheet();
$scope.dvTechSheet.$setPristine();
};
}]);
You lose the advantage of the Promises so you can opt-in a Promise this way. (I do not recommend it)
From the top of head something like this:
// inject $q
$scope.getCustomerById = function(custId) {
const deferred = $q.defer()
const successFunction = function(response) {
$scope.TechSheetInfo.Customer = response.data;
$scope.TechSheetInfoStatic.Customer = angular.copy(response.data);
$rootScope.customerInfo = response.data;
$scope.customerIDDisabled = true;
deferred.resolve(); // can pass value if you like
};
const failureFunction = function(data) {
alert('getcustomer fail');
console.log('Error' + JSON.stringify(data));
deferred.reject();
};
TechSheetFactory.getCustomerById(successFunction, failureFunction, custId);
return deferred.promise;
};
/////////////
$scope.setOrderFromGrid = function(woInfo) {
const prom = $scope.getCustomerById(woInfo.CustomerID);
prom.then(()=>{
$scope.TechSheetInfo.WorkOrder = woInfo;
$scope.TechSheetInfoStatic.Customer =
angular.copy($scope.TechSheetInfo.Customer);
$scope.orderIDDisabled=true;
$scope.dvTechSheet.$setPristine();
})
};
Mentioned on the github repository #225 of angular-service-modal
But i don't have a $on on $rootScope, so that shouldn't be the problem.
(also included code below)
My modal is getting called multiple times on close/hiding. Eg. [http://beta.belgianbrewed.com/en/product/budweiser-24x30cl](Example page)
The file in question can be found on /assets/angular/controllers/ShopActionController.js
Any thoughts where the problem could be?
The code calls: showPopup(ProductId,'BuyImmediate') in ShopActionController.js
app.controller('ShopActionDialogController', ['$scope', 'CurrentProduct', function ($scope, CurrentProduct) {
$scope.CurrentProduct = CurrentProduct;
console.log("Dialog called and ...");
console.log(CurrentProduct);
//modal.element.modal();
//modal.close.then(function (result) {
// $scope.message = result ? "You said Yes" : "You said No";
//});
}]);
app.controller('ShopActionController', ['$rootScope', '$scope', '$injector', '$http', '$timeout', 'ModalService', 'EndpointService', 'ImageResizeService', 'hotkeys',
function ($rootScope, $scope, $injector, $http, $timeout, ModalService, EndpointService, ImageResizeService, hotkeys) {
$scope.Resize = ImageResizeService;
$scope.Amount;
$scope.InitAmount;
$scope.ProductId;
$scope.ProductVariantId;
$scope.OrderLineId;
$scope.isLoading = false;
$scope.isShown = true;
//$scope.addedToCart = false; //new - not implemented
$scope.inCartAmount = 0; //new - not implemented
$scope.inWishList = false;
$scope.Change = function (Amount) {
$scope.Amount += Amount;
}
$scope.showPopup = function (ProductId,action) {
EndpointService.searchProducts(undefined, 0, 1, ProductId).then(function (response) {
ModalService.showModal({
templateUrl: "ProductPopup.html",
controller: "ShopActionDialogController",
inputs: {
CurrentProduct: response.data[0]
}
}).then(function (modal) {
// The modal object has the element built, if this is a bootstrap modal
// you can call 'modal' to show it, if it's a custom modal just show or hide
// it as you need to.
// console.log("test");
modal.element.modal();
var args = {
Amount: $scope.Amount,
ProductId: response.data[0].Id,
ProductVariantId: response.data[0].ProductVariantId,
OrderLineId: undefined,
InitAmount : $scope.InitAmount
};
if (action != undefined) {
args.Action = action;
}
$rootScope.$broadcast('init', args);
$scope.Amount = $scope.InitAmount;
modal.element.on('hidden.bs.modal', function (e) {
// $scope.Amount = $scope.InitAmount;
console.log("hidden");
modal.element.remove();
// close(result, 200);
});
modal.close.then(function (result) {
// console.log("close");
$scope.Amount = $scope.InitAmount;
modal.element.remove();
// close(result, 200);
//ModalService.closeModals();
// $scope.message = result ? "You said Yes" : "You said No";
});
});
});
}
$scope.CurrentProduct;// = CurrentProduct;
$scope.initiated = false;
var initListener = $scope.$on('init', function (event,args) {
if (!$scope.initiated) {
$scope.Amount = args.Amount;
$scope.InitAmount = args.InitAmount;
$scope.ProductId = args.ProductId;
$scope.ProductVariantId = args.ProductVariantId;
$scope.OrderLineId = args.OrderLineId;
switch (args.Action)
{
case 'BuyImmediate':
$scope.AddToCart();
break;
case 'View':
break;
}
}
});
$scope.$on('$destroy', function () {
console.log("killing this scope");
initListener();
});
$scope.init = function (Amount, ProductId, ProductVariantId, OrderLineId) {
$scope.initiated = true;
$scope.Amount = Amount;
$scope.InitAmount = Amount;
$scope.ProductId = ProductId;
$scope.ProductVariantId = ProductVariantId;
$scope.OrderLineId = OrderLineId;
}
$scope.getSpecification = function (Product,SpecificationId, SpecificationName) {
var Spec = undefined;
angular.forEach(Product.Specifications, function (elem, i) {
if (elem.SpecificationCandidate.SpecificationId == SpecificationId ||
elem.SpecificationCandidate.Specification.Name == SpecificationName) {
Spec = elem.SpecificationCandidate;
}
});
return Spec;
}
$scope.isAddedInCart = function () {
return $scope.OrderLineId != undefined;
}
$scope.PriceInclusive = function (orderline) {
return orderline.Amount * orderline.Product.Price * 1.21;
}
$scope.PriceExclusive = function (orderline) {
return orderline.Amount * orderline.Product.Price;
}
$scope.bindKeys = function () {
hotkeys.add({
combo: '+',
description: 'Add 1 to ammount',
callback: function () {
$scope.Amount += 1;
}
});
hotkeys.add({
combo: '-',
description: 'Substract 1 from ammount',
callback: function () {
if ($scope.Amount > 0) {
$scope.Amount -= 1;
}
}
});
}
$scope.IncrementWith = function (Amount) {
var newAmount = $scope.Amount + Amount;
if (newAmount >= 0) {
$scope.Amount = newAmount;
}
}
$scope.ChangeSortBy = function (SortBy) {
console.log("Changing Sort By");
}
$scope.ChangePageSize = function (PageSize) {
console.log("Changing PageSize");
}
$scope.GetCart = function () {
return EndpointService.orderlines;
}
$scope.RemoveOrderLine = function ($event) {
$scope.isLoading = true;
EndpointService.removeOrderLine($scope.OrderLineId)
.then(function (response) {
EndpointService.orderlines = response.data;
$rootScope.$broadcast('DeleteOrderLine', { OrderLineId: $scope.OrderLineId });
$scope.isLoading = false;
$scope.isShown = false;
});
$event.preventDefault();
return false;
}
$scope.AddToWishlist = function () {
//AddToWishlist
EndpointService.addToWishList($scope.ProductId)
.then(function (response) {
//return true;
$scope.inWishList = true;
});
return false;
}
$scope.RemoveFromWishlist = function () {
EndpointService.removeFromWishList($scope.ProductId)
.then(function (response) {
//return true;
$scope.isShown = false;
});
return false;
}
$scope.PrepareAddOrderLineRequest = function (onlyBulk) {
if (!onlyBulk || (onlyBulk && $scope.InitAmount == 0 && $scope.InitAmount < $scope.Amount)) {
var request = EndpointService.UpdateAmountRequest;
request.OrderLineId = $scope.OrderLineId;
request.Amount = $scope.Amount;
request.ProductId = $scope.ProductId;
return request;
} else {
return undefined;
}
}
$scope.FocusAmountInput = function () {
if ($scope.Amount == $scope.InitAmount) {
$scope.Amount = "";
}
}
$scope.LeaveAmountInput = function () {
if ($scope.Amount == "") {
$scope.Amount = $scope.InitAmount;
}
}
$scope.$on("BroadCastBulkOrders", function () {
var request = $scope.PrepareAddOrderLineRequest(true);
if (request != undefined) {
$rootScope.$broadcast("AddBulkOrder", request);
$scope.Amount = $scope.InitAmount;
}
});
$scope.AddToCart = function () {
$scope.isLoading = true;
var request = $scope.PrepareAddOrderLineRequest(false);
EndpointService.updateAmount(request)
.then(function (response) {
EndpointService.orderlines = response.data;
$rootScope.$broadcast('BasketChanged');
angular.forEach(response.data, function (elem, i) {
if (elem.ProductId == $scope.ProductId) {
$scope.OrderLineId = elem.Id;
$scope.inCartAmount = elem.Amount;
}
});
$scope.Amount = $scope.InitAmount;
$scope.isLoading = false;
});
return false;
}
$scope.UpdateOrderLine = function () {
//$emit required values
$scope.isLoading = true;
var request = $scope.PrepareAddOrderLineRequest(false);
request.isFixed = true;
EndpointService.updateAmount(request)//$scope.OrderLineId, $scope.ProductId, $scope.Amount, true)
.then(function (response) {
angular.forEach(response.data, function (elem, i) {
if (elem.Id == $scope.OrderLineId) {
$rootScope.$broadcast('ChangeAmount', { OrderLineId: $scope.OrderLineId, Amount: $scope.Amount });
}
});
$scope.isLoading = false;
});
return false;
}
}]);
The service
app.service('EndpointService', ['$http', '$q', function ($http, $q) {
this.orderlines = new Array();
//search for products, standard paging included
this.searchProducts = function (searchTerm, page, pageSize, productId) {
var endPoint = "/api/Endpoint/SearchProducts?$expand=Tags,Specifications($expand=SpecificationCandidate($expand=Specification)),CoverPhoto";
if (searchTerm != undefined && searchTerm.length > 0) {
endPoint = endPoint + "&$filter=indexof(Title,'" + searchTerm + "') gt -1"; //make a var
} else if (productId !== undefined) {
{
endPoint = endPoint + "&$filter=Id eq " + productId + " "; //make a var
}
//endPoint = endPoint + "&$filter=";
}
endPoint = endPoint + "&$skip=0&$top=" + pageSize;
return $http.get(endPoint);
//.then(function (response) {
// //console.log(response.data);
// return response.data;
//})
}
// this.ShippingCost = $q.defer();
this.ShippingCost = new Object();
this.calculateShipping = function (address, shippingMethodId) {
if (address == undefined) {
return this.ShippingCost;
} else {
//https://appendto.com/2016/02/working-promises-angularjs-services/
//var deferred = $q.defer();
var endPoint = "/api/Endpoint/CalculateShippingCost?timestamp=" + Date.now();
return $http({
url: endPoint,
method: "GET",
params: {
DeliveryAddress: address,
ShippingMethodId: shippingMethodId,
timestamp: Date.now()
}
})
}
}
this.getOrderLines = function () {
var endPoint = "/api/Endpoint/GetOrder";
return $http({
url: endPoint,
method: "GET",
params: {
timestamp : Date.now()
}
})
.then(function (response) {
this.orderlines = response.data;
return this.orderlines;
});
}
this.removeOrderLine = function (OrderLineId) {
var endPoint = "/api/Endpoint/RemoveOrderLine";
return $http({
url: endPoint,
method: "POST",
params: {
OrderLineId: OrderLineId
}
});
}
this.addToWishList = function (ProductId) {
var endPoint = "/api/Endpoint/AddToWishlist";
return $http({
url: endPoint + "?ProductId=" + ProductId,
method: "GET"
});
}
this.removeFromWishList = function (ProductId) {
var endPoint = "/api/Endpoint/RemoveFromWishlist";
return $http({
url: endPoint + "?ProductId=" + ProductId,
method: "GET"
});
}
this.UpdateAmountRequest = {
ProductId: "",
Amount: 0,
OrderLineId: "",
isFixed : false
}
this.bulkUpdateAmount = function (request) {
var endPoint = "/api/Endpoint/BulkAddOrderLines";
return $http({
url: endPoint,
method: "POST",
headers: {
'Content-Type': "application/json"
},
data: request
});
}
this.updateAmount = function (request){//OrderLineId,ProductId, Amount, isFixed) {
var endPoint = "/api/Endpoint/AddOrderLine?timestamp="+ Date.now();
//console.log("hey, changing the amount " + Amount + " for product id " + ProductId + " are you? :) ");
return $http({
url: endPoint,
method: "POST",
headers: {
'Content-Type': "application/json"
},
data: request
});
}
}]);
You need to add your bootstrap modal hidden listener to the dialog controller context.
app.controller('ShopActionDialogController', ['$scope', '$element', 'CurrentProduct', 'close', function ($scope, $element, CurrentProduct, close) {
$scope.CurrentProduct = CurrentProduct;
console.log("Dialog called and ...");
console.log(CurrentProduct);
//modal.element.modal();
//modal.close.then(function (result) {
// $scope.message = result ? "You said Yes" : "You said No";
//});
//listen for when the modal is dismissed and resolve the ModalService Close promise
$element.on('hidden.bs.modal', function (e) {
close({
currentProduct: CurrentProduct
}, 200); // close, but give 200ms for bootstrap to animate
});
}]);
Note that $element and close were added to the controller dependencies.
My Issue
Everything working fine with $post but when I update it to $resource,
I am getting error of unsupported_grant_type.
I tried many solutions from SO, but unable to resolve this issue.
Below is my code.
Controller
$scope.login = function () {
authService.login($scope.loginData).promise.then(function (response) {
if (document.referrer != "" && document.referrer != window.location.href) {
window.location.href = document.referrer;
}
else {
window.location.href = "/Roles/Index"
}
}
};
Service
app.factory('authService', ['$http', '$q', 'localStorageService', '$resource', '$rootScope',
function ($http, $q, localStorageService, $resource, $rootScope) {
var authServiceFactory = {};
var _authentication = {
isAuth: false,
userName: ""
};
var url = function (relativeUrl) {
return $rootScope.apiBaseUrl + '/api/' + relativeUrl;
};
var authResource = $resource(url('account/:id'), null, {
register: {
method: 'POST',
url: url('account/register')
},
login: {
method: 'POST',
url: $rootScope.apiBaseUrl + '/token'
}
},
{
headers: {
'Access-Control-Allow-Origin': '*',
'Content-Type': 'application/x-www-form-urlencoded'
}
});
var _login = function (loginData) {
// var data = "grant_type=password&username=" + loginData.userName + "&password=" + loginData.password;
loginData.grant_type = "password";
var deferred = $q.defer();
authResource.login($.param(loginData)).$promise
.then(function (response) {
localStorageService.set('authorizationData', { token: response.access_token, userName: loginData.userName });
_authentication.isAuth = true;
_authentication.userName = loginData.userName;
deferred.resolve(response);
});
return deferred;
};
var _fillAuthData = function () {
var authData = localStorageService.get('authorizationData');
if (authData) {
_authentication.isAuth = true;
_authentication.userName = authData.userName;
}
}
authServiceFactory.saveRegistration = _saveRegistration;
authServiceFactory.login = _login;
authServiceFactory.logOut = _logOut;
authServiceFactory.fillAuthData = _fillAuthData;
authServiceFactory.authentication = _authentication;
return authServiceFactory;
}]);
What I found from so many tries?
I found that, My request does not have any headers.
The twitter login is used by my app using ionic framework, and i want to get email address from twitter, i have requested twitter and app is now able to get email address.
But somehow the code below is not able to get email address.
For this i have created new function named getTwitterProfileManual but still it is not working.
I have also read document provided by twitter at Doc and as suggested i am also passing include_email params as request query. But still response do not have email address in it.
serviceModule.factory('TwitterService', function ($cordovaOauth, $cordovaOauthUtility, $http, $resource, $q, AUTH_ID)
{
var twitterKey = "STORAGE.TWITTER.KEY";
var clientId = AUTH_ID.TWITTER_APP_ID;
var clientSecret = AUTH_ID.TWITTER_APP_SEC;
function storeUserToken(data)
{
window.localStorage.setItem(twitterKey, JSON.stringify(data));
}
function getStoredToken()
{
return window.localStorage.getItem(twitterKey);
}
function createTwitterSignature(method, url, params)
{
if (!params) {
params = {};
}
var token = angular.fromJson(getStoredToken());
var oauthObject = {
oauth_consumer_key: clientId,
oauth_nonce: $cordovaOauthUtility.createNonce(10),
oauth_signature_method: "HMAC-SHA1",
oauth_token: token.oauth_token,
oauth_timestamp: Math.round((new Date()).getTime() / 1000.0),
oauth_version: "1.0"
};
console.log(JSON.stringify(oauthObject));
var signatureObj = $cordovaOauthUtility.createSignature(method, url, oauthObject, params, clientSecret, token.oauth_token_secret);
$http.defaults.headers.common.Authorization = signatureObj.authorization_header;
console.log(JSON.stringify(signatureObj.authorization_header));
}
return {
initialize: function ()
{
var deferred = $q.defer();
var token = getStoredToken();
if (token !== null)
{
deferred.resolve(true);
}
else
{
$cordovaOauth.twitter(clientId, clientSecret).then(function (result)
{
storeUserToken(result);
deferred.resolve(true);
}, function (error)
{
deferred.reject(false);
});
}
return deferred.promise;
},
isAuthenticated: function ()
{
return getStoredToken() !== null;
},
getHomeTimeline: function ()
{
var home_tl_url = 'https://api.twitter.com/1.1/statuses/home_timeline.json';
createTwitterSignature('GET', home_tl_url);
return $resource(home_tl_url).query();
},
getTwitterProfile: function ()
{
var tl_url = 'https://api.twitter.com/1.1/account/verify_credentials.json';
createTwitterSignature('GET', tl_url);
return $resource(tl_url, {'include_email': true}).query();
},
getTwitterProfileManual: function () {
var deferred = $q.defer();
var token = angular.fromJson(getStoredToken());
createTwitterSignature('GET', 'https://api.twitter.com/1.1/account/verify_credentials.json');
// $http.get("https://api.twitter.com/1.1/account/verify_credentials.json")
$http({
method: 'GET',
url: "https://api.twitter.com/1.1/account/verify_credentials.json",
params : { 'include_email': true }
}).success(function (result)
{
console.log(result);
alert('USER TIMELINE: ' + JSON.stringify(result));
deferred.resolve(result);
}).error(function (error)
{
alert("Error: " + JSON.stringify(error));
deferred.reject(false);
});
return deferred.promise;
},
storeUserToken: storeUserToken,
getStoredToken: getStoredToken,
createTwitterSignature: createTwitterSignature
};
});
Does anyone came across such problem and solved it, if so please provide some hint.
After days of working i finally made it working.
Below is the code for anyone who will face such issue.
Code :
serviceModule.factory('$twitterHelpers', ['$q', '$http', function ($q, $http) {
function createSignature(method, endPoint, headerParameters, bodyParameters, secretKey, tokenSecret) {
if (typeof jsSHA !== "undefined") {
var headerAndBodyParameters = angular.copy(headerParameters);
var bodyParameterKeys = Object.keys(bodyParameters);
for (var i = 0; i < bodyParameterKeys.length; i++) {
headerAndBodyParameters[bodyParameterKeys[i]] = escapeSpecialCharacters(bodyParameters[bodyParameterKeys[i]]);
}
var signatureBaseString = method + "&" + encodeURIComponent(endPoint) + "&";
var headerAndBodyParameterKeys = (Object.keys(headerAndBodyParameters)).sort();
for (i = 0; i < headerAndBodyParameterKeys.length; i++) {
if (i == headerAndBodyParameterKeys.length - 1) {
signatureBaseString += encodeURIComponent(headerAndBodyParameterKeys[i] + "=" + headerAndBodyParameters[headerAndBodyParameterKeys[i]]);
} else {
signatureBaseString += encodeURIComponent(headerAndBodyParameterKeys[i] + "=" + headerAndBodyParameters[headerAndBodyParameterKeys[i]] + "&");
}
}
var oauthSignatureObject = new jsSHA(signatureBaseString, "TEXT");
var encodedTokenSecret = '';
if (tokenSecret) {
encodedTokenSecret = encodeURIComponent(tokenSecret);
}
headerParameters.oauth_signature = encodeURIComponent(oauthSignatureObject.getHMAC(encodeURIComponent(secretKey) + "&" + encodedTokenSecret, "TEXT", "SHA-1", "B64"));
var headerParameterKeys = Object.keys(headerParameters);
var authorizationHeader = 'OAuth ';
for (i = 0; i < headerParameterKeys.length; i++) {
if (i == headerParameterKeys.length - 1) {
authorizationHeader += headerParameterKeys[i] + '="' + headerParameters[headerParameterKeys[i]] + '"';
} else {
authorizationHeader += headerParameterKeys[i] + '="' + headerParameters[headerParameterKeys[i]] + '",';
}
}
return {signature_base_string: signatureBaseString, authorization_header: authorizationHeader, signature: headerParameters.oauth_signature};
} else {
return "Missing jsSHA JavaScript library";
}
}
function createNonce(length) {
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for (var i = 0; i < length; i++) {
text += possible.charAt(Math.floor(Math.random() * possible.length));
}
return text;
}
function escapeSpecialCharacters(string) {
var tmp = encodeURIComponent(string);
tmp = tmp.replace(/\!/g, "%21");
tmp = tmp.replace(/\'/g, "%27");
tmp = tmp.replace(/\(/g, "%28");
tmp = tmp.replace(/\)/g, "%29");
tmp = tmp.replace(/\*/g, "%2A");
return tmp;
}
function transformRequest(obj) {
var str = [];
for (var p in obj)
str.push(encodeURIComponent(p) + "=" + escapeSpecialCharacters(obj[p]));
console.log(str.join('&'));
return str.join('&');
}
return {
createTwitterSignature: function (method, url, bodyParameters, clientId, clientSecret, token) {
var oauthObject = {
oauth_consumer_key: clientId,
oauth_nonce: createNonce(10),
oauth_signature_method: "HMAC-SHA1",
oauth_token: token.oauth_token,
oauth_timestamp: Math.round((new Date()).getTime() / 1000.0),
oauth_version: "1.0"
};
var signatureObj = createSignature(method, url, oauthObject, bodyParameters, clientSecret, token.oauth_token_secret);
$http.defaults.headers.common.Authorization = signatureObj.authorization_header;
return signatureObj;
},
transformRequest: transformRequest
};
}]);
serviceModule.factory('TwitterService', function ($cordovaOauth, $cordovaOauthUtility, $http, $resource, $q, AUTH_ID, $twitterHelpers)
{
var twitterKey = "STORAGE.TWITTER.KEY";
var clientId = AUTH_ID.TWITTER_APP_ID;
var clientSecret = AUTH_ID.TWITTER_APP_SEC;
function storeUserToken(data)
{
window.localStorage.setItem(twitterKey, JSON.stringify(data));
}
function getStoredToken()
{
return window.localStorage.getItem(twitterKey);
}
return {
initialize: function ()
{
var deferred = $q.defer();
var token = getStoredToken();
if (token !== null)
{
deferred.resolve(true);
}
else
{
$cordovaOauth.twitter(clientId, clientSecret).then(function (result)
{
storeUserToken(result);
deferred.resolve(true);
}, function (error)
{
deferred.reject(false);
});
}
return deferred.promise;
},
isAuthenticated: function ()
{
return getStoredToken() !== null;
},
getHomeTimeline: function ()
{
var home_tl_url = 'https://api.twitter.com/1.1/statuses/home_timeline.json';
createTwitterSignature('GET', home_tl_url);
return $resource(home_tl_url).query();
},
getTwitterProfileManual: function () {
var deferred = $q.defer();
var token = angular.fromJson(getStoredToken());
$twitterHelpers.createTwitterSignature('GET', 'https://api.twitter.com/1.1/account/verify_credentials.json', { 'include_email' : 'true' }, clientId, clientSecret, token);
$http({
method: 'GET',
url: "https://api.twitter.com/1.1/account/verify_credentials.json",
params: {'include_email': 'true'},
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
}).success(function (result)
{
console.log(result);
alert('USER TIMELINE: ' + JSON.stringify(result));
deferred.resolve(result);
}).error(function (error)
{
alert("Error: " + JSON.stringify(error));
deferred.reject(false);
});
return deferred.promise;
},
storeUserToken: storeUserToken,
getStoredToken: getStoredToken
};
});
From the above code use getTwitterProfileManual this function to get email address in twitter user object response.
Note : To get email address your twitter app must be whitelisted to have access to user email address.
I am just beginning to learn AngularJS and have a problem understanding promises. I have
factory which makes call to back-end server and returns a promise as follows:
var commonModule = angular.module("CommonModule", [])
.factory('AjaxFactory', function($http, $q, $dialogs, transformRequestAsFormPost) {
return {
post: function(reqUrl, formData) {
var deferred = $q.defer();
$http({
method: "post",
url: reqUrl,
transformRequest: transformRequestAsFormPost,
data: formData
}).success(function(data) {
if (data['error']) {
if (data['message']) {
$dialogs.notify('Error', data['message']);
} else {
}
} else if (data['success']) {
if (data['message']) {
$dialogs.notify('Message', data['message']);
}
} else if (data['validation']) {
}
deferred.resolve(data);
}).error(function(data) {
$dialogs.notify('Error', 'Unknown Error. Please contact administrator');
});
return deferred.promise;
}
};
})
.factory("transformRequestAsFormPost", function() {
function transformRequest(data, getHeaders) {
var headers = getHeaders();
headers[ "Content-type" ] = "application/x-www-form-urlencoded; charset=utf-8";
return(serializeData(data));
}
return(transformRequest);
function serializeData(data) {
if (!angular.isObject(data)) {
return((data === null) ? "" : data.toString());
}
var buffer = [];
for (var name in data) {
if (!data.hasOwnProperty(name)) {
continue;
}
var value = data[ name ];
buffer.push(
encodeURIComponent(name) +
"=" +
encodeURIComponent((value === null) ? "" : value)
);
}
var source = buffer
.join("&")
.replace(/%20/g, "+")
;
return(source);
}
}
);
I have a controller which calls the AjaxFactory service using two functions as follows
marketingCampaignModule.controller('CampaignInfoController', ['$scope', 'AjaxFactory', '$state', 'campaign', function($scope, AjaxFactory, $state, campaign) {
$scope.init = function() {
$scope.name = campaign['name'];
$scope.description = campaign['description'];
console.log($scope.mcmcid);
if ($scope.mcmcid > 0) {
var inputData = {};
inputData['mcmcid'] = $scope.mcmcid;
var ajaxPromise1 = AjaxFactory.post('index.php/mcm/infosave/view', inputData);
ajaxPromise1.then(function(data) {
if (data['success']) {
$scope.name = data['params']['name'];
$scope.description = data['params']['description'];
}
},
function(data) {
if (data['success']) {
$scope.name = data['params']['name'];
$scope.description = data['params']['description'];
}
}
);
}
};
$scope.init();
$scope.submitForm = function(isValid) {
if (isValid) {
var formData = $scope.prepareFormData();
var ajaxPromise = AjaxFactory.post('index.php/mcm/infosave/save', formData);
ajaxPromise.then(function(data) {
if (data['success']) {
$scope.setValues(data['params']);
} else if ('validation') {
$scope.handleServerValidationError(data['message']);
}
});
}
};
$scope.prepareFormData = function() {
mcmcId = '';
var formData = {};
if ($scope.mcmcid > 0) {
mcmcId = $scope.mcmcid;
}
formData["mcmcid"] = mcmcId;
formData["name"] = $scope.name;
formData["description"] = $scope.description;
return formData;
};
$scope.setValues = function(data) {
$scope.mcmcid = data['mcmcid'];
$state.go('TabsView.Companies');
};
$scope.handleServerValidationError = function(validationMessages) {
alert(validationMessages['name']);
};
}]);
The promise ajaxPromise gets resolved in the function $scope.submitform but not in $scope.init.
Please tell me what am I missing.
add to your service deffere.reject() on error:
app.factory('AjaxFactory', function($http, $q, $dialogs, transformRequestAsFormPost) {
return {
post: function(reqUrl, formData) {
var deferred = $q.defer();
$http({
method: "post",
url: reqUrl,
transformRequest: transformRequestAsFormPost,
data: formData
}).success(function(data) {
if (data['error']) {
if (data['message']) {
$dialogs.notify('Error', data['message']);
} else {
}
} else if (data['success']) {
if (data['message']) {
$dialogs.notify('Message', data['message']);
}
} else if (data['validation']) {
}
deferred.resolve(data);
}).error(function(data) {
deferred.reject(data)
$dialogs.notify('Error', 'Unknown Error. Please contact administrator');
});
return deferred.promise;
}
};
});
and in you controller handle error:
$scope.init = function () {
$scope.name = campaign['name'];
$scope.description = campaign['description'];
console.log($scope.mcmcid);
if ($scope.mcmcid > 0) {
var inputData = {};
inputData['mcmcid'] = $scope.mcmcid;
var ajaxPromise1 = AjaxFactory.post('index.php/mcm/infosave/view', inputData);
ajaxPromise1.then(function (data) {
if (data['success']) {
$scope.name = data['params']['name'];
$scope.description = data['params']['description'];
}
},
function (data) {
if (data['success']) {
$scope.name = data['params']['name'];
$scope.description = data['params']['description'];
}
},
//on error
function (data) {
alert("error");
console.log(data);
});
}
};