How to get url parameters from controller in angular.js - angularjs

so, in my app.js :
.state('app.packages', {
url: "/packages/:packagesId",
views: {
'menuContent' :{
templateUrl: "templates/packages.html",
controller: function ($stateParams) {
console.log($stateParams);
}
}
}
})
in browser console, it showing this :
Object {packagesId: "25242039"}
How do i access the $stateParams that hold the value of packagesId inside controller.js?
Currently doing it like this, but it is not working...
.controller('PlaylistCtrl', function($scope,$stateParams) {
$scope.getId = function(){
return $scope = $stateParams.packagesId ;
};
})

First off, I don't understand why you want to assign the id to the scope return $scope = $stateParams.packagesId;
Secondly, you have a controller PlaylistCtrl, so you need to set it for router state.
// you may try simple view first
.state('app.packages', {
url: "/packages/:packagesId",
templateUrl: "templates/packages.html",
controller: 'PlaylistCtrl'

Related

If it possible to get the abstract controller from a nested state in $stateProvider

I'm using $stateProvider with AngularJS and I'm wondering if there's any way to get the abstract, or parent, controller from a child state. Before you throw $parent out there, it doesn't seem to work as I thought it would.
Example:
$stateProvider.state('page',
{
url: '/page',
abstract: true,
cache: false,
templateUrl: 'navigation.html',
controller: 'navigationController'
});
$stateProvider.state('page.login',
{
url: '/login',
templateUrl: '...',
views:
{
'login':
{
templateUrl: 'login.html',
controller: 'loginController'
}
}
});
So, the question is, how would I modify a value in navigationController from loginController.
EX:
var navigationController = function($scope) {
$scope.showNavigation = true;
}
var loginController = function($scope) {
$scope.onClicked = function() {
// navigationController::$scope.showNavigation = false
}
}
I've tried using $scope.$parent.showNavigation but that doesn't modify the value. Printing $scope.$parent yields an unreadable nested object of the current scope.

How to activate a state and pass object to the new view?

app.js:
$stateProvider.state('datasource', {
url: '/datasource',
templateUrl: 'views/datasource.html',
controller: 'datasourceController'
});
$stateProvider.state('datasourceList', {
url: '/datasource/:datasourceId',
templateUrl: 'views/datasource.list.html',
controller: 'datasourceController'
});
Then, I've a function activated onClick defined in (datasourceController)
$scope.submitSelected = function() {
if (angular.isDefined($scope.selectedSource)) {
$scope.datasource = dataSourcesService.find($scope.selectedSource.id);
$state.go('datasourceList', {datasourceId : datasource});
}
}
As I said, in my datasource.html view have an element click that triggers submitSelected() function
I can retrieve data successfully from my service based on ID when call it in function.
Problem is, i cant access the results (scope) of it in the view datasource.list.html after changing the state.
Add 'param' in state config
$stateProvider.state('datasource', {
url: '/datasource',
templateUrl: 'views/datasource.html',
controller: 'datasourceController'
});
$stateProvider.state('datasourceList', {
url: '/datasource/:datasourceId',
templateUrl: 'views/datasource.list.html',
params: ['index', 'anotherKey'],
controller: 'datasourceController'
});
And get values using $stateParams in another controller
app.controller('datasourceController', function($scope, $stateParams) {
var index = $stateParams.index;
var anotherKey = $stateParams.anotherKey;
});

How To Autoload ui-view on nested views?

I have code like this
<a ui-sref="nested.something">something</a>
<div ui-view="nested.something"></div>
how to load ui-view without click ui-sref ?
EXTEND - related to this plunker provided by OP in the comments above
The state definition is:
.state('store', {
views: {
'store': {
templateUrl: 'store.html'
}
}
})
.state('store.detail', {
views: {
'store_detail': {
templateUrl: 'store_detail.html'
}
}
})
Then in this updated plunker we can see that this would do the job
//$urlRouterProvider.otherwise('/store');
$urlRouterProvider.otherwise(function($injector, $location){
var state = $injector.get('$state');
state.go('store.detail');
return $location.path();
});
Reason? states do not have defined url. Which is a bit weird. So, I would honestly rather suggested to do it like this (the link to such plunker):
$urlRouterProvider.otherwise('/store/detail');
//$urlRouterProvider.otherwise(function($injector, $location){
// var state = $injector.get('$state');
// state.go('store.detail');
// return $location.path();
//});
$stateProvider
.state('store', {
url: '/store',
views: {
'store': {
templateUrl: 'store.html'
}
}
})
.state('store.detail', {
url: '/detail',
views: {
'store_detail': {
templateUrl: 'store_detail.html'
}
}
})
There is a working plunker
ORIGINAL
We can use the .otherwise(rule) of $urlRouterProvider, documented here
$urlRouterProvider.otherwise('/parent/child');
As the doc says:
otherwise(rule)
Defines a path that is used when an invalid route is requested.
So, this could be used for some default - start up "redirection"
The .otherwise() could be even a function, like shown here:
How not to change url when show 404 error page with ui-router
which takes '$injector', '$location' and can do even much more magic (on invalid or startup path)
$urlRouterProvider.otherwise(function($injector, $location){
var state = $injector.get('$state');
state.go('404');
return $location.path();
});
ALSO, if we want to fill in some more details into some nested viesw, we can do it by defining multi-named views:
.state('parent.child', {
url: "/child",
views: {
'' : {
templateUrl: 'tpl.child.html',
controller: 'ChildCtrl',
},
'nested.something#parent.child' : {
templateUrl: 'tpl.something.html',
},
}
})
So, if the tpl.child.html will have this anchor/target:
<i>place for nested something:</i>
<div ui-view="nested.something"></div>
it will be filled with the tpl.something.html content
Check it in action here

dynamic template based on $routeProvider resolves

I've got a url in my application that needs to load one of two templates based on the results of a resolve call, like so:
app.config(function($routeProvider) {
$routeProvider.
when('/someurl', {
resolve: {
someData: function(dataService) {
var data = dataService.loadData();
// data has a .type field that determines which template should be loaded
return data;
}
},
templateUrl: function(routeParams) {
// return a path based on the value of data.type in the someData resolve block
}
})
});
Is there a way for me to set the templateUrl based on what's returned by the someData resolve?
So I figured out how to do this using ui-router - thanks m59 for pointing me at it.
Here's how you'd do this with ui-router:
app.config(function($stateProvider) {
$stateProvider
.state('someState'
url: '/someurl',
template: '<ui-view>',
resolve: {
someData: function(dataService) {
var data = dataService.loadData();
// data has a .type field that determines which template should be loaded
return data;
}
},
controller: function($state, someData) {
$state.go('someState.' + someData.type);
}
})
.state('someState.type1', {
templateUrl: 'someTemplate1.html',
controller: 'Type1Controller'
})
.state('someState.type2', {
templateUrl: 'someTemplate2.html',
controller: 'Type2Controller'
})
});
There's a parent state that handles resolves, then redirects to the child states based on the information it gets. The child states don't have a url, so they can't be loaded directly.

Angular ui-router to accomplish a conditional view

I am asking a similar question to this question: UI Router conditional ui views?, but my situation is a little more complex and I cannot seem to get the provided answer to work.
Basically, I have a url that can be rendered two very different ways, depending on the type of entity that the url points to.
Here is what I am currently trying
$stateProvider
.state('home', {
url : '/{id}',
resolve: {
entity: function($stateParams, RestService) {
return RestService.getEntity($stateParams.id);
}
},
template: 'Home Template <ui-view></ui-view>',
onEnter: function($state, entity) {
if (entity.Type == 'first') {
$state.transitionTo('home.first');
} else {
$state.transitionTo('home.second');
}
}
})
.state('home.first', {
url: '',
templateUrl: 'first.html',
controller: 'FirstController'
})
.state('home.second', {
url: '',
templateUrl: 'second.html',
controller: 'SecondController'
});
I set up a Resolve to fetch the actual entity from a restful service.
Every thing seems to be working until I actually get to the transitionTo based on the type.
The transition seems to work, except the resolve re-fires and the getEntity fails because the id is null.
I've tried to send the id to the transitionTo calls, but then it still tries to do a second resolve, meaning the entity is fetched from the rest service twice.
What seems to be happening is that in the onEnter handler, the state hasn't actually changed yet, so when the transition happens, it thinks it is transitioning to a whole new state rather than to a child state. This is further evidenced because when I remove the entity. from the state name in the transitionTo, it believes the current state is root, rather than home. This also prevents me from using 'go' instead of transitionTo.
Any ideas?
The templateUrl can be a function as well so you check the type and return a different view and define the controller in the view rather than as part of the state configuration. You cannot inject parameters to templateUrl so you might have to use templateProvider.
$stateProvider.state('home', {
templateProvider: ['$stateParams', 'restService' , function ($stateParams, restService) {
restService.getEntity($stateParams.id).then(function(entity) {
if (entity.Type == 'first') {
return '<div ng-include="first.html"></div>;
} else {
return '<div ng-include="second.html"></div>';
}
});
}]
})
You can also do the following :
$stateProvider
.state('home', {
url : '/{id}',
resolve: {
entity: function($stateParams, RestService) {
return RestService.getEntity($stateParams.id);
}
},
template: 'Home Template <ui-view></ui-view>',
onEnter: function($state, entity) {
if (entity.Type == 'first') {
$timeout(function() {
$state.go('home.first');
}, 0);
} else {
$timeout(function() {
$state.go('home.second');
}, 0);
}
}
})
.state('home.first', {
url: '',
templateUrl: 'first.html',
controller: 'FirstController'
})
.state('home.second', {
url: '',
templateUrl: 'second.html',
controller: 'SecondController'
});
I ended up making the home controller a sibling of first and second, rather than a parent, and then had the controller of home do a $state.go to first or second depending on the results of the resolve.
Use verified code for conditional view in ui-route
$stateProvider.state('dashboard.home', {
url: '/dashboard',
controller: 'MainCtrl',
// templateUrl: $rootScope.active_admin_template,
templateProvider: ['$stateParams', '$templateRequest','$rootScope', function ($stateParams, templateRequest,$rootScope) {
var templateUrl ='';
if ($rootScope.current_user.role == 'MANAGER'){
templateUrl ='views/manager_portal/dashboard.html';
}else{
templateUrl ='views/dashboard/home.html';
}
return templateRequest(templateUrl);
}]
});

Resources