I have controller that needs to receive two id values. One id value identifies a vendor and the second identifies an event (eventId and VendorId).
My current state is as such.
.state('/vendordetail', {
url: '/vendordetail/:vendorId',
templateUrl: '/home/vendordetail',
controller: 'VendorDetailController',
resolve: {
vendorId: ['$stateParams', function ($stateParams) {
return $stateParams.vendorId;
}],
vendorPreload: ['$stateParams', 'vendorDetailRepo', '$state', function ($stateParams, vendorDetailRepo, $state) {
if ($stateParams.vendorId != "")
return vendorDetailRepo.get({ id: $stateParams.vendorId }).$promise;
}]
}
});
At the moment I am able to take the vendorId. But I would like to include an eventId in the state. Can anyone help me modify my state to take the second parameter (eventId) ?
Thank you.
First oft all I would advice you to put your parameters as url-parameters if you don't have good reasons against it.
Following this advice your state may look as follows:
state('/vendordetail', {
url: '/vendordetail?:vendorId:eventId',
templateUrl: '/home/vendordetail',
controller: 'VendorDetailController',
resolve: {
vendorId: ['$stateParams', function ($stateParams) {
return $stateParams.vendorId;
}],
eventId: ['$stateParams', function ($stateParams) {
return $stateParams.eventId;
}],
vendorPreload: ['$stateParams', 'vendorDetailRepo', '$state', function ($stateParams, vendorDetailRepo, $state) {
if ($stateParams.vendorId != "")
return vendorDetailRepo.get({ id: $stateParams.vendorId }).$promise;
}]
}
});
By the way: you don't need to resolve the parameters. You can simply inject $stateParams into your controller.
url: '/vendordetail/:vendorId'/:eventId,
Not sure why you have a vendorId in the resolve as well as the url part. As long as $stateParams is injected into your controller, you can access them that way.
Related
Can someone explain how to use parameters sent with $state.go? In CreatePollController I create a poll which I send to the state add_data_poll (AddDataPollController), but I really don't know how to access this parameter to display it in the view or use it in the controller (I tried to see the response with console.log($scope.response), but it doesn't work), can anyone explain me?
angular.module('estudios')
.controller('CreatePollController', ['$scope', 'Restangular', '$state',
function($scope, Restangular, $state) {
$scope.addPoll = function() {
if ($scope.allow_anonymous_answer == null)
$scope.allow_anonymous_answer = false
var poll = {title: $scope.title, description: $scope.description, allow_anonymous_answer: $scope.allow_anonymous_answer, initial_message: $scope.initial_message, final_message: $scope.final_message};
Restangular.all('polls').post(poll).then(function(response) {
$state.go('add_data_poll', response);
});
};
}])
.controller('AddDataPollController', ['$scope', 'Restangular',
function($scope, Restangular) {
}]);
And these are the corresponding states.
.state('create_poll', {
url: '/create_poll',
parent: 'home',
templateUrl: 'poll/create_poll.html',
controller: 'CreatePollController'
})
.state('add_data_poll', {
url: '/create_poll/add_data_poll',
parent: 'home',
templateUrl: 'poll/add_data_poll.html',
controller: 'AddDataPollController'
You need to have either params defined in your state or query params defined in your state url.
Example for state params:
.state('add_data_poll', {
url: '/create_poll/add_data_poll',
params: {
// define object with parameters that you want to pass
// Example:
id: 1 // 1 is the default parameter if no id is passed
}
parent: 'home',
templateUrl: 'poll/add_data_poll.html',
controller: 'AddDataPollController'
This way you can send parameters but they won't be available in the query string and upon refresh they will be lost.
Example for defining query parameters:
.state('add_data_poll', {
url: '/create_poll/add_data_poll?someParameter&anotherOne',
parent: 'home',
templateUrl: 'poll/add_data_poll.html',
controller: 'AddDataPollController'
someParameter and anotherOne will be available if you pass them from the incoming state.
When passing parameters you should define what parameters you are passing.
$state.go('some.route', {id: 2, someParam: 'coolParam');
And then you can access them with $stateParams in the controller. But first you need to inject it.
myApp.controller('myCtrl', function($stateParams) {
console.log($stateParams);
});
It is not good idea to pass the whole response from an API. Better will be if you choose just the stuff you need from the response and build your state around them.
Read more about ui-router state params HERE
I can't retrieve parameters passed from ui-router in Ionic.
Parameters passed into the Controller are undefined
This is my state code:
.state('app.dayliston', {
cache: false,
url: '/myurl',
views: {
'mainContent': {
templateUrl: 'calendar/daylist.html',
controller: 'MyCtrl',
params : { 'mode':'online'}
}
}
})
and here is My Controller code:
.controller('MyCtrl', function($scope,$state, $stateParams,CalendarFactory,FBFactory, $ionicHistory,$ionicScrollDelegate,$ionicModal,$ionicPopup, $timeout) {
console.log('MyCtrl')
console.log('mode'+$stateParams.mode) // mode is undefined
....
})
I'm using 1.6.1. Is there anything wrong with my code?
As I can see in your code, you dont need to use $stateParams because you don't get the "mode" parameter from the URL.
I think attached data in state will be a better choice (Docs):
.state('app.dayliston', {
cache: false,
url: '/myurl',
data:{
mode: 'online'
},
views: {
'mainContent': {
templateUrl: 'calendar/daylist.html',
controller: 'MyCtrl'
}
}
})
Then you can get the data stored in state like this:
.controller('MyCtrl', function($scope, $state, $stateParams, CalendarFactory, FBFactory, $ionicHistory, $ionicScrollDelegate, $ionicModal, $ionicPopup, $timeout) {
console.log('MyCtrl')
console.log('mode'+$state.current.data.mode) // "online"
})
MyCtrl is the actual name of your controller. It's not a parameter that's passed to the controller per se.
Route:
.state('app.dayliston', {
cache: false,
url: '/myurl/:mode',
views: {
'mainContent': {
templateUrl: 'calendar/daylist.html',
controller: 'MyCtrl'
}
}
})
Check URL Routing Query Parameters doc
Link from view:
<a ui-sref="app.dayliston({mode: 'online'});">Go to dayliston</a>
Go to state/route from controller:
$state.go('app.dayliston', {mode: 'online'});
you are passing the $stateParams incorrectly
https://github.com/angular-ui/ui-router/wiki/URL-Routing#stateparams-service
The should be on the url or you can pass data in using the resolve map on the state.
https://github.com/angular-ui/ui-router/wiki#resolve
also passing in custom data might be a better approach? Hard to tell from the code sample you provided
I am in the process of converting my current angular project to use ui-router and I am a little confused. The documentation states I add my controller as such:
$stateProvider.state('contacts.detail', {
url: '/contacts/:contactId',
controller: function($stateParams){
$stateParams.contactId //*** Exists! ***//
}
})
I have defined my old controller in this manner:
xap.controller('DemoCtrl', [$scope, function ($scope, demoService) {
})
where xap is defined as:
var xap = angular.module({ .... })
What is the correct integration method?
Thanks
You can refer to a pre-registered controller by name:
$stateProvider.state('contacts.detail', {
url: '/contacts/:contactId',
controller: 'DemoCtrl'
});
You can add the $stateParams dependency to your controller to access parameters:
xap.controller('DemoCtrl', [
'$scope',
'$stateParams',
'demoService',
function ($scope, $stateParams, demoService) {
$stateParams.contactId //*** Exists! ***//
}
]);
But you can also inline your controllers and therefore not have to come up with unique names for each controller for every state:
$stateProvider.state('contacts.detail', {
url: '/contacts/:contactId',
controller: [
'$scope',
'$stateParams',
'demoService',
function ($scope, $stateParams, demoService) {
$stateParams.contactId //*** Exists! ***//
}
]
});
The controller in the state is not a resolve field.
In the state, you have to put only controller name because when you declare it, it's "injected" into your angular module.
So, you have to put controller name like this :
$stateProvider.state('contacts.detail', {
url: '/contacts/:contactId',
controller: 'ContactsCtrl'
});
If you want to inject some variable, you can add an object in the state like this :
$stateProvider.state('contacts.detail', {
url: '/contacts/:contactId',
controller: 'ContactsCtrl',
myVar: function(...){
return '...';
}
});
So, if you put a function, it's for a resolve field and not for controllers... You can implement it into state but it's better to do it outside state declaration.
I need to get some content data to my controller:
state('admin.businesses.employees.all', {
resolve: {
executorsListTitle: 'All employees',
executorsEmptyListMessage: 'Add the first employee'
},
url: '/all',
controller: 'ExecutorsController',
templateUrl: 'templates/admin/executors/index.html'
})
And a controller code:
module.controller(
'ExecutorsController',
[
'$scope', '$rootScope', '$state',
'$stateParams', '$modal', 'executorsListTitle',
'executorsEmptyListMessage', 'Executor',
function($scope, $rootScope, $state, $stateParams, $modal, executorsListTitle, executorsEmptyListMessage, Executor) {
// Some code
}
)
But when I try to get into this state I can't do it - click by button makes nothing; if I remove resolve from state description it works good. What I do wrong? Thanks!
The resolve of the state machine expects a key and a factory. The doc states:
key – {string}: a name of a dependency to be injected into the controller.
factory - {string|function}
And when you provide a string to the factory:
If string, then it is an alias for a service.
If you want to return a string, you can do the following:
state('admin.businesses.employees.all', {
resolve: {
executorsListTitle: function() {
return 'All employees';
},
executorsEmptyListMessage: function() {
return 'Add the first employee';
},
},
url: '/all',
controller: 'ExecutorsController',
templateUrl: 'templates/admin/executors/index.html'
})
If you are using static data (the strings you are resolving to), you can also use the custom data property:
state('admin.businesses.employees.all', {
data: {
executorsListTitle: 'All employees',
executorsEmptyListMessage: 'Add the first employee'
},
url: '/all',
controller: 'ExecutorsController',
templateUrl: 'templates/admin/executors/index.html'
})
If you use this method, in the controller you can access the data like this:
$state.current.data.executorsListTitle
You can use strings directly with this method. Here is the doc for the custom data property.
So consider the following fragment from my angularUI routing setup. I am navigating to the route /category/manage/4/details (for example). I expect 'category' to be resolved before the relevant controller loads, and indeed it is to the extent that I can put a breakpoint inside the resolve function that returns the category from the category service and see that the category has been returned. Now putting another breakpoint inside the controller itself I can see that 'category' is always undefined. It is not injected by UI router.
Can anyone see the problem? It may be somewhere other than in the code I've provided but as I have no errors when I run the code, it's impossible to tell where the source of the issue might lie. Typical js silent failures!
.state('category.manage', {
url: '/manage',
templateUrl: '/main/category/tree',
controller: 'CategoryCtrl'
})
.state('category.manage.view', {
abstract: true,
url: '/{categoryId:[0-9]*}',
resolve: {
category: ['CategoryService', '$stateParams', function (CategoryService, $stateParams) {
return CategoryService.getCategory($stateParams.categoryId).then(returnData); //this line runs before the controller is instantiated
}]
},
views: {
'category-content': {
templateUrl: '/main/category/ribbon',
controller: ['$scope', 'category', function ($scope, category) {
$scope.category = category; //category is always undefined, i.e., UI router is not injecting it
}]
}
},
})
.state('category.manage.view.details', {
url: '/details',
data: { mode: 'view' },
templateUrl: '/main/category/details',
controller: 'CategoryDetailsCtrl as details'
})
The concept is working. I created working plunker here. The changes is here
instead of this
resolve: {
category: ['CategoryService', '$stateParams', function (CategoryService, $stateParams) {
//this line runs before the controller is instantiated
return CategoryService.getCategory($stateParams.categoryId).then(returnData);
}]
},
I just returned the result of the getCategory...
resolve: {
category: ['CategoryService', '$stateParams', function (CategoryService, $stateParams) {
return CategoryService.getCategory($stateParams.categoryId); // not then
}]
},
with naive service implementation:
.factory('CategoryService', function() {return {
getCategory : function(id){
return { category : 'SuperClass', categoryId: id };
}
}});
even if that would be a promise... resolve will wait until it is processed...
.factory('CategoryService', function($timeout) {return {
getCategory : function(id){
return $timeout(function() {
return { category : 'SuperClass', categoryId: id };
}, 500);
}
}});