AngularJS - State name passed into controller doesn't work - javascript

I'm new to angular and I can't figure out why this isn't working.
When I call {{$state.current.name}} in my view it works perfectly fine, but as soon as I try to pass it to my controller, the state gets "lost".
Here is my setup:
Module:
angular.module('app', ['ui.router'])
.run(function ($rootScope, $state, $stateParams) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
})
//followed by boilerplate ui router setup
View:
<home-nav-bar></home-nav-bar>
Directive:
angular.module('app')
.directive('homeNavBar', function () {
return {
restrict: 'E',
templateUrl: 'homeNavBarView.html',
controller: 'navCtrl'
};
})
})();
Controller:
angular.module('app')
.controller('navCtrl', function ($state, $scope) {
alert($state.current.name); //returns empty
});
})();
At this point I am clueless as to why I can get the state name in the view but not in my controller..

Well, ui-router docs say you can access current state's config object using the current property of $state, so there is absolutely no need to attach anything to $rootScope. I have just tested something along the lines of (simplified a bit for readability):
angular.module('myApp')
.controller('SomeCtrl', function ($scope, $state) {
console.log($state.current);
});
The result in Chrome console is:
Object {url: "/some", templateUrl: "app/some.html", controller: "SomeCtrl", name: "some"}
So as you can see all information should be available along with the name.

Related

Resolve in directives AngularJS

how i can use something like resolve in config in directives?
I have such code:
angular.module('config', ['ngRoute', 'resources.params'])
.config(['$routeProvider', function($routeProvider) {
'use strict';
$routeProvider
.when('/config',{
templateUrl: 'templates/config/config.tpl.html',
controller: 'ConfigCtrl',
resolve: {
params: ['Params', '$route',
function(Params, $route) {
if ($route.current.params.skey)
return Params.get($route.current.params.skey);
else
return null;
}
]
},
reloadOnSearch: true
});
}
])
.controller('ConfigCtrl', ['$scope','$route','$routeParams', 'params','Params',
function($scope,$route,$routeParams,params,Params){
'use strict';
I can use "params" in my controller because i wrote "params: [..." in my .config
But now i want to use this "params" in my directive:
.directive('mapsysitem', ['$location', '$routeParams', '$freshmark',
function($location, $routeParams, $freshmark) {
'use strict';
return {
restrict: 'E',
require: '^mapsyslist',
scope: {
zoomlist: '#',
item: '=',
skey: '=',
select: '&'
},
replace: true,
templateUrl: 'templates/map/mapsysitem.tpl.html',
controller: ['$element', '$scope', 'System','$filter','Params',
function($element, $scope, System, $filter, Params) {
.....
}]
};
}]);
If i will add "params" to controller options i will have "Unknown provider: paramsProvider <- params". How i can solve this problem? Thaks you.
Due to your use of an isolated scope within your directive, you will need pass the parameter as an attribute in the directive node
Set the scope in the app controller
.controller('ConfigCtrl', ['$scope','$route','$routeParams','params','Params',
function($scope,$route,$routeParams,params,Params){
$scope.myParams=Params
then pass the $scope.myParams to the directive
<mapsysitem param='myParams'></mapsysitem>
Then create the two way binding in your scope
scope: {
param:'='
},
Then you will be able to use this in the directive controller
controller: ['$element', '$scope', 'System','$filter',
function($element, $scope, System, $filter ) {
var myParams= scope.param
I don't think you can get the scope or attributes values of your directive's controller so if you can't you have to use a service (or $rootScope maybe) to share those values (and watch for changes).
Otherwise you may use the link function. You can access to the scope and attributes here. Here is a quote from angular site about controller/link function :
Best Practice: use controller when you want to expose an API to other directives. Otherwise use link.
This mean "use link function unless you're really sure you need controller".
See https://docs.angularjs.org/guide/directive

How to redirect after login

I am trying to redirect a user to different page after user is authenticated. I am using jwt authentication and I tried with $location, $window for redirection but its throwing error $state.go is not a function. I am new to angular and I am guessing there should be way to redirect may using a service in angular but I am still new to factories and service.
I have my state provider like this in state.js file:
myApp.config(function ($stateProvider, $urlRouterProvider) {
// default route
$urlRouterProvider.otherwise("/Home");
var header = {
templateUrl: 'commonViews/Header.html',
controller: function ($scope) {
}
};
var footer = {
templateUrl: 'commonViews/Footer.html',
controller: function ($scope) {
}
};
// ui router states
$stateProvider
.state('Home', {
url: "/Home",
views: {
header: header,
content: {
templateUrl: 'views/HomePage.html',
controller: function ($scope) {
}
},
footer: footer
}
})
.state('LoggedIn', {
url: "/LoggedIn",
views: {
'header': header,
'content': {
templateUrl: 'views/LoggedIn.html',
controller: function () {
}
},
'footer': footer
}
});
});
and loginController.js:
myApp.controller('loginController', ['$scope', '$http', 'jwtHelper', '$localStorage', '$state', function ($scope, $http, jwtHelper, $localStorage, $sessionStorage, $state)
{
$scope.email = "";
$scope.password = "";
$scope.token = "";
$scope.loginForm = function () {
var data = {email: $scope.email, password: $scope.password};
var url = 'rs/loginResource/login';
$http.post(url, data).then(function (response)
{
$localStorage.token = response.data.token;
console.log("Encoded Token in localstorage is:" + $localStorage.token);
if ($localStorage.token) {
// $location.url("/LoggedIn");
$state.go('/LoggedIn');
}
}, function (error)
{
console.log("error", error);
});
};
}]);
further I have to perform refresh token based on expiration time etc, so is it better to have separate the functions like using a service to do the signup and signin?
The problem is the definition of your controller and the way you're handling your injections. And no, referring to your own answer to your question, the problem is not the "order" of the injections. It's a bit worse.
myApp.controller('loginController', ['$scope', '$http', 'jwtHelper', '$localStorage', '$state', function ($scope, $http, jwtHelper, $localStorage, $sessionStorage, $state)
in this code you're mapping '$scope' to a $scope variable, '$http' to $http, 'jwtHelper' to jwtHelper, '$localStorage' to $localStorage and '$state' to $sessionStorage, and you're not mapping anything to $state. So obviously you get an error when you try to call a method on an undefined $state variable.
So in short, you're injecting 5 dependencies and you're assigning 6 variables to your dependencies, which in turn results in things not doing what they're supposed to do.
You can use Angular $window:
$window.location.href = '/index.html';
$state. go accepts the view name, not the URL. Replace '/LoggedIn' with Logged and you should be good.
Use $state.go instead of $window and location.
Add $state injector on controller
write code $state.go('LoggedIn');
Instead $state.go('/LoggedIn');
Write state name('LoggedIn') instead of url('/LoggedIn').
Hopefully this will work in your case.
You need to add $window as a dependency to your controller if you are using $window,
myApp.controller('loginController', ['$scope', '$http', 'jwtHelper', '$localStorage', '$state','$window', function ($scope, $http, jwtHelper, $localStorage, $sessionStorage, $state,$window)
{
$window.location.href = '/index.html';
}
otherwise change the route like this, here also you need to inject $state,
myApp.controller('loginController', ['$scope', '$http', 'jwtHelper', '$localStorage', '$state','$window','$state', function ($scope, $http, jwtHelper, $localStorage, $sessionStorage, $state,$window,$state)
{
$state.go('LoggedIn');
}

Access current state name within a directive?

I am using UI-Router and trying to access my web app's current state from within a directive, using the following:
footer.directive.js
(function () {
'use strict';
angular
.module('app')
.directive('myFooter', myFooter);
myFooter.$inject = ['$cookies', 'userFactory', '$state', '$log', '$rootScope'];
function myFooter($cookies, userFactory, $state, $log, $rootScope) {
var directive = {
restrict: 'E',
templateUrl: 'app/components/footer/footer.html',
controller: FooterController,
controllerAs: 'vm',
bindToController: true
};
return directive;
function FooterController($state) {
var vm = this;
vm.currentState = $state;
}
}
})();
footer.html
<div class="footer">
<p>{{ vm.currentState.current.name }}</p>
</div>
When I run $log.log($state) it posts an object in my console that has a current object with a name attribute that is equal to the state name that I need, but when I try to reference the $state.current.name, either on my view or by logging it to the console, it displays as an empty string.
I'm a bit new to Angular, so if someone could explain to me what is going on here or at the least how to fix this so that I can display what I want properly, that would be a huge help. Thanks!
Edit: Two other questions that I looked at before posting this one are:
This one which seems to deal more with changing a class name based on state name, and this one, which doesn't quite address my problem either (and doesn't look like it could possibly be the right way to do this.)
First of all, there is a naming bug in your posted code! (amaiFooter)
The second thing is, if you log an object, it's bound by a call by reference
So the moment you log it, you log the reference. That means when you look at it, it can contain other values than when you have logged it
But when you logged the state name and it was undefined, that was the right output!
You can try to wrap it in a $timeout function with 0 delay, just to add your code to the end of the current digest cycle, that should solve your problem
You need inject the state service on the controller as follows
(function () {
'use strict';
angular
.module('app')
.directive('myFooter', myFooter);
myFooter.$inject = ['$cookies', 'userFactory', '$state', '$log', '$rootScope'];
function myFooter($cookies, userFactory, $state, $log, $rootScope) {
var directive = {
restrict: 'E',
templateUrl: 'app/components/footer/footer.html',
controller: FooterController,
controllerAs: 'vm',
bindToController: true
};
return directive;
}
FooterController.$inject = ['$state'];
function FooterController($state) {
var vm = this;
vm.currentState = $state;
}
})();

angular.js routing and stateparams

I'm trying to modify standard user module of meanjs. I added a simple route:
state('users', {
url: '/users/:username',
templateUrl: 'modules/users/views/view-profile.client.view.html'
});
And in my view:
data-ng-controller="ViewProfileController" data-ng-init="findUser()"
I also injected $stateParams to my controller. So in my ViewProfileController - findUser function, when I write this:
console.log($stateParams.username)
I expect to get username parameter. But it returns undefined.
When I set the route this way,
state('users', {
url: '/users/:username',
template: function ($stateParams){
return $stateParams.username;
}
});
it returns username. I don't know what is wrong or missing. Any ideas?
edit: this was my full controller code
'use strict';
angular.module('users').controller('ViewProfileController', ['$scope', '$http', '$stateParams', '$location', 'Users', 'Authentication',
function($scope, $http, $location, Users, Authentication, $stateParams) {
$scope.user = Authentication.user;
$scope.findUser = function () {
console.log($stateParams);
...
};
}
]);
Your dependencies don't match up - the list of dependencies need to match the parameters in the controller function in the same order:
'use strict';
angular.module('users')
.controller('ViewProfileController', ['$scope', '$http', '$stateParams', '$location', 'Users', 'Authentication',
function($scope, $http, $stateParams, $location, Users, Authentication) {
$scope.user = Authentication.user;
$scope.findUser = function () {
console.log($stateParams);
};
}
]);
I should use controller instead of template.
Replace into you code the template: to the follow snippet:
controller: function($stateParams){
console.log('username: '+$stateParams.username);
}
You can see a complete example of this feature here

How does the "main" controller access $routeParams in this example?

I'm experimenting with $routeParams, by following along with this example in the AngularJS documentation. For reference, here is the script itself:
angular.module('ngRouteExample', ['ngRoute'])
.controller('MainController', function($scope, $route, $routeParams, $location) {
$scope.$route = $route;
$scope.$location = $location;
$scope.$routeParams = $routeParams;
})
.controller('BookController', function($scope, $routeParams) {
$scope.name = "BookController";
$scope.params = $routeParams;
})
.controller('ChapterController', function($scope, $routeParams) {
$scope.name = "ChapterController";
$scope.params = $routeParams;
})
.config(function($routeProvider, $locationProvider) {
$routeProvider
.when('/Book/:bookId', {
templateUrl: 'book.html',
controller: 'BookController',
resolve: {
// I will cause a 1 second delay
delay: function($q, $timeout) {
var delay = $q.defer();
$timeout(delay.resolve, 1000);
return delay.promise;
}
}
})
.when('/Book/:bookId/ch/:chapterId', {
templateUrl: 'chapter.html',
controller: 'ChapterController'
});
// configure html5 to get links working on jsfiddle
$locationProvider.html5Mode(true);
});
What I can't understand is this: how does MainController get the updated $routeParam object? I can see that as I click, items that MainController is responsible for setting are changing, but I don't understand how. It's making it a little tough to reproduce this behavior.
It doesn't get re-instantiated, and it's not "getting" the updated $routeParams object - the object in the controller is the routeParams object. It is the same object that is in the other controllers, not a "copy" of it.
So when the $routeParams object gets changed, the other controller already has the changes.

Categories

Resources