Angular UI-Router: Accept same query parameter on every url - angularjs

I'm curious if there's a way to configure UI-Router to accept a query string parameter for all routes in an application.
For context, I have a resolve handler on all of my application's routes, which takes in a query parameter and triggers some behaviour based on that parameter. Here's a reduced version of my application's state definitions:
$stateProvider
.state('state1', {
url: '/state1?myparam'
resolve: myHandler,
templateUrl: 'state1.html',
controller: 'Ctrl1',
})
.state('state2', {
url: '/state2?myparam',
resolve: myHandler,
// [etc]
})
.state('state2.child1', {
url: '/state2/child1?myparam',
resolve: myHandler,
// [etc]
})
// [and a bunch more similar '.state's];
This works fine, and I'm able to access the myparam value inside of myHandler via $stateParams. It just seems a bit repetitive to add ?myparam to every route definition's url.
Any suggestions?

Did you tried using $urlMatcherFactory.
Snippet:
var urlMatcher = $urlMatcherFactory.compile("/state2/:id?param1");
$stateProvider.state('myState', {
url: urlMatcher
});
Hope this query params and urlMatcherFactory filehelps you.
P.S: I did not test this code.

Related

Are query parameters in Angular state URLs carried to nested states?

I'm using angular^1.8.0 and I have several substates that I would like to all have access to a common URL parameter. I don't have any route at /.
Here's an example of what I mean:
$stateProvider
.state('app', {
url: '?hl', // also tried /?hl
resolve: {
handleHl: function($stateParams) {
console.log($stateParams); // outputs { hl: undefined ... } for all routes
}
}
})
.state('app.dashboard', {
url: '/dashboard'
});
Is there any way to make this work? Or do I have to edit the url parameter of all the substates?
You defined a query param, and you want to see it in state params.
According to the ui-router doc:
The state params should be start with :
:hl
The query params can be specified following a '?'
?hl

passing parameters in nested views with ui-router

I am running into trouble understanding how you can correctly pass parameters using AngularJS.
This is the code I was trying to use in my app.js file for the nested views, however, the nest state never properly renders.
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('news', {
url: '/news',
templateUrl: 'templates/news.html',
controller: 'NewsCtrl'
})
.state('news.id', {
url: '/news/:id',
templateUrl: 'templates/news.id.html',
controller: 'NewsCtrl'
});
// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/news');
})
It will try and change the url to #/news/news/:id versus just #/news/:id.
And if I try and change the path to just be the #/news/:id, then the pages do not render correctly.
What is the best approach to achieve these nested views with parameters?
According to ui-route wiki:
When using url routing together with nested states the default
behavior is for child states to append their url to the urls of each
of its parent states.
If you want to have absolute url matching, then you need to prefix
your url string with a special symbol '^'.
So in your case, you should try
.state('news.id', {
url: '^/news/:id',
templateUrl: 'templates/news.id.html',
controller: 'NewsCtrl'
});

Angularjs ui-router - pass extras 'unplanned' parameters

I have this simple state :
.state('search', {
url: '/search',
templateUrl: 'views/search.html',
controller: 'search'
})
And I would like to pass any extra unplanned parameters to the controller when using search state or /search route :
ui-sref="search({foo:1, bar:2})"
// would call '#/search?foo=1&bar2',
// match the state and pass foo and bar to the controller (through $stateParams)
When I try this, it matches the otherwise of the router instead. :(
I've read a lot of solutions that imply to declare each parameter in the state:
.state('search', {
url: '/search?param1&param2&param3?...',
})
But I cannot do this as far as the parameters list is not really defined and changes all the time depending on searched content.
Is there a way to achieve this ? Or am I wrong somewhere ?
Thx.
EDIT : When I try to call directly this url : #/search?foo=1, the state search matches but the foo parameter never goes to $stateParams which is empty. I don't know how to get it in.
.state('search', {
params: ['param1','param2','param3'],
templateUrl: '...',
controller: '...'
});
ui-sref="search({param1:1, param2:2})"
Credit goes to Parameters for states without URLs in ui-router for AngularJS

AngularJs UI router - one state with multiple URLs

I have a request to add in another URL parameter that directs to a state that I already have set up. For efficiency purposes, I'm trying to see if I can add multiple URLs to point to the same state, or should I just use the $UrlRouterProvider.when() method to re-direct to that state in this new case.
Ex. this is what already exists
.state('site.link1',
{
url: '/link1',
templateUrl: '/views/link1.html',
controller: 'link1Ctrl'
})
and the request is to add www.site.com/newlink that points to the link1 page. Is there something like this;
.state('site.link1',
{
url: '/link1, /newlink',
...
Try using the Regex and a parameter in the url. It is not optimal but works.
.state('site.link1',
{
url: '/{path:link1|newlink}',
templateUrl: '/views/link1.html',
controller: 'link1Ctrl'
})
More information on regex in Urls.
To generate links with ui-sref pass the same parameter with the state name as a function
<a ui-sref="site.link1({path:'link1'})" >site link 1</a>
<a ui-sref="site.link1({path:'newlink'})">site new link</a>
You use params:
https://github.com/angular-ui/ui-router/wiki/URL-Routing
.state('site.link',
{
url: '/{link}'
..
}
so when you use the same state like this
$state.go('site.link', {link: 'link1'})
$state.go('site.link', {link: 'link2'})
you can used when() function
.state('site.link1',
{
url: '/link1',
templateUrl: '/views/link1.html',
controller: 'link1Ctrl'
})
then on root config
angular.module('myApp', [...])
.config(function ($urlRouterProvider) {
$urlRouterProvider.when(/newlink/, ['$state','$match', function ($state, $match) {
$state.go('site.link1');
}]);
});
I found this approach to be quite simple and clean: create two equal states, just changing the url property
//Both root and login are the same, but with different url's.
var rootConfig = {
url: '/',
templateUrl:'html/authentication/login.html',
controller: 'authCtrl',
data: {
requireLogin: false
}
}
var loginConfig = Object.create(rootConfig)
loginConfig.url = '/login'
$stateProvider
.state('root', rootConfig)
.state('login', loginConfig)
I had almost the same problem, only with another constraint - I didn't want to use a redirect, since I wanted the url in the browser to stay the same, but display the same state.
This was because I wanted the chrome saved passwords to work for users that already saved the previous url.
In my case I wanted these two urls :
/gilly and
/new/gilly
to both point to the same state.
I solved this by having one state defined for /gilly, and for the second url, I defined an abstract state called /new.
This should be set up like this :
$stateProvider.state('new', {
abstract: true,
url: '/new'
template: '',
controller: function() { }
}).state('gilly', {
url: '/gilly',
template: 'gilly.html',
controller: 'GillyController'
}).state('new.gilly', {
url: '/gilly', // don't add the '/new' prefix here!
template: 'gilly.html',
controller: 'GillyController'
});

How can I change my AngularJS routes to file?param1=a&param2=b format?

I need to change an existing AngularJS application from using URLs in the format:
example.com/thePage/#/section/1/subsection/1
To making the section & subsection parameters readable by the server with a format like so:
example.com/thePage?section=1&subsection=1
The environment does not offer something like mod_rewrite, so I need to change the routing in Angular to make it handle & generate these URLs. I believe I can do this using $locationProvider.html5Mode(true); however I’m not sure how to proceed from there. I’ve tried updating the existing routing to something like the below, however it fails to return a view (as if the routing isn’t working.
$stateProvider
.state('section', {
abstract: true,
url: '?section',
views: {
'header': {
template: '<h3></h3>'
},
'main': {
templateUrl: constants.baseUrl + 'views/section.html',
controller: 'sectionCtrl',
resolve: {
section: ['sectionervice', '$stateParams',
function (sectionervice, $stateParams) {
return sectionervice.getsection($stateParams);
}],
subsection: ['sectionervice', '$stateParams',
function (sectionervice, $stateParams) {
return sectionervice.getsubsection($stateParams);
}]
}
}
}
})
.state('section.detail.subsection', {
url: '&subsection=:sectionId',
views: {
'main': {
templateUrl: constants.baseUrl + 'views/section.detail.subsection.html',
controller: 'DictionaryCtrl'
}
}
});
It seems that $stateProvider may only work with the forward-slash(/) parameter delimiter. Is there another way to achieve this?
In the ui-router website has a simple example of you trying to do.
Maybe you can do the same thing, see the RouteProvider and StateProvider settings.
url: http://angular-ui.github.io/ui-router/sample/app/app.js
In the server side you can retrieve the url, so you can get your parameters.
[Edit]
About $locationProvider.html5Mode(true); you can do this and do the settings in route and state providers too, that don't interfere in functionality

Resources