I'm trying to update my nav bar every time the route changes, and I've tried this, however it doesn't seem to be working. It's supposed to write bob every time the view changes, but it only writes it when the controller loads.
nav.controller.js
angular.module('app')
.controller('navController', ['$scope', '$state', function ($scope, $state) {
var timeSpan;
$scope.user;
...
// Update when the view changes.
$scope.reload = function () {
$state.reload();
};
$scope.$state = $state;
$scope.$watch('$state.$current.locals.globals.view', function () {
console.log('bob');
$scope.user = userService.get();
});
...
$scope.reroute = function(route){
$state.go(route);
};
}]);
route.js
angular.module('SimPlannerApp')
.config(function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.when('/','/signin');
$stateProvider
.state('signin', {
url: "/signin",
templateUrl: 'views/signin.html',
controller: 'signinController'
})
.state('menu', {
url: "/menu",
templateUrl: 'views/menu.html',
controller: 'menuController',
resolve: {
config: function (configService) {
return configService.getConfig()
.then(function(response){
return response.data;
})
.catch(function(error){
console.log('Error : ', error);
return undefined;
});
}
}
})
.state('view', {
url: '/view/:view',
templateUrl: 'views/view.html',
controller: 'viewController',
resolve: {
view: function ($stateParams, configService) {
return configService.getConfig()
.then(function(response){
var config = response.data;
for (var i = 0; i < config.views.length; i++) {
if (config.views[i].route === $stateParams.view) {
return config.views[i];
}
}
return undefined;
})
.catch(function(error){
console.log('Error : ', error);
return undefined;
});
},
config: function (configService) {
return configService.getConfig()
.then(function(response){
return response.data;
})
.catch(function(error){
console.log('Error : ', error);
return undefined;
});
}
}
})
.state('404', {
url: '{path:.*}',
templateUrl: 'views/404.html',
controller: 'errorController'
});
});
PS:
Propably should mention I'm using AngularJS with ui-router.
Not sure if I fully understand but would it not be better to use $stateChangeSuccess to detect when the route changes? I use this in the .run block
$rootScope.$on('$stateChangeSuccess',
function(event, toState, toParams, fromState, fromParams){ ... })
but you could place this in your Controller
https://github.com/angular-ui/ui-router/wiki
You can handle with $locationChangeStart like below:
$rootScope.$on('$locationChangeStart', function () {
console.log('bob');
});
You should write this in .module.run() function.
angular
.module()
.run(function($rootScope) {
// to Here
})
Related
I want to remove exclamation marks from url state routing like my url is now http://localhost:3000/#!/auth/register
i just want to remove this "!" marks from url after "#"
Is it possible to do? with mean.io
here is my app.js/system.js
'use strict';
//Setting up route
angular.module('mean').config(['$stateProvider', '$urlRouterProvider',
function($stateProvider, $urlRouterProvider) {
// For unmatched routes:
//$urlRouterProvider.otherwise('/');
var checkLoggedin = function($q, $timeout, $http, $location) {
// Initialize a new promise
var deferred = $q.defer();
// Make an AJAX call to check if the user is logged in
$http.get('/loggedin').success(function(user) {
// Authenticated
if (user !== '0') $timeout(deferred.resolve);
// Not Authenticated
else {
$timeout(deferred.reject);
$location.url('/auth/login');
}
});
return deferred.promise;
};
// console.log($stateProvider);
// states for my app
$stateProvider
.state('tasks', {
url: '/kanban/:projectId/:projectSlug',
templateUrl: 'system/views/index.html',
controller: 'IndexController',
resolve: {
loggedin: checkLoggedin,
onEnter: function($stateParams,$state, $uibModal) {
if ( $stateParams.projectId != "" ) {
updateTopMenu('Kanban','task','#!/kanban/'+$stateParams.projectId+'/'+$stateParams.projectSlug);
updateTopMenu('Schedule','schedule','#!/schedule');
}
}
}
}).state('home',{
url:'/',
templateUrl: 'projects/views/index.html',
controller: 'ProjectController',
resolve:{
loggedin: checkLoggedin
}
}).state('taskEdit',{
url:'/kanban/:projectId/:projectSlug/:taskSlug',
templateUrl: 'system/views/index.html',
controller: 'IndexController',
resolve:{
loggedin: checkLoggedin
}
}).state('taskAdd',{
url: "/task/taskAdd",
onEnter: function($stateParams, $state, $uibModal) {
$uibModal.open({
templateUrl: "system/views/include/model.html",
resolve: {},
controller: function($scope, $state, itemService) {
/*
$scope.state = $state.current;
$scope.params = $stateParams;
$scope.item = itemService.get($stateParams.id);
*/
$scope.ok = function () {
$scope.$close('clicked ok');
};
$scope.dismiss = function () {
$scope.$dismiss('clicked cancel');
};
}
}).result.then(function (result) {
// $scope.$close
alert('result ->' + result);
}, function (result) {
// $scope.$dismiss
return $state.transitionTo("home");
alert('dismiss ->' + result);
}).finally(function () {
// handle finally
return $state.transitionTo("tasks");
});
}
});
}
]).config(['$locationProvider',
function($locationProvider) {
$locationProvider.hashPrefix('!');
}
]);
you have configured it here
function($locationProvider) {
$locationProvider.hashPrefix('!');
}
remove this line to get ! removed from url
or enable html5mode using below code to remove # from url
$locationProvider.html5Mode(true);
but please read more about how url routes are handled in angular, and server side routing vs client side routing etc, before enabling html5mode
Change $locationProvider.hashPrefix('!'); to $locationProvider.hashPrefix('');
System.js
.config(['$locationProvider',
function($locationProvider) {
$locationProvider.hashPrefix('');
}
]);
I've faced with such problem, when I add controller to my route code it fails to unexpected identifier. Have no idea why it's happening
This is my routeProvider:
app.config(function($routeProvider) {
$routeProvider
.when("/login", {
title: 'Login',
templateUrl: 'assets/login.html'
controller: authCtrl
})
});
And this is my controller:
app.controller('authCtrl', function ($scope, $rootScope, $routeParams, $location, $http, Data) {
//initially set those objects to null to avoid undefined error
$scope.login = {};
$scope.signup = {};
$scope.doLogin = function (customer) {
Data.post('login', {
customer: customer
}).then(function (results) {
Data.toast(results);
if (results.status == "success") {
$location.path('dashboard');
}
});
};
$scope.signup = {email:'',password:'',name:'',phone:'',address:''};
$scope.signUp = function (customer) {
Data.post('signUp', {
customer: customer
}).then(function (results) {
Data.toast(results);
if (results.status == "success") {
$location.path('dashboard');
}
});
};
$scope.logout = function () {
Data.get('logout').then(function (results) {
Data.toast(results);
$location.path('login');
});
}
});
I've included such paths in my html:
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"/>
<script src="app/angular-route.min.js"></script>
<script src="app/angular-animate.min.js" ></script>
<script src="app/toaster.js"></script>
<script src="app/app.js"></script>
There is some typos in your code :
app.config(function($routeProvider) {
$routeProvider
.when("/login", {
title: 'Login',
templateUrl: 'assets/login.html', // <---- missing ','
controller: 'authCtrl' // <----- should be format to string
})
});
Not sure if it will solve your problem
try it.
app.config(function($routeProvider) {
$routeProvider
.when("/login", {
title: 'Login',
templateUrl: 'assets/login.html',
controller: 'authCtrl' // <-- string
})
});
the controller name must pass as a string..try this
app.config(function($routeProvider) {
$routeProvider
.when("/login", {
title: 'Login',
templateUrl: 'assets/login.html',
controller: 'authCtrl'
})
});
I want to show UI after all promises has complete.
When I move to any step , before this I do some code execution.
I am stuck here my templateURl gets executed synchronously. I want templateUrl should execute once all execution has been completed (from .run method).
below is my app.js
(function () {
"use strict";
var app = angular.module("autoQuote", ["ui.router", "ngResource"]);
app.config(["$stateProvider", "$urlRouterProvider", function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/");
$stateProvider
.state("Cars", {
url: "",
templateUrl: "/rc1/renderStep/cars"
})
.state("Drivers", {
url: "/drivers",
templateUrl: "/rc1/renderStep/drivers",
controller: "renderStepCtrl",
})
}])
app.run(["$log", "$rootScope", "$state", "dtoResource", "questionResource", "postDtoFactory", function ($log, $rootScope, $state, dtoResource, questionResource, postDtoFactory) {
$log.info('Post DTO on page load.');
$rootScope.$state = $state;
dtoResource.rc1LoadDTO()
.then(function (data) {
$rootScope.AutoQuote = data;
postDtoFactory.postDto()
.then(function (data) {
questionResource.getQuestions($rootScope.AutoQuote.postAutoQuoteObj.SessionInfo.StateCode)
.then(function (questions) {
console.log('questions', questions);
$rootScope.questions = questions;
//$rootScope.answers = {PC:12345,VehicleYear_1:2017}; // test code
console.log('Obtained questions. Assigned to rootscope');
})
})
})
.then(function () {
console.log('This should be printed after the above methods are done executing');
console.log($rootScope);
})
}])
}());
you can put the code to ui-router resolve.
$stateProvider.state('demo', {
url: '/demo',
template: require('./views/demo.html'),
controller: 'DemoController as vm',
resolve: {
resolvedInfo: [demoService,
function (demoService) {
//put some code execution
return promise;
}]
}
})
I'm having trouble figuring out how I could pass a parameter to a function that is a part of resolve of ngRoute.
In my case I'm doing stuff with tokens. These tokens are typed, so you cannot use the same token for confirming and email and reseting a password. Here's how my routes are defined:
.when("/confirm/:token", {
controller: "confirmEmailController",
templateUrl: "/app/views/confirmEmail.html",
resolve: {
tokenStatus: getTokenStatus
}
})
.when("/reset/:token", {
controller: "resetPasswordController",
templateUrl: "/app/views/resetPasswordEmail.html",
resolve: {
tokenStatus: getTokenStatus
}
})
Here's the getTokenStatus function that's being called for both of them:
var getTokenStatus = ["$q", "$route", "tokenService", function($q, $route, tokenService)
{
var deferred = $q.defer();
var tokenType = ???? //<-- how do I pass this?
tokenService
.getTokenStatus($route.current.params.token, tokenType)
.success(function(response)
{
deferred.resolve(true);
})
.error(function()
{
deferred.resolve(false);
});
return deferred.promise;
}];
The problem is that in order to avoid code duplication I need to somehow pass the value of the token type, as marked in the code. How could I do that?
I've been messing about with this for the last 2 hours, but can't seem to figure it out.
1. You can try to include token type into route
.when("/:tokenType/:token", {
controller: "confirmEmailController",
templateUrl: "/app/views/confirmEmail.html",
resolve: {
tokenStatus: getTokenStatus
}
})
.when("/:tokenType/:token", {
controller: "resetPasswordController",
templateUrl: "/app/views/resetPasswordEmail.html",
resolve: {
tokenStatus: getTokenStatus
}
})
And then just get it from $route.current.params.tokenType. But it's not clean solution - you should check your URL for validity.
2. You can use function wrapping
$routeProvider.when("/confirm/:token", {
controller: "confirmEmailController",
templateUrl: "/app/views/confirmEmail.html",
resolve: {
tokenStatus: getTokenStatus("confirm")
}
})
.when("/reset/:token", {
controller: "resetPasswordController",
templateUrl: "/app/views/resetPasswordEmail.html",
resolve: {
tokenStatus: getTokenStatus("reset")
}
});
var getTokenStatus = function(tokenType) {
return ["$q", "$route", "tokenService", function($q, $route, tokenService) {
var deferred = $q.defer();
tokenService
.getTokenStatus($route.current.params.token, tokenType)
.success(function(response)
{
deferred.resolve(true);
})
.error(function()
{
deferred.resolve(false);
});
return deferred.promise;
}];
};
3. You can move get-token-status logic into separate servise
$routeProvider.when("/confirm/:token", {
controller: "confirmEmailController",
templateUrl: "/app/views/confirmEmail.html",
resolve: {
tokenStatus: ['tokenStatusGetterService', function(tokenStatusGetterService){
return tokenStatusGetterService("confirm");
}]
}
})
.when("/reset/:token", {
controller: "resetPasswordController",
templateUrl: "/app/views/resetPasswordEmail.html",
resolve: {
tokenStatus: ['tokenStatusGetterService', function(tokenStatusGetterService){
return tokenStatusGetterService("reset");
}]
}
});
//...
.service('tokenStatusGetterService', ["$q", "$route", "tokenService", function($q, $route, tokenService) {
return function(tokenType) {
var deferred = $q.defer();
tokenService
.getTokenStatus($route.current.params.token, tokenType)
.success(function(response)
{
deferred.resolve(true);
})
.error(function()
{
deferred.resolve(false);
});
return deferred.promise;
};
}]);
one way to do it is to put a function on your getTokenStatus service.
this is a simplified example, yet it shows how to pass an argument to your resolve function.
app.factory('getTokenStatus',['$q', '$timeout', '$route', function($q, $timeout, $route){
this.action = function(tokenType) {
var defer = $q.defer();
$timeout(function(){
var res = {
path: $route.current.params.token,
tokenType: tokenType
}
defer.resolve(res);
},1000);
return defer.promise;
}
return this;
}]);
and call it from your resolve object:
app.config(function($routeProvider){
$routeProvider
.when("/123/:token", {
template: "<h1>hello</h1>",
controller: 'testCtrl',
resolve: {
tokenStatus: function(getTokenStatus) {
return getTokenStatus.action('firstToken').then(function(res){
console.log(res);
});
}
}
})
here's a plnkr
I am trying to create a login script using Angularjs. I have an Authentication Service that handles the logic for that.
Here the service:
.factory("AuthSvc",
['$http','$q','$state',
function ($http,$q,$state) {
function GetUser() {
var d = $q.defer();
$http.get('api/auth/check')
.success(function(res){
d.resolve(res);
});
return d.promise;
};
return {
login: function (credentials, form) {
var defer = $q.defer();
$http.post('/api/auth/login', credentials)
.success(function (response) {
form.$setPristine();
user = response;
$state.go('base.posts.content');
defer.resolve();
})
.error(function (response) {
defer.reject();
});
return defer.promise;
},
isLoggedIn: GetUser,
user: null
};
}]);
I have a resolve property and a listener for the user property to update the view on the app configuration as below:
.config(['$stateProvider',
function ($stateProvider) {
// Now set up the states
$stateProvider
.state('base', {
url : "",
templateUrl: "/templates/base/index.html",
resolve : {user : ["AuthSvc",
function(AuthSvc) {
return AuthSvc.user;
}]
},
})
.state('base.login', {
url : "login",
templateUrl: "/templates/login/index.html",
controller : 'LoginCtrl'
})
.state('base.posts', {
abstract : true,
url : 'posts',
templateUrl: '/templates/posts/posts.html'
})
.state('base.posts.content',{
url: '',
resolve: {
posts: function (PostsSvc) {
return PostsSvc.getPosts();
}
},
views:{
'create': {
templateUrl: '/templates/posts/create.html',
controller: 'PostsCtrl'
},
'list': {
templateUrl: '/templates/posts/list.html',
controller: 'PostsCtrl'
}
}
});
}]);
app.run(['$rootScope','AuthSvc','$state',
function ($rootScope,AuthSvc,$state,
) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
$rootScope.$on('$stateChangeStart',
function(event, next, current){
AuthSvc.user = AuthSvc.isLoggedIn();
});
$state.transitionTo('base.posts.content');
}]);
}());
The $rootScope.on('$stateChangeStart') is not working. I see some code where people directly assign a value to a promise without using the then function of the promise. How do I accomplish this using this code?