AngularJS ReferenceError: $window is not defined - javascript

I'm trying to re-direct my users if they pass my form validation (checking usernames and passwords against database values).
The validation works fine but in my .Success function the redirect doesn't seem to be working, it produces the error: 'ReferenceError: $window is not defined'.
Here's the code:
.success(function(data) {
console.log(data);
if (!data.success) {
// if not successful, bind errors to error variables
$scope.errorUserName = data.errors.userName;
$scope.errorUserPassword = data.errors.userPassword;
} else {
// if successful, bind success message to message
$scope.message = data.message;
$window.location=('twitter.com');
}
});
I've tried changing the location path but nothing seems to be working. Any ideas?
Thanks!
LazyTotoro

$window needs to be injected.
To inject it you simply add it as a parameter to your controller function and Angular will automatically take care of the rest.
For example:
app.controller('MyController', function MyController($scope, $window) {
$window.location = 'http://stackoverflow.com'
});
You can read more about dependency injection in AngularJS here.
If you don't need a full page reload you should instead inject and use $location:
// get the current path
$location.path();
// change the path
$location.path('/newValue');

Related

Angular js How to handle HTTP error globally

HI all i have 2 question
angular try to handle server $http error globally. so written below code in app.js
angular.module('mname',[])
.config(function ($provide, $httpProvider) {
$provide.factory('ErrorInterceptor', function ($q) {
return {
responseError: function(rejection) {
//console.log(JSON.stringify(rejection));
alert('Error:==>'+rejection.status+"===>"+rejection.statusText);
return $q.reject(rejection);
}
};
});
1) Here I can able to get that alert if 404 error.
But if server through any code error like missing variable or etc... but connection state is 200 .. that time how can i manage??
can't come inside this responseError: area .
2) I wrote one method for dialog factory to display the errors and message as Factory. I can able to include inside the controller to get working. How can use inside "responseError:" area . (refer above code)

Parsing a JSONP file in AngularJS

I'm new to Angular and also relatively new to the JSONP format. In my code, I set up a factory to read in the JSONP file - and I get back the data variable as the JSONP data properly
$http.get('someJSONFile').success(function(data){
console.log(data);
});
The console log gives me back the following:
states([{"code":"AL","name":"Alabama"},{"code":"AK","name":"Alaska"},{"code":"AZ","name":"Arizona"},{"code":"AR","name":"Arkansas"},{"code":"CA","name":"California"},{"code":"CO","name":"Colorado"},{"code":"CT","name":"Connecticut"},{"code":"DE","name":"Delaware"}])
So - I'm stuck on what to do now. I have a data object that contains a function. I need to parse out the JSON from this function - but not sure how to do it.
I have read in other places that I need to declare a function somewhere in my controller or factory called
function states(results)
{
// what is in results should be the JSON data I crave
}
But even if I do that, I don't think it ever executes - so I am not sure what I should do at that point to get the JSON data into an object that I can use.
The full file I am trying to parse is http://massachusettswebdesigns.com/states.json
Any help is appreciated!
Angular $http service provides a method to consume JSONP endpoints. In your case this should work:
$http.jsonp('someJSONFile').then(function(data) {
console.log(data)
});
Behind the scene, Angular will create a globally accessible function that will receive data, parse and pass further, so you don't need to worry about creating functions yourself.
What looks like your trying to do is standard JSON not JSONP, JSONP will require a callback and is only required if getting data from a different domain, ie a API service
Also the console log output you give is not valid JSON.
//init app
var app = angular.module('MyApp',[]);
//setup a factory for the data handling
app.factory("Data",function($http){
return {
getData:function(type){
return $http.get(type).
then(function(result) {
return result.data;
});
}
}
});
//in a controller 'call' the factory for the data
app.controller('main', function main($scope, Data) {
//other stuff
Data.getData('someJSONFile').then(function (data) {
$scope.jsonData = JSON.parse(data);
});
//other stuff
});
So my error was a stupid one. The JSON file was giving me the name of a custom callback I had to define. Once I did this, all worked. . . . here's the code
angular.module('locationApp')
.controller('MainCtrl', ['$scope', '$http', function ($scope, $http) {
$scope.states = [];
$scope.cities = [];
// Function for the States callback on the JSON files provided
window.states = function (data)
{
$scope.states = data;
};
// Get the State JSON file.
$http.jsonp('http://locationinc-mapping-demo.herokuapp.com/states.json');
}]) // end of MainCtrl

Angular JS authorization - check user role before loading the page

I'm writing cms front-end in Angular JS and I don't know how to deal with authorize user to see particular content when user first load the app. I have working solution when user is already log in and just navigate from page to page. I do it this way:
angular.module("myApp")
.run ($rootScope, AUTH_EVENTS, AuthServ) ->
$rootScope.$on '$stateChangeStart', (event, next) ->
if next.data
authorizedRoles = next.data.authorizedRoles
unless AuthServ.isAuthorized(authorizedRoles)
event.preventDefault()
if AuthServ.isAuthenticated()
$rootScope.$broadcast(AUTH_EVENTS.notAuthorized)
else
$rootScope.$broadcast(AUTH_EVENTS.notAuthenticated)
When user change the route, the AuthServ.isAuthorized(authorizedRoles) is fired.
When user logs in I get token and user data from server. Token is stored in local storage and user data are stored in memory (in the scope of top level controller). In the user data I have an info about his role, so I can check if he's authorized to see particular content.
Now let's assume that user is logged in and he reload the page. I still have the token as this is in localStorage but I loose user data (so I don't know what is his role). I don't want to show any content to user before I get his data again from server. So my question is how to resolve this ? Where and when should I make the request to server for user data ?
I thought that solution could be to manually bootstrap the app. I tried to do something like this:
app = angular.module('myApp', [])
fetchData = ->
injector = angular.injector(['ng'])
$http = injector.get('$http')
API_URI = injector.get('API_URI')
$localStorage = injector.get('$localStorage')
$http.get("#{API_URI}/users/me?token=#{$localStorage.token}")
.success (data) ->
app.constant('USER_DATA', data)
bootstrapApplication = ->
angular.element(document).ready ->
angular.bootstrap(document, ['myApp'])
fetchData().then(bootstrapApplication)
The problem with this code is that I don't have access to $localStorage service and API_URI constant. I need them to get token and to dynamically change url (development, production).
So what is the best solution ? Maybe storing user role in local storage as well ?
Any help would appreciated, Thanks.
You can use Angular's resolve in your routes configuration. Here is an example where I am resolving 'user' for a particular route. It must resolve before angular will load this route.
app.config( [ '$routeProvider', '$locationProvider',
function( $routeProvider, $locationProvider ) {
$routeProvider
.when('/somePath', {
templateUrl: "someView.html",
controller: "someController",
resolve: {
user: function( authService ){
return authService.getUser();
}
}
}
);
}
]);
Here is the service(factory in this case) to go along with it. I am checking to see if auth.user exists first so there won't be a request on each route change:
app.factory('authService', [ '$http', '$q',
function( $http, $q ) {
var pub = {};
pub.user = null;
pub.getUser = function() {
var deferred = $q.defer();
if( pub.user ) {
deferred.resolve( pub.user );
}
else{
$http.get('/someAuthUrl').then(function( user ) {
pub.user = user;
deferred.resolve( user );
});
}
return deferred.promise;
};
return pub;
}
]);
And then finally the controller which will not load until the auth function has resolved with your needed user data. You can access the user object now through injection.
app.controller( 'someController', [ '$scope', 'user',
function( $scope, user ) {
//Controller runs here only when user is resolved.
// Anything resolved will be passed in as your last dependency.
$scope.user = user;
}
]);
In this case you could have injected the service into the controller instead and use authService.user as we know it's available.
app.controller( 'someController', [ '$scope', 'authService',
function( $scope, authService ) {
$scope.user = authService.user;
}
]);
This is because whenever you reload/navigate new instance of controller is created and your user data in controller is lost. Best way to do is to move the logic of authenticating and storing data to a Service and use that service in the controller, this way you won't lose the data on refresh/navigation

How can I prevent angularJS from squelching script errors?

On my AngularJS sample project, I know that I have a service method which SHOULD throw a JavaScript error.
Using Firebug, I confirm that a JS error is thrown when resolving a promise from a $resource (TypeError: phone.images is undefined); but, the error never appears in the Firebug console.
How can I get the resource to 'fail fast' and propagate the error up the call stack?
Here is the service code:
var phonecatServices = angular.module('phonecatServices', ['ngResource']);
phonecatServices.factory('Phone', ['$resource',
function($resource){
return $resource('phones/:phoneId.json', {}, {
query: {method:'GET', params:{phoneId:'phones'}, isArray:true}
});
}]);
Here is the controller (which fails silently):
phonecatControllers.controller('PhoneDetailCtrl', ['$scope', '$routeParams', 'Phone',
function($scope, $routeParams, Phone) {
$scope.phone = Phone.get({phoneId: $routeParams.phoneId}, function(phone) {
//JS error SHOULD be thrown here:
$scope.mainImageUrl = phone.images[0];
});
...
}]);
I don't want the code to fail silently! How can I fix it?
Ideally, I would like to fix it throughout the framework, rather than putting in special error handling code for each service or resource call.
You need to add the error callback to your get call:
Phone.get({phoneId: $routeParams.phoneId}, function(phone){
// Do Stuff with phone object
}, function(error) {
alert("Y U NO RETURN PHONE?");
// Handle error accordingly
});
Here is the documentation for $resource
If you'd like to generically handle errors for AJAX requests through the angular framework, then you'd probably like something like an http interceptor (Check the interceptors section). This kind of paradigm requires that all requests pass through your interceptor service to be handled in a generic fashion.

AngularJS : Understanding service when using $http.post

I am moving all http calls in my controllers to services, using $q to promise... Everything seems to work till I refresh the page then the content disappears.
Setting: In my login service, I have a function which does an $http.post, it takes username and password. Then the response data is put in the promise.
Problem: Though the service works, It is trying resend the http call when the page is refreshed. The call then fails because the are no login details.
Question: How do I keep/store the original data so when the page is refreshed (and user is still signed in) and when I use the service in other controllers it does not do the http call it just returns the data?
Service:
var app = angular.module('myApp', ['ngRoute']);
app.factory('loginService', function($http, $q) {
var deferResults = $q.defer();
return {
appContent: function(login_username, login_password) {
$http.post('/login',{username: login_username, password: login_password}).success(function(data) {
deferResults.resolve(myData);
});
return deferResults.promise;
}
});
Controllers:
function loginPageCtrl($scope, loginService) {
$scope.login = function (login_username, login_password, login_rememberMe) {
loginService.appContent(login_username, login_username).then(function (data) {
$scope.pageOneContent = data;
});
};
};
function pageTwoCtrl($scope, loginService) {
// Use the same data when page is refreshed
// without having to pass-in login details
loginService.appContent().then(function (data) {
$scope.pageTwoContent = data;
});
};
Of course that happens, your app loses all its state when the page is refreshed. You need to persist that username and password somewhere, like a cookie, and then retrieve that then make your second $http call, even better just keep a token in a cookie and use that for authentication. Use angular's $cookieStore to persist the login details:
var userData={username:login_username,password:login_password};
$cookieStore.put('user_data', userData);
and then when the controller loads, check if the cookie exists:
var userData = $cookieStore.get('user_data');
return userData
Check the source in this answer to see this in action.
To recap, every time the controller loads check the cookie, if its undefined then redirect the user to a login page, if it's not then extract the toke/username/password and make your $http call.

Categories