AngularUI Route Resolve Issue when Rejecting Promise - angularjs

I have included my code below. Basically, when I am loading my view, I am using resolve to get some data. In my service, if my promise is rejected - on error - the resolve gets infinitely called. Is there a better way I should be performing this?
(function () {
function AppService($q, $http, $log, $timeout, pageOptionsModel) {
return {
getPageOptions: function () {
var deferred = $q.defer();
var pageOptions = pageOptionsModel.getPageOptions();
if (pageOptions === null) {
$http.get("api/HomeApi/GetPageOptions")
.success(function (response) {
deferred.resolve(response);
$log.info("Successfully retriedved page options from service.");
})
.error(function (response) {
deferred.reject("Error");
$log.error("Errored while retrieving page options from service.");
});
}
else {
deferred.resolve(pageOptions);
}
return deferred.promise;
}
}
};
function AppConfig($stateProvider, $urlRouterProvider, $locationProvider) {
$urlRouterProvider.otherwise("line");
// Now set up the states
$stateProvider
.state('line', {
url: "/line",
templateUrl: "app/line/lineTemplate.html",
controller: "lineController",
controllerAs: "line",
resolve: {
pageOptions: function (appService) {
return appService.getPageOptions();
}
}
});
$locationProvider.html5Mode({
enabled: true,
requireBase: false
});
};
angular.module("app", ["ui.router", "ui.bootstrap", "app.line", "app.modal"])
.config(AppConfig)
.factory("appService", AppService);
})();
Here is my Line Controller which never initializes if my promise is rejected.
(function () {
function LineController($scope, pageOptions) {
var self = this;
// INITIALIZE
self.pageOptions = pageOptions;
};
angular.module("app.line")
.controller("lineController", LineController);
})();

Related

Facebook SDK not loaded during the call to get login status

I am using Facebook SDK to build an application however I am faced with a challenge, I try to get the login status of the user before I redirect him to his profile page, however during the call to get the login status I get the error that
ReferenceError: FB is not defined
now the SDK is being loaded asynchronously so the error makes sense, how can i resolve the problem. Here is my code:
app.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: "Views/ListPages.html",
controller: 'MainCtrl',
resolve: {
authentication:["$location", "LoginFactory", function($location, LoginFactory){
console.log("in resolve");
LoginFactory.getLoginStatus()
.then(function(response){
if(response){
$location.path('/login');
}
else{
$location.path('/');
}
});
}]
}
})
.when('/login', {
templateUrl: "Views/Login.html",
controller: 'LoginCtrl'
})
.otherwise
({redirectTo: '/'});
});
loginApp.factory("LoginFactory", function ($rootScope, $q, $location, UserInfo) {
return {
getLoginStatus: function () {
var deferred = $q.defer();
FB.getLoginStatus(function (response) {
if(!response || response.error){
deferred.reject(new error("User Not logged in."));
}
else{
deferred.resolve(response);
}
});
return deferred.promise;
},
login: function () {
FB.login(function (response) {
if (response.authResponse === "connected") {
$rootScope.$broadcast('fb_connected', {facebook_id:response.authResponse.userID});
} else {
$rootScope.$broadcast('fb_login_failed');
}
}, {scope: "read_insights, publish_pages, manage_pages"});
},
logout: function () {
FB.logout(function (response) {
if (response) {
$rootScope.$broadcast('fb_logout_succeded');
$location.path('/login');
} else {
$rootScope.$broadcast('fb_logout_failed');
}
});
}
};
angular.module("LoginCtrlModule", ["FacebookLogin"])
.controller("LoginCtrl", ["$scope", "$location", "LoginFactory", function ($scope, $location, LoginFactory) {
$scope.login = function () {
LoginFactory.login();
$scope.on("fb_connected", function () {
$location.path("/");
});
$scope.on("fb_login_failed", function(){
$location.path("/login");
});
}
}]);
app.run(function ($rootScope, $location, LoginFactory) {
window.fbAsyncInit = function () {
FB.init({
appId: '',
status: true,
cookie: true,
xfbml: true
});
};
(function (d) {
var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0];
if (d.getElementById(id)) {
return;
}
js = d.createElement('script');
js.id = id;
js.async = true;
js.src = "//connect.facebook.net/en_US/all.js";
ref.parentNode.insertBefore(js, ref);
}(document));
});
I was following these posts:
AngularJS- Login and Authentication in each route and controller
http://www.sitepoint.com/implementing-authentication-angular-applications/
But the problem i am facing is different.
Thanks for the help.
I think the solution is to not call the FB.getLoginStatus() but rather have an object that contains the User information and the access token, each time I try to route I should check if the User info object is null, in case if its not null then call the check login status method and accordingly take the route or not to take the route.

"$injector:unpr Unknown provider" after adding resolve in $stateProvider

I searched already for similar problems but couldn't figure out what the problem is in my specific case. Maybe one of you has an idea?
My code was executing with out an error but I had to add resolve to my $stateProvider. After doing so I got following error:
Error: [$injector:unpr] Unknown provider: rquoteShipmentListProvider <- rquoteShipmentList <- vendorQuoteCtrl http://errors.angularjs.org/1.4.7/$injector/unpr?p0=rquoteShipmentListProvider%20%3C-%20rquoteShipmentList%20%3C-%20vendorQuoteCtrl at Anonymous function (https://code.angularjs.org/1.4.7/angular.js:4289:13) ...
My code:
var app = angular.module("offerModul", ["ui.router", "ui.bootstrap"]);
app.config(function($stateProvider, $urlRouterProvider){
$urlRouterProvider.otherwise("/");
$stateProvider
.state("main",{
url: "/",
controller:'vendorQuoteCtrl',
templateUrl:'src/html/vendorQuoteRequest.html',
resolve: {
rquoteShipmentList: function(shipmentService) {
return shipmentService.loadquoteShipments();
}
}
});
});
app.controller('vendorQuoteCtrl', ['$scope', 'shipmentService', 'carrierService', 'chargesService', 'rquoteShipmentList', function($scope, shipmentService, carrierService, chargesService, rquoteShipmentList) {
$scope.quoteShipmentList = rquoteShipmentList;
$scope.open = function ()
{
init();
}
function init() {
$scope.quoteShipmentList = shipmentService.getquoteShipments();
}
}]);
app.service('shipmentService', ['$http', function ($http) {
var quoteShipmentList = null;
return {
loadquoteShipments: function () {
$http.get("./src/data/getShipments.php",{
cache: true})
.success(function (response) { quoteShipmentList = response; alert("quoteShipmentList:" + quoteShipmentList);})
.error(function (data, status) {
alert("error getting Quotes! status:"+status);
});
alert("should be set:" + quoteShipmentList);
return quoteShipmentList;
},
getquoteShipments: function () {
return quoteShipmentList;
}
};
}]);
Before adding resolve my code is executed without an error. The code before:
var app = angular.module("offerModul", ["ui.router", "ui.bootstrap"]);
app.config(function($stateProvider, $urlRouterProvider){
$urlRouterProvider.otherwise("/");
$stateProvider
.state("main",{
url: "/",
controller:'vendorQuoteCtrl',
templateUrl:'src/html/vendorQuoteRequest.html'
});
});
app.controller('vendorQuoteCtrl', ['$scope', 'shipmentService', 'carrierService', 'chargesService', function($scope, shipmentService, carrierService, chargesService) {
$scope.quoteShipmentList = shipmentService.loadquoteShipments();
$scope.open = function ()
{
init();
}
function init() {
$scope.quoteShipmentList = shipmentService.getquoteShipments();
}
}]);
app.service('shipmentService', ['$http', function ($http) {
var quoteShipmentList = null;
var shipmentList = null;
return {
loadquoteShipments: function () {
$http.get("./src/data/getShipments.php",{
cache: true})
.success(function (response) { quoteShipmentList = response; alert("quoteShipmentList:" + quoteShipmentList);})
.error(function (data, status) {
alert("error getting Quotes! status:"+status);
});
alert("should be set:" + quoteShipmentList);
return quoteShipmentList;
},
getquoteShipments: function () {
return quoteShipmentList;
}
};
}]);
Thank you very much for your help!!!
Like recommended in other posts I deleted ng-controller from my html BUT I didn't saw that there was another one in a modal-dialog (?:-/).
Removing that tag removed the error!
Thank you for trying to help!
there is a problem in the resolve. you have to inject your service shipmentService in the resolve like we inject in controller.
Something like :
resolve: {
rquoteShipmentList: ['rquoteShipmentList', function (rquoteShipmentList){
return shipmentService.loadquoteShipments();
}],
}

AngularJS ui-router resolve is undefined

I have moved from using ngRoute to ui-router. I am trying to resolve a Factory call in the route for use in the controller but it is undefined when output to the console. Here is the Factory:
'use strict';
angular.module('angular10App')
.factory('AirportService', function ($http) {
return {
getAirports: function () {
var airports = $http.get('../json/airports.json')
.then(function (response) {
console.log(response.data); //Outputs an array of objects
return response.data;
});
}
});
Here is the Route:
'use strict';
angular.module('angular10App')
.config(function ($stateProvider) {
$stateProvider
.state('selectFlights', {
url: '/select_flights',
templateUrl: 'app/selectFlights/selectFlights.html',
controller: 'SelectFlightsCtrl',
resolve: {
AirportService: 'AirportService',
airports: function (AirportService) {
return AirportService.getAirports();
}
},
});
});
and here is the controller:
'use strict';
angular.module('angular10App')
.controller('SelectFlightsCtrl', function ($scope, airports) {
$scope.selectedAirport = null;
$scope.airports = airports;
console.log($scope.airports); //undefined
});
Try changing your resolve block to this:
resolve: {
airports: function (AirportService) {
return AirportService.getAirports();
}
}
And modify the getAirPorts function into:
function getAirports () {
// You need to return the $http promise (or in your case, 'var airports');
return $http.get('../json/airports.json')
.then(function (response) {
console.log(response.data); //Outputs an array of objects
return response.data;
});
}

angular HttpInterceptor cancelled timeout promise aborted request

My goal is cancel a xhr request if
the lastest has a 401 status.
With the code below I can cancel
the next request but if I try
to do
an other request (ie do login) is aborted
(it need like canceller.reject(reason))
The flow
1 set a parent route (auth) to check if the login is required
2 set a child root which inheriting the auth state
3 when the app hits the route cancel the request to articles and show a modal login
(function() {
'use strict';
function Auth($http) {
return {
isLoggedIn: function() {
return $http.get('/api/auth/isloggedin');
},
signin: function(data) {
return $http.post('/api/auth/signin', data);
}
};
}
function loginModal($modal, $rootScope,$templateCache) {
function successCallback (data) {
console.log('success',data);
}
function errorCallback (data) {
console.log('fail',data);
}
return {
open : function(){
var modalInstance = $modal.open({
template: $templateCache.get('auth/templates/modal-login.html'),
controller: 'LoginModalController',
controllerAs: 'auth'
});
return modalInstance.result.then(successCallback).catch(errorCallback);
}
};
}
function HttpInterceptor($rootScope,$q) {
var canceller = $q.defer();
return {
'request': function(config) {
config.requestTimestamp = new Date().getTime();
config.timeout = canceller.promise;
return config;
},
'response': function(response) {
response.config.responseTimestamp = new Date().getTime();
return response;
},
'responseError': function(rejection) {
if (rejection.status === 401) {
$rootScope.$emit('no-auth', rejection);
canceller.resolve('Unauthorized');
}
return $q.reject(rejection);
}
};
}
angular.module('auth.services', [])
.factory('Auth', Auth)
.factory('HttpInterceptor', HttpInterceptor)
.factory('loginModal', loginModal);
})();
(function() {
'use strict';
angular.module('auth',
['auth.services','auth.controllers','auth.routes'])
.run(function($rootScope,loginModal,HAS_MODAL_LOGIN){
$rootScope.$on('no-auth', function(event, data) {
if(HAS_MODAL_LOGIN){
loginModal.open();
}
});
});
})();
(function() {
'use strict';
function config($stateProvider,$httpProvider) {
$stateProvider
.state('auth', {
abstract: true,
template: '<ui-view/>',
resolve:{
auth : function(Auth){
return Auth.isLoggedIn();
}
}
});
//Http Intercpetor to check auth failures for xhr requests
$httpProvider.interceptors.push('HttpInterceptor');
}
angular.module('auth.routes', [])
.config(config);
})();
(function() {
'use strict';
function config($stateProvider) {
$stateProvider
.state('auth.articles', {
url: '/articles',
templateUrl: 'articles/templates/index.html',
controller:'ArticlesController as articles',
resolve:{
articlesData : function(Articles){
return Articles.get();
}
}
});
}
angular.module('articles.routes', [])
.config(config);
})();
You do not need to reject. If you have 401 error, then you may simply open login dialog right there. And if user closed dialog, navigate to home.
Please read this article by Gabe Scholz
http://brewhouse.io/blog/2014/12/09/authentication-made-simple-in-single-page-angularjs-applications.html
This is exactly what you try to do but much cleaner way.

How to redirect with $state.go

I'm trying to redirect my user to Dashboard after Third Party Login. But when success callback is fired, the application still on Login Page, nothing happened. If I refresh the browser my interceptor catch already login and change to Dashboard... My Login Controller looks like this:
ThirdParty.login(function(result){
callbackSUCCESS(result);
},function(){});
function callbackSUCCESS(result){
AuthenticationService.login(result).then(
callbackServerSUCCESS(), function(reject) {
callbackServerERROR(reject);
});
}
function callbackServerSUCCESS() {
$scope.$apply(function() {
$state.go('dashboard');
});
}
My route in app.js
$stateProvider
.state('dashboard', {
url: '/dashboard',
views: {
'': {
templateUrl: 'views/dashboard/dashboard.html',
controller: 'DashboardCtrl'
}
}
});
My Header Controller
.controller('HeaderCtrl', ['$scope', 'AuthenticationService', '$state',
function($scope, AuthenticationService, $state) {
$scope.logout = function() {
AuthenticationService.logout().then(callbackServer(), callbackServer());
};
function callbackServer() {
$state.go('login');
}
}
]);
Authentication Controller Angular Factory
var headersConfig = {
'Cache-Control': 'no-cache',
'Pragma': 'no-cache'
};
return {
login: function(credentials) {
var deferred = $q.defer();
$http.post('/api/users/sign_in', sanitizeCredentials(credentials), {
headers: headersConfig,
timeout: deferred.promise
}).then(function(result) {
if (result.status === 200) {
UserSessionService.cacheSession(result.data);
deferred.resolve();
} else {
deferred.reject();
}
}, function(reject) {
UserSessionService.clean();
deferred.reject(reject);
});
$timeout(function() {
deferred.resolve();
}, 15000);
return deferred.promise;
}
};
I can't remember the exact semantics of $state.go, but usually you need to use $scope.$apply in some manner when responding to events Angular isn't aware of, to ensure a digest cycle occurs. I.e. you could try:
ThirdParty.login(function(result) {
$scope.$apply(function() {
$state.go('dashboard');
});
}, function() {});
You need to get a reference to a scope from somewhere, but one shouldn't be hard to find in an Angular app.
Get rid of both () in
then(callbackServer(), callbackServer())

Resources