Angular state : pass multiple parameter without changing url querystring to controller - angularjs

I want to send a parameter from app.run to my loginController. Because, I call a state.go() from the $rootScope.$on() defined inside the app.run.
app.run('$rootScope', '$state', '$stateParams',function($rootScope, $state, $stateParams(){
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
$rootScope.$on('unauthorized_access', function (event, args) {
$state.go("page.login", {'error': args.error,'msg': args.msg});
});
}]);
I have
app.config(['$stateProvider','$urlRouterProvider',function($stateProvider, $urlRouterProvider, $httpProvider){
$urlRouterProvider.otherwise('/');
$stateProvider
// some parts omitted...
.state('page.login', {
url: '/login',
views: {
'page': {
templateUrl: 'app/landingPage/login.html',
controller: 'loginController',
params: {obj : {error : null, message: null} }
}
}
});
}]);
and I want to pass parameters to the loginController from app.run, through $state.go() during transition.
$state.go("page.login", {'error': err,'message': msg});
and in my controller, this is how I am trying to receive the params...
app.controller('loginController',['$scope', '$state', '$stateParams', function($scope, $state, $stateParams){
console.log($stateParams.obj);
}]);
I do not want to change the url to >> url: '/login/:params' etc. in stateProvider
I referenced this page : stackoverflow example
but,was not helpful. Any help is appreciated. Apologies for my poor communication.

After a long research, I ended up with weird solution. I still doubt, whether this is even a solution. However, it does work for me.... I made a hack of ui.router LOL ....
I am using Angular ui-router version v0.2.18. and there at line no. 3160, they have put a line of code like :
// Store the hash param for later (since it will be stripped out by various methods)
var hash = toParams['#'];
and in line no. 3223 they have
if (shouldSkipReload(to, toParams, from, fromParams, locals, options)) {
if (hash) toParams['#'] = hash;
So, I thought of passing my object with a '#' key like this
.state('page.login', {
url: '/login',
views: {
'body#page': {
templateUrl: 'app/landingPage/login.html',
controller: 'loginController',
params: {'#' : null},
}
},
authenticate: false
});
and like this
$rootScope.$on('unauthorized_access', function (event, args) {
$state.go("page.login", {'#' : {'error': args.error,'msg': args.msg}});
});
and surprise, it worked.....
I got the object logged in console : console.log($stateParams['#']);
I know the solution is cunning[udayip as in malayalam]... but then it worked for me... I will not mark this as an answer. So, I request some angular experts to provide a real solution. If some experts say, this can be a solution, I will mark this as the answer.

Related

Inject a resolve provider from child state to controller

So i'm trying to pull some id from the url parameters.
Here are my states :
$stateProvider
.state('parent', {
url: '/parent',
templateUrl: 'path/to/parent.html',
controller: 'lolController'
})
.state('parent.child', {
url: '/child-profile/:id',
templateUrl: 'path/to/child.html',
resolve: {
someId: function ($stateParams) {
// I cant print the id from here
console.log("PARAMS", $stateParams.id)
return $stateParams.id;
}
},
})
Controller
.controller('lolController',
['$scope', 'someId', function ($scope, someId) {
$scope.someId = someId;
}])
But whenever i'm trying to access the url /parent/child-profile/123abc i'm getting the error Unknown provider: someId See error here..
How do I fix this? Thanks.
EDIT
The answer provided by Jay Shukla helped me get this idea.
The parameter is undefined because I declared the controller on the parent state before actually calling the child state which contains the value from it's url. Here's a simple solution I came up with, with Jay Shukla's help.
$stateProvider
.state('parent', {
url: '/parent',
templateUrl: 'path/to/parent.html',
})
.state('parent.child', {
url: '/child-profile/:id',
templateUrl: 'path/to/child.html',
controller: 'lolController'
})
I removed the controller declaration from the parent state and moved it to the child state. Since in my situation the parent state's template only contains a <div ui-view></div>.
The idea is :
Only state is nested but both html are separate so controller models will not be inherited - Jay Shukla
Each state can have their own controller.
Please add/edit more to improve this question.
Try to inject $stateParams then you will get id in that object.
Like this
.controller('lolController',
['$scope', '$stateParams', function ($scope, $stateParams) {
$scope.someId = $stateParams.id;
}])
You can also defined your parameters in different ways as below
url: '/child-profile/:id', // Inside stateparams you will get id as key
OR
url: '/child-profile/{id}',
OR
url: '/child-profile/:{id:int}', // Id with integer value

$stateProvider params null with ionic

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

AngularJS (ionic) - $routeParams argument from URL

I'm new with AngularJS and I'm wondering about the reading-limits of the a $routeParams-Service... reading the URL-arguments.. whether f.i. "/" - a slash would disrupt the workflow...? .. or is there a usable workaround?
Codeexample: (partly from Ionic Starter App)
App.js
.config(function ($stateProvider, $urlRouterProvider, USER_ROLES) {
$stateProvider
.state('main.product/:productId', {
url: 'main/product/:productId',
views: {
'menuContent': {
templateUrl: 'templates/product.html',
controller: 'productIdCtrl'
}
}
})
.controller('productIdCtrl'),
function($scope, $location, $routeParams, ProductDataService){
var pId = $routeParams.productId; // Reading productId from URL
}
Inside the database its sadly possible to use "/" - slash as an "productId"-Name. Probably some other special characters... which I have yet to explore.. so I dont think this will work..?
So my question is, where are the limits .. which characters would need a major workaround.
(In Order to read Data from the database I should probably use get/post with json.php ... but I'm not there yet (but I surely like advice :D)
It is supposed to simply read data from the database.. with a small searchengine which is already realized on another system and I just need to 'get' and display the data...)
Here correctly
...
.state('main.product.id', {
url: 'main/product/:productId',
views: {
'menuContent': {
templateUrl: 'templates/product.html',
controller: 'productIdCtrl'
}
}
})
...
.controller("AppController", function($scope, $state){
$scope.openProduct = function(){
$state.go('main.product.id', {productId: 1});
};
});

Angular ui.router. Deep nested routes

Here is an example to check http://embed.plnkr.co/uVMlkk/preview
When we navigate to 'page2' route there is a 'hey, I'm a subroute' note.
But once we navigate anywhere else that note will disappear forever.
The goal is to make some nested states to be shown right away (as a default ones).
I assume there should be some cases using $state.go(), but can't figure it out so far. Any help is highly appreciated.
State definition snippet:
.state('root.page2.tab', {
url: '/:tabId',
templateUrl: 'tpl.page2.tab.html',
controller: 'Page2TabController'
})
.state('root.page2.tab.subroute', {
url: '',
templateUrl: 'tpl.page2.tab.subroute.html'
})
the content of the 'tpl.page2.tab.subroute.html':
hey, I'm a subroute
related controller:
.controller('Page2TabController', ['$scope', '$state', function($scope, $state) {
$scope.tabId = $state.params.tabId;
$state.go('root.page2.tab.subroute');
}])
There is a fixed version.
I removed the url from the 'root.page2.tab.subroute'
.state('root.page2.tab.subroute', {
//url: '',
templateUrl: 'tpl.page2.tab.subroute.html'
})
And because the parent has defined paramater tabId:
.state('root.page2.tab', {
url: '/:tabId',
templateUrl: 'tpl.page2.tab.html',
controller: 'Page2TabController'
})
We have to pass that param inside of the redicrection:
.controller('Page2TabController', ['$scope', '$state', function($scope, $state) {
$scope.tabId = $state.params.tabId;
// instead of this
// $state.go('root.page2.tab.subroute');
// we need this
$state.go('root.page2.tab.subroute', $state.params);
}])
Check the working, fixed version here
ANOTHER approach - using redirectTo - there is a working plunker
One way, inspired by this:
Redirect a state to default substate with UI-Router in AngularJS
could be to add a very smart but small redirect code snippet:
.run(['$rootScope', '$state', function($rootScope, $state) {
$rootScope.$on('$stateChangeStart', function(evt, to, params) {
if (to.redirectTo) {
evt.preventDefault();
$state.go(to.redirectTo, params)
}
});
}])
And adjust our state like this:
.state('root.page2.tab', {
url: '/:tabId',
templateUrl: 'tpl.page2.tab.html',
controller: 'Page2TabController',
redirectTo: 'root.page2.tab.subroute',
})
Check it here
There is a trick how to handle scenarios:
Parent should trigger some action in case that
it is accessed, or
its reached again, when navigating back from child in a parent state
In that case, we can use the "target (ui-view) for a child" as a place where sits the special view, with special controller. This will be
injected into that position once parent is created and
re-injected into that position again, once child is left. In that case, it will be re-init.
Enough explanation. There is a working plunker. There is adjusted state:
.state('root.page2', {
url: '/page2',
views: {
'content#root': {
templateUrl: './tpl.page2.html',
controller: 'Page2Controller'
},
'#root.page2': {
template: '<div></div>',
controller: 'RedirectorController'
}
}
})
So, now we can do some magic inside of our 'RedirectorController'
.controller('RedirectorController', ['$scope', '$state',
function($scope, $state) {
$state.go('root.page2.tab', { tabId: $scope.activeTabId });
}])
Check it in action here
Read more about what that new view/controller get from the other (Scope Inheritance by View Hierarchy Only) one here
Nested states or views for layout with leftbar in ui-router?
How do I share $scope data between states in angularjs ui-router?

How to send and retrieve parameters using $state.go toParams and $stateParams?

I am using AngularJS v1.2.0-rc.2 with ui-router v0.2.0. I want to pass the referrer state to another state so I use the toParams of $state.go like so:
$state.go('toState', {referer: $state.current.name});
According to the docs, this should populate the $stateParams on the toState controller, but it is undefined. What am I missing?
I've created a plunk to demonstrate:
http://plnkr.co/edit/ywEcG1
If you want to pass non-URL state, then you must not use url when setting up your state. I found the answer on a PR and did some monkeying around to better understand.
$stateProvider.state('toState', {
templateUrl:'wokka.html',
controller:'stateController',
params: {
'referer': 'some default',
'param2': 'some default',
'etc': 'some default'
}
});
Then you can navigate to it like so:
$state.go('toState', { 'referer':'jimbob', 'param2':37, 'etc':'bluebell' });
Or:
var result = { referer:'jimbob', param2:37, etc:'bluebell' };
$state.go('toState', result);
And in HTML thusly:
<a ui-sref="toState(thingy)" class="list-group-item" ng-repeat="thingy in thingies">{{ thingy.referer }}</a>
This use case is completely uncovered in the documentation, but I think it's a powerful means on transitioning state without using URLs.
The Nathan Matthews's solution did not work for me but it is totally correct but there is little point to reaching a workaround:
The key point is: Type of defined parameters and toParamas of $state.go should be same array or object on both sides of state transition.
For example when you define a params in a state as follows you means params is array because of using "[]":
$stateProvider
.state('home', {
templateUrl: 'home',
controller: 'homeController'
})
.state('view', {
templateUrl: 'overview',
params: ['index', 'anotherKey'],
controller: 'overviewController'
})
So also you should pass toParams as array like this:
params = { 'index': 123, 'anotherKey': 'This is a test' }
paramsArr = (val for key, val of params)
$state.go('view', paramsArr)
And you can access them via $stateParams as array like this:
app.controller('overviewController', function($scope, $stateParams) {
var index = $stateParams[0];
var anotherKey = $stateParams[1];
});
Better solution is using object instead of array in both sides:
$stateProvider
.state('home', {
templateUrl: 'home',
controller: 'homeController'
})
.state('view', {
templateUrl: 'overview',
params: {'index': null, 'anotherKey': null},
controller: 'overviewController'
})
I replaced [] with {} in params definition. For passing toParams to $state.go also you should using object instead of array:
$state.go('view', { 'index': 123, 'anotherKey': 'This is a test' })
then you can access them via $stateParams easily:
app.controller('overviewController', function($scope, $stateParams) {
var index = $stateParams.index;
var anotherKey = $stateParams.anotherKey;
});
All I had to do was add a parameter to the url state definition like so
url: '/toState?referer'
Doh!
Not sure if it will work with AngularJS v1.2.0-rc.2 with ui-router v0.2.0.
I have tested this solution on AngularJS v1.3.14 with ui-router v0.2.13.
I just realize that is not necessary to pass the parameter in the URL as gwhn recommends.
Just add your parameters with a default value on your state definition.
Your state can still have an Url value.
$stateProvider.state('state1', {
url : '/url',
templateUrl : "new.html",
controller : 'TestController',
params: {new_param: null}
});
and add the param to $state.go()
$state.go('state1',{new_param: "Going places!"});
None of these examples on this page worked for me. This is what I used and it worked well. Some solutions said you cannot combine url with $state.go() but this is not true. The awkward thing is you must define the params for the url and also list the params. Both must be present. Tested on Angular 1.4.8 and UI Router 0.2.15.
In the state add your params to end of state and define the params:
url: 'view?index&anotherKey',
params: {'index': null, 'anotherKey': null}
In your controller your go statement will look like this:
$state.go('view', { 'index': 123, 'anotherKey': 'This is a test' });
Then to pull the params out and use them in your new state's controller (don't forget to pass in $stateParams to your controller function):
var index = $stateParams.index;
var anotherKey = $stateParams.anotherKey;
console.log(anotherKey); //it works!
In my case I tried with all the options given here, but no one was working properly (angular 1.3.13, ionic 1.0.0, angular-ui-router 0.2.13). The solution was:
.state('tab.friends', {
url: '/friends/:param1/:param2',
views: {
'tab-friends': {
templateUrl: 'templates/tab-friends.html',
controller: 'FriendsCtrl'
}
}
})
and in the state.go:
$state.go('tab.friends', {param1 : val1, param2 : val2});
Cheers
I've spent a good deal of time fighting with Ionic / Angular's $state & $stateParams;
To utilize $state.go() and $stateParams you must have certain things setup and other parameters must not be present.
In my app.config() I've included $stateProvider and defined within it several states:
$stateProvider
.state('home', {
templateUrl: 'home',
controller: 'homeController'
})
.state('view', {
templateUrl: 'overview',
params: ['index', 'anotherKey'],
controller: 'overviewController'
})
The params key is especially important. As well, notice there are NO url keys present... utilizing stateParams and URLs do NOT mix. They are mutually exclusive to each other.
In the $state.go() call, define it as such:
$state.go('view', { 'index': 123, 'anotherKey': 'This is a test' })
The index and anotherKey $stateParams variables will ONLY be populated if they are first listed in the $stateController params defining key.
Within the controller, include $stateParams as illustrated:
app.controller('overviewController', function($scope, $stateParams) {
var index = $stateParams.index;
var anotherKey = $stateParams.anotherKey;
});
The passed variables should be available!
Try With reload: true?
Couldn't figure out what was going on for the longest time -- turns out I was fooling myself. If you're certain that things are written correctly and you will to use the same state, try reload: true:
.state('status.item', {
url: '/:id',
views: {...}
}
$state.go('status.item', { id: $scope.id }, { reload: true });
Hope this saves you time!
I'd faced a similar problem. I ended up with a working solution after a lot of googling and trial and test. Here is my solution which would work for you.
I have two controllers - searchBoxController and stateResultController and a parameter named searchQuery to be passed from a view having a search box to a view showing the results fetched from a remote server. This is how you do it:
Below is the controller from which you call the next view using $state.go()
.controller('searchBoxController', function ($scope, $state) {
$scope.doSearch = function(){
var searchInputRaw = $scope.searchQueryInput;
$state.go('app.searchResults', { searchQuery: searchInput });
}
})
Below is the state that would be called when the $state.go() gets executed:
.state('app.searchResults',
{
url: '/searchResults',
views:
{
'menuContent': { templateUrl: 'templates/searchResult.html', controller: 'stateResultController' }
},
params:
{
'searchQuery': ''
}
})
And finally, the controller associated with the app.searchResults state:
.controller('stateResultController', function ($scope, $state, $stateParams, $http) {
$scope.searchQueryInput = $stateParams.searchQuery;
});
And in my case of a parent/child state. all the parameters declared in child state has to be known by the parent state
.state('full', {
url: '/full',
templateUrl: 'js/content/templates/FullReadView.html',
params: { opmlFeed:null, source:null },
controller: 'FullReadCtrl'
})
.state('full.readFeed', {
url: '/readFeed',
views: {
'full': {
templateUrl: 'js/content/templates/ReadFeedView.html',
params: { opmlFeed:null, source:null },
controller: 'ReadFeedCtrl'
}
}
})
The solution we came to having a state that took 2 parameters was changing:
.state('somestate', {
url: '/somestate',
views: {...}
}
to
.state('somestate', {
url: '/somestate?id=:&sub=:',
views: {...}
}
Your define following in router.js
$stateProvider.state('users', {
url: '/users',
controller: 'UsersCtrl',
params: {
obj: null
}
})
Your controller need add $stateParams.
function UserCtrl($stateParams) {
console.log($stateParams);
}
You can send an object by parameter as follows.
$state.go('users', {obj:yourObj});
I was trying to Navigate from Page 1 to 2, and I had to pass some data as well.
In my router.js, I added params name and age :
.state('page2', {
url: '/vehicle/:source',
params: {name: null, age: null},
.................
In Page1, onClick of next button :
$state.go("page2", {name: 'Ron', age: '20'});
In Page2, I could access those params :
$stateParams.name
$stateParams.age
If this is a query parameter that you want to pass like this:
/toState?referer=current_user
then you need to describe your state like this:
$stateProvider.state('toState', {
url:'toState?referer',
views:{'...'}
});
source: https://github.com/angular-ui/ui-router/wiki/URL-Routing#query-parameters

Resources