AngularJS state machine extension ui-router declares a directive that converts routes with attribute ui-sref into href paths and populates it with requested variables. Is there a way to access the same route parser from a scope?
Update
I am looking for a hopefully built-in yet undocumented resolver (or a way to get the same outcome) that gives the path to a named argument. In the spirit of a named route:
<a ui-sref="management.person({personId: 1})" />
Which matches a route
$stateProvider.state('management', {
url: '/absolute/part'
});
$stateProvider.state('management.person', {
url: '/relative/part/:personId'
});
and outputs #/absolute/part/relative/part/1 - and in case I switch to use ! fragment, all the URLs are converted. Directive itself does this already, but its arguments cannot be constructed dynamically.
As of March 2015 I got 'UrlMatcher is not defined' for Chad Robinson's answer. But I succeeded by injecting $urlMatcherFactory and replace urlParams in a ui-router template url.
$urlMatcherFactory.compile("/about/:person").format({
person: "bob"
})
ui-router provides several services in an API that you can use to do things this. Try one of these examples:
From http://angular-ui.github.io/ui-router/site/#/api/ui.router.state.$state
var url = $state.href('about-person', {
person: "bob"
});
From http://angular-ui.github.io/ui-router/site/#/api/ui.router.router.$urlRouter
var url = $urlRouter.href(new UrlMatcher("/about/:person"), {
person: "bob"
});
These two patterns convert state names and URL templates into fully formatted URLs. There are additional API calls available as well.
Related
Example
http://localhost:4200/login?aUasas129198
resolves to
http://localhost:4200/login
What should I do if I want the value after '?'
I tried doing
{ path: 'login/:id', component: LoginComponent },
But it did not work
I also tried
console.log(this.route.snapshot.queryParams);
console.log(this.route.snapshot.params);
But they both return empty object. What should I do now please help
If it’s unavoidable that Angular redirects you immediately and loses the query parameters, you could subscribe to router events and on each NavigationStart for login route get a hold of route’s queryParamMap or snapshot.paramMap before they’re lost in redirection, then you can e.g. pass it to a service and do whatever you wanted to do with it.
Or, as another alternative, you could look into configuring your router with queryParamsHandling: 'preserve', in which case it should pass the query params to the next route (see the section in Angular docs linked below for more on this).
I worked with a project that made use of query params in Angular 5, IIRC I don’t think it would redirect on its own so I’d recommend to look elsewhere in your project but I may be wrong.
See also
Routing & Navigation → Query parameters and fragments in Angular docs
Angular Route Start and Route End Events on StackOverflow
Actually, You are not passing the value in any key:
http://localhost:4200/login?aUasas129198
The proper way should be:
http://localhost:4200/login?anykey=aUasas129198
// get it as
// this._ActivatedRoute.queryParams.subscribe()
If you are using the URI as you shown in your question as:
{ path: 'login/:id', component: LoginComponent }
Then you should pass the value to id as:
http://localhost:4200/login/aUasas129198
// remember the '/' after the login that you didn't use.
// get it as
// this._ActivatedRoute.snapshot.params.id
I'm using ui-router with Angular 1.6. The root state is the site language (/en, /nl, /de).
Most child states are the same for all languages. However, for some states the names of the child states are translated:
/en/english-state/common-state
/nl/dutch-state/common-state
/de/german-state/common-state
How can I make sure the middle state always matches the lang parameter (en/nl/de) in the parent state? I'd like to use ui-sref without providing the middle state; this should be filled automatically based on the language. When the middle state doesn't match the language in the parent state it should be changed automatically to match the language in the parent state.
I can't find an intuitive solution in the ui-router docs, but perhaps I'm missing something. Anyone done this before?
After a while, I've decided to solve it like this, which I think is the cleanest way to do it:
(Note: This is a simplified version. I've replaced functions with strings , omitted dependencies and removed lines, this is not-working code, it's about the idea).
Expose the language variable in the resolve part of the root state, something like this:
$stateProvider.state({
url: '/{lang:(?:en|nl|de)}',
name: 'root',
[ ... ]
resolve: {
language: function() { return $stateParams.lang }
}
In the child state, check if the URL matches the language:
$stateProvider.state({
url: '/{mySlug:(?:english-state|dutch-state|german-state|__my-state__)}',
name: 'root.child',
resolve: {
checkSlug: function () {
$timout(function() {
if (notMatchesLanguage($stateParams.mySlug, language)) {
var params = JSON.parse(JSON.stringify($stateParams));
params.mySlug = correctSlug;
$state.transitionTo($state.current.name, params, { notify: false });
}
}
}
}
Note the added slug in the mySlug list, __my-state_ _
Now in every ui-sref, or $state.go we can use __my-state_ as mySlug parameter. This strange slug won't match any language and will be replaced with the matching state slug.
I have the following state in Angular routing:
.state("supplier/document", {
url: "/supplier/document/:supplierid/:docid",
controller: "ctrlSupplierDocument",
templateUrl: "views/supplier/document.html"})
And I get to this state with the following code:
$state.go('supplier/document', { 'supplierid': $scope.supplierid, 'docid': item.QualificationID });
This results in me correctly going to the view in question, with a url formatted as expected:
http://localhost:60437/index.html#/supplier/document/14/70
I now need to grab the two ids from the url (14 being supplierid and 70 being the document id). BUT $state.params is undefined (obviously it doesn't see these as GET params). Normally, with one parameter $state.param.id works fine. Difference here is the two parameters.
Q. How do I grab these params? OR is there an alternative method to achieve this where I can use $state.params on the target view controller?
Thanks!
Try: $state.current.params.supplierid and $state.current.params.docid
See: http://angular-ui.github.io/ui-router/site/#/api/ui.router.state.$state
I'm using state-based routing (Angular UI Router v0.2.7) in a project and looking for a way to get the current state (name) from a given URL string.
Something like:
$state.get([urlString]) returns stateName:String or state:Object
I need this method to check if a state exists to a given URL because not all URLs are mapped to a state in my project. Using Play Framework as backend, some URLs (e.g., login form) are not mapped to a state because they using different templates then the Angular (main) part of my application.
For those "none-Angular" pages (i.e., not covered by a state) I would do a reload. To identify URLs not covered by a state I need the method mentioned above. Planned to do it like this:
$rootScope.$watch(function() { return $location.path(); }, function(newUrl, oldUrl) {
if(newUrl !== oldUrl) {
if (!$state.get(newUrl)) {
$window.location.assign(newValue);
}
}
}
Already checked the docu but there is no such method.
Any ideas?
It's all or nothing. If you plan to use ui-router make sure all your URLs resolve to a state. If the state doesn't exist it will go to the otherwise state. It's possible to have optional parameters.
An alternative is to use .htaccess redirects to catch the URL and redirect you before it hits the ui-router.
Provide more details and we can see what the best option is.
Try using this will get the current sate name.
var stateName = $state.current.name;
In Angularjs app, i have a url like http://url.com/my_app/#/store/items.
Now i want to append query string for example, http://url.com/my_app/#/store/items?page=2. but in url, javascript encodes the "?" to "%3F" which i don't want. It should remain "?" only in the url as angularjs $location.search() returns nothing for "%3F".
How it can be done ?
There is not enough details in your question so I will assume that you are using AngularJS routing - or at least the $location service - in non-HTML5 mode. If so, the part after the # character represents your URL from the single-page-application point of view (more about AngularJS here).
If the above assumptions are correct it means that you shouldn't try to add or manipulate the question mark "by hand". Instead you should change the search part of the $location to manipulate query string (part after ?) and the question mark will be added / removed to the final URL as needed.
In your case you could write:
$location.path('/store/items').search('page', 2)
This is assuming that you are manipulating URLs from JavaScript, as stated in your question.
If you are using the $location service then use $location.url('/store/items?page=2') instead. This has been a setter method from at least 1.0.7 and works a treat in my 1.1.5 app.
you can create a parameter object like:
var param = {
page: 2
}
$location.url("/store/items").search(param)
If you're using the ui-router which is highly recommended, you could use $state.go(to, params, options) as described here.
As prerequisite you need to define your state properly, that means every possible query parameter must be made known to the ui-router. See the following example (page and otherParam):
$stateProvider.
state('storeItems', {
url: '/store/items?page&otherParam',
templateUrl: '/modules/store/views/item.client.view.html'
});
And then you can just switch locations for instance from a controller by calling
$scope.gotoItemsPage = function(page) {
$state.go('storeItems', {
page: page,
otherParam: 'Just a show off'
});
};
No fiddling with the encoding needed and highly readable!
You can use decodeURIComponent.
For example:
decodeURIComponent('http://url.com/my_app/#/store/items%3Fpage=2');
// will give you `http://url.com/my_app/#/store/items?page=2`