I cannot get $state.go('dashboard') to work. I get the error:
Failed to instantiate module app.controllers.login due to:
Error: [$injector:nomod] http://errors.angularjs.org/1.2.19/$injector/nomod?p0=app...
When defined routes I get no errors. What I'm I doing wrong?
I have also tried $stateProvider and get the same error.
This is my controller...
App.js
var app = angular.module('dashboardApp', [
"ngRoute",
"ngAnimate",
"ngTouch",
"mobile-angular-ui",
"ui.router",
"app.factories.storage",
"app.controllers.main",
"app.controllers.login",
"angular-loading-bar"
]);
app.config(function ($stateProvider, $urlRouterProvider) {
// For any unmatched url, send to /route1
$urlRouterProvider.otherwise("/");
$stateProvider
.state('login', {
url: "/",
templateUrl: STATIC_URL + "html/company/login.html",
controller: "loginController"
})
.state('dashboard', {
url: "/dashboard",
templateUrl: STATIC_URL + "html/company/dashboard.html"
})
});
Controller:
angular.module('app.controllers.login', [
"app.factories.http",
"ui.router",
])
.controller("loginController", ['$scope', "$location", "httpTokens", "httpFactory", "toaster", "$state",
function ($scope, $location, httpTokens, httpFactory, toaster, $state ) {
$scope.actionLoginCompanyUser = function () {
var post_data = {username: $scope.user.email, password: $scope.user.password};
httpTokens.createAccessTokens(post_data)
.then(function (responce) {
if (responce.status == 200) {
$state.go('dashboard')
}
else {
toaster.pop('error', "Incorrect Credentials", "Incorrect Email/Password");
}
})
}
}]);
You never defined the route.
angular.module('app.controllers.login', ["app.factories.http","ui.router"])
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('dashboard', {
url: "/dashboard",
views: {
"view": {
templateUrl: "views/something.html"
}
}
});
This should work!
If you want something like a re-route to the login page, which I assume, you can also add the following in the config:
$urlRouterProvider.otherwise("login");
What this does is, if someone tries to go to a route which doesn't exist it will route you back to login.
NOTE:
If you are using $q or $timeout, try using $location.path('/dashboard'); instead.
More info on that particular behaviour: https://github.com/angular-ui/ui-router/issues/916
Related
I am making head ways into diving into my first complete AngularJS app using PHP and tailored toward an api-centric approach.
I have reached this point:
I want to be able to capture the state name inside $stateProvider below for purpose of passing to load function. However I am unable to get $rootScope.statename to be anything but undefined. I have removed this from my solution because I could not get it to help remove undefined from the load function alert statement.
How do I capture (risk or actionitem) as the desired state name to be able to pass to the load function?
app.js -Removed code snippet
app.run( ['$rootScope', '$state', '$stateParams',
function ($rootScope, $state, $stateParams) {
$rootScope.statename = $state.current;
}]);
app.js
angular.module('Action', ['datatables', 'datatables.scroller', 'ngResource']);
angular.module('Risk', ['datatables', 'datatables.scroller', 'ngResource']);
var app = angular.module('Main', ['ui.router', 'oc.lazyLoad', 'datatables', 'ngResource', 'Action', 'Risk']);
app.config(['$ocLazyLoadProvider', '$stateProvider', '$urlRouterProvider', function($ocLazyLoadProvider, $stateProvider, $urlRouterProvider){
configRoutes($stateProvider, $urlRouterProvider, $ocLazyLoadProvider);
}]);
route-config.js
function load ($ocLazyLoad, $q, $rootScope){
var deferred = $q.defer();
try{
$ocLazyLoad.load($rootScope.statename).then(function(){
deferred.resolve();
});
}
catch (ex){
deferred.reject(ex);
}
return deferred.promise;
}
function configRoutes($stateProvider, $urlRouterProvider, $ocLazyLoadProvider)
{
$urlRouterProvider
.when('action', 'action')
.when('issue', 'issue')
.when('lesson', 'lesson')
.when('opportunity', 'opporutnity')
.when('risk', 'risk')
.otherwise('main');
$ocLazyLoadProvider.config({
modules:
[{
name: 'action',
files: ['app/tool/action/ActionController.js']
},
{
name: 'risk',
files: ['app/tool/risk/RiskController.js']
}]
});
$stateProvider
.state('main', {
url: "/main",
//templateUrl: '/app/tool/home/home.html',
});
$stateProvider
.state('action', {
name: 'action', <----------------------state name I want to capture for this url
url: "/actionitems",
resolve: {
loadDependencies: ['$ocLazyLoad', '$q', '$rootScope', load]
},
templateUrl: '/app/tool/action/ActionItems.html'
});
$stateProvider
.state('risk', {
name: 'risk', <----------------------state name I want to capture for this url
url: "/risks",
resolve: {
loadDependencies: ['$ocLazyLoad', '$q', '$rootScope', load]
},
templateUrl: '/app/tool/risk/Risks.html'
});
}
$state.current has all the information about the current state, including the name. So $state.current.name will get you the information you need.
Just keep the code simple:
$stateProvider
.state('action', {
name: 'action', //<--state name I want to capture for this url
url: "/actionitems",
resolve: {
loadDependencies: function($ocLazyLoad) {
return $ocLazyLoad.load("action");
}
},
templateUrl: '/app/tool/action/ActionItems.html'
});
I added the allowed method to the resolve section and cleaned up the code to get the desired outcome. I declared a global state to capture the value in $state$.name
var state = '';
//route-config.js
function load($ocLazyLoad, $q)
{
var deferred = $q.defer();
try
{
$ocLazyLoad.load(state).then(function ()
{
deferred.resolve();
});
}
catch (ex)
{
deferred.reject(ex);
}
return deferred.promise;
}
function configRoutes($stateProvider, $urlRouterProvider, $ocLazyLoadProvider)
{
var res =
{
loadDependencies: ['$ocLazyLoad', '$q', load],
allowed: function ($state$)
{
state = $state$.name;
}
};
$urlRouterProvider
.when('action', 'action')
.when('issue', 'issue')
.when('lesson', 'lesson')
.when('opportunity', 'opporutnity')
.when('risk', 'risk')
.otherwise('main');
$ocLazyLoadProvider.config(
{
modules: [
{
name: 'action',
files: ['app/tool/action/ActionController.js']
},
{
name: 'risk',
files: ['app/tool/risk/RiskController.js']
}]
});
$stateProvider
.state('action',
{
url: "/actionitems",
resolve: res,
templateUrl: '/app/tool/action/ActionItems.html'
});
$stateProvider
.state('risk',
{
url: "/risks",
resolve: res,
templateUrl: '/app/tool/risk/Risks.html'
});
}
When a user attempts to visit my home page, I want to be able to redirect them to a different state based on query params.
For example, if URL is: http://example.com, then load the home page.
If URL is: http://example.com?channel=1, then don't load the home page and go to some other state right away.
Here's what I have (doesn't work):
$stateProvider
...
.state('default-template.home', {
url: '/?channel&campaign',
views: {
'': {
templateUrl: 'app/pages/home/home.html',
controller: 'HomeCtrl as vm'
}
},
resolve: {
data: ['$rootScope', '$stateParams', '$state', function($rootScope, $stateParams, $state) {
var channel = $stateParams.channel;
// If channel is 1, redirect
if (channel === 1) {
$state.go('default-template.other-state', {channel: channel});
}
}]
}
})
The problem seems to be that while both states get kicked off ($stateChangeStart event gets kicked off), the end result is the user always ends up on the home page.
Any thoughts on how to make this work?
You can use the $location built-in service to achieve this.
Your code must have an additional state for the fake path as below
$stateProvider
...
.state('default-template.fake.home', {
url: '/?channel',
views: {
'': {
templateUrl: 'app/pages/home/home.html',
controller: 'HomeCtrl as vm'
}
},
})
.state('default-template.home', {
url: '/?channel&campaign',
views: {
'': {
templateUrl: 'app/pages/home/home.html',
controller: 'HomeCtrl as vm'
}
},
resolve: {
data: ['$rootScope', '$stateParams', '$state', function($rootScope, $stateParams, $state) {
var channel = $stateParams.channel;
// If channel is 1, redirect
if (channel === 1) {
$state.go('default-template.other-state', {channel: channel});
}
}]
}
})
Your HomeCtrl should use the $location service to access the url as below
angular.controller('HomeCtrl',function($location,$state){
if($location.$$url= '') //check if it is empty
$state.go('default-template.home');
....................................
})
LIVE DEMO
I am following the angularfire tutorial to authenticate users.
Users are able to register, signin and even signout in the app.
When I try to use a resolve to check for $requireSignIn() for some routes(ui-route), it doesn't work.
Also, I want to do a check for user authentication status($onAuthStateChanged()) in my app.js where my modules are loaded. Then if there is a change in authentication, update authentication service( userAuth). I am using ng-show="authData" / ng-hide="authData to change html for logged in elements. But sometimes even after login, some of these elements are still showing as not logged in. I think this has something to do with the authentication update status.
If a user is logged in and the try to visit the login/signup page send them back to home page.
Here is my app.js
angular
.module('myApp', [
'ngAnimate',
'ngAria',
'ngCookies',
'ngResource',
'ui.router',
'ngMeta',
'firebase'
])
.run(["$rootScope", "$state", function($rootScope, $state) {
$rootScope.$on("$stateChangeError", function(event, toState, toParams, fromState, fromParams, error) {
if (error === "AUTH_REQUIRED") {
$state.go("home");
}
});
}])
.config(['$stateProvider', '$urlRouterProvider', '$locationProvider',
function( $stateProvider, $urlRouterProvider, $locationProvider, ngMetaProvider, $location, userAuth) {
$urlRouterProvider.otherwise('/');
$stateProvider
.state('/', {
url: '/',
templateUrl: 'views/main.html',
controller: 'MainCtrl',
meta: {
'title': 'Goaf | Your next great destination',
'description': 'This is the description shown in Google search results'
}
})
.state('home', {
url: '/home',
templateUrl: 'views/home.html',
controller: 'HomeCtrl',
meta: {
'title': 'Goaf | Your next great destination',
'description': 'This is the description shown in Google search results'
},
resolve: {
"currentAuth": ["userAuth", function(userAuth) {
return userAuth.$requireSignIn();
}]
}
})
}]);
Here is the controller for the home page where I want only logged in users:
angular.module('myApp')
.controller('HomeCtrl', ["currentAuth", function ($rootScope, $scope, $http, $interval, $location, userAuth, dataservice, currentAuth) {
$scope.authData = userAuth.isLoggedIn();
}]);
And here is my userAuth service file:
angular.module('myApp')
.service('userAuth', ["$firebaseAuth", function($firebaseAuth) {
var firebaseAuthObject = $firebaseAuth();
this.login = function(loginEmail, loginPassword){
return firebaseAuthObject.$signInWithEmailAndPassword(loginEmail, loginPassword);
};
this.isLoggedIn = function(){
return firebaseAuthObject.$getAuth();
};
this.signOutUser = function() {
firebaseAuthObject.$signOut();
console.log('logging out user!');
};
}
]);
I'm attempting to use angular-ui-router to display templates, based on state. Currently, i'm not getting errors in the terminal. In the console, I see "Uncaught TypeError: Cannot read property 'isDefined' of undefined" and "uncaught TypeError: Cannot read property 'isDefined' of undefined". This makes me think I'm not instantiating modules properly. New to angularjs and hoping someone might be able to point me in the right direction. app.js
var app = angular.module('app', ['ui.bootstrap', 'ui.router', 'ngMessages', 'app-templates'])
.run(function($rootScope, $state, Auth) {
$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
if (!Auth.authorize(toState.data.access)) {
event.preventDefault();
$state.go('anon.login');
}
});
});
And, routes.js.
angular.module('app')
.config(function($stateProvider, $urlRouterProvider, AccessLevels) {
$urlRouterProvider.otherwise('/');
$stateProvider
.state('anon', {
abstract: true,
template: '<ui-view/>',
data: {
access: AccessLevels.anon
}
})
.state('anon.index', {
url: '/',
templateUrl: 'index.html'
})
.state('anon.login', {
url: '/login',
template: 'auth/login.html',
controller: 'LoginController'
})
.state('anon.register', {
url: '/register',
templateUrl: 'auth/register.html',
controller: 'RegisterController'
});
$stateProvider
.state('user', {
abstract: true,
template: '<ui-view/>',
data: {
access: AccessLevels.user
}
})
.state('user.messages', {
url: '/messages',
template: 'user/messages.html',
controller: 'MessagesController'
});
});
i'am using AngularJS with ui-router, this is my current app.js configuration.
'use strict';
angular.module('nodeserverApp', [
'ngCookies',
'ngResource',
'ngSanitize',
'ngRoute',
'ui.bootstrap',
'ui.router'
])
.config(function ($routeProvider, $locationProvider, $httpProvider , $stateProvider , $urlRouterProvider) {
$stateProvider
.state('home', {
url: '/',
templateUrl: 'partials/user/main',
controller: 'MainCtrl'
})
.state('dashboard', {
url: '/user/dashboard',
templateUrl: 'partials/user/dashboard/main',
controller: 'UserDashboardDashboardCtrl',
authenticate: true
})
.state('dashboard.welcome', {
url: '/welcome',
parent: 'dashboard',
templateUrl: 'partials/user/dashboard/welcome'
})
.state('dashboard.account', {
url: '/account',
templateUrl: 'partials/user/dashboard/account',
controller: 'UserDashboardAccountCtrl'
})
.state('dashboard.address', {
url: '/address',
templateUrl: 'partials/user/dashboard/address/index'
})
.state('dashboard.address.view', {
url: '/view',
templateUrl: 'partials/user/dashboard/address/view',
controller: 'UserDashboardAddressViewCtrl'
})
.state('dashboard.address.new', {
url: '/new',
templateUrl: 'partials/user/dashboard/address/new',
controller: 'UserDashboardAddressNewCtrl'
})
.state('login', {
url: '/user/login',
templateUrl: 'partials/user/login',
controller: 'LoginCtrl'
})
.state('signup', {
url: '/user/signup',
templateUrl: 'partials/user/signup',
controller: 'SignupCtrl'
})
.state('settings', {
url: '/user/settings',
templateUrl: 'partials/user/settings',
controller: 'SettingsCtrl',
authenticate: true
});
$urlRouterProvider.otherwise("/");
$locationProvider.html5Mode(true);
// Intercept 401s and 403s and redirect you to login
$httpProvider.interceptors.push(['$q', '$location', function($q, $location) {
return {
'responseError': function(response) {
if(response.status === 401 || response.status === 403) {
$location.path('/user/login');
return $q.reject(response);
}
else {
return $q.reject(response);
}
}
};
}]);
})
.run(function ($rootScope, $state, Auth) {
$rootScope.$on("$stateChangeStart", function(event, toState, toParams, fromState, fromParams){
if (toState.authenticate && !Auth.isLoggedIn()){
// User isn’t authenticated
$state.transitionTo("login");
event.preventDefault();
}
});
});
as you can see, dashboard requires authentication, how can i make it's children inherit the authenticate like dashboard.welcome , dashboard.address.view etc. with out the need to specify each one?
I know this is pretty old, but for future Googlers, note that the data property is inherited by child states, so you can place something like this authenticate flag in the parent. These modifications to your should do the trick:
For $stateProvider:
.state('dashboard', {
url: '/user/dashboard',
templateUrl: 'partials/user/dashboard/main',
controller: 'UserDashboardDashboardCtrl',
data: {
authenticate: true
}
})
For angular.module:
.run(function ($rootScope, $state, Auth) {
$rootScope.$on("$stateChangeStart", function(event, toState, toParams, fromState, fromParams){
if (toState.data.authenticate && !Auth.isLoggedIn()){
// User isn’t authenticated
$state.transitionTo("login");
event.preventDefault();
}
});
});
I hope this link will help, this is a great article from Frederik Nakstad about the Single Page Auth for AngularJS, sorry but not able to provide you the detail codes
http://frederiknakstad.com/2013/01/21/authentication-in-single-page-applications-with-angular-js/