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;
Related
I want to extend my application with a URL parameter functionality:
If a filter is activated, the URL needs to be updated
If someone goes directly to the URL you should get the same data as you filtered manually
I see different ways in this world:
The parameter story based on: domain.com/?status=pending&relation=1
Clearer/neat way: domain.com/filter/status:pending/relation:1
I'm more looking for the last example. How can I do this within Vue? I am currently working as an example within Router with props: route => ({ query: route.query }).
Can someone help me and maybe others on my way to realize this?
It dependes....maybe is better to create an api that refresh your table...
In this way you pass the parameter to the api that will get you the book array, and in this way you refresh your content...
In this way you will have a url like:
domain.net/page?f=1p=filterparamete
Or you can use vue dynamic routing
/page/:filter/:filter_value
But in this case you shold have a fixed url structure in case of multiple filter setting..
In any case the first way is the most easy and scalable way...
You can use the query-string lib to parse URL parameters and then just filter items by params
const queryString = require('query-string');
console.log(location.search); // '?status=pending'
const parsedParams = queryString.parse(location.search);
console.log(parsedParams) // { status: 'pending' };
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 have an app that has a bunch of dropdown components that alter state. . The state of the dropdowns control a main datatable that has info based around the params. Cool.
I want to also alter the URL so users can share urls with their coworkers and simply have the datatable show up without choosing dropdown parameters.
Example: http://localhost:8080/?region=372&pc=341&pc=375 or http://localhost:8080/?region=372&pc=341&vendor=123456
Right now I've got this working by manually watching the dropdown parameters selected (via watch) and building a url and using this.$router.push to update browser history when things change. I have a feeling this isn't totally correct, but it's the only reliable way I've been able to make the url update consistently.
The main issue is that when I hit the browser's back/forward buttons, the components do not update their state based on the url. The application remains in it's current state if I hit back/forward. How do I properly go about this?
It looks like you're effectively trying to bind the state of your dropdown to your URL query. VueRouter, unfortunately, doesn't have a baked-in solution for this.
I'm not sure how your data is structured, so let's assume you have an object dropdownParams containing the relevant parameters:
dropdownParams: {
region: 372,
pc: 341,
vendor: 123456,
}
You need to set a watcher on dropdownParams to update the query in the $route when those are updated. Use $router.replace instead of $router.push so that the history doesn't change:
watch: {
dropdownParams(params) {
// format the data however you want this is an example with lodash
let query = _.pickBy(params, p => !_.isEmpty(p));
this.$router.replace({ query: query });
}
}
Then, in the mounted hook, you can set the dropdownParams object based on any relevant $route.query parameters, if they already exist:
mounted() {
let keys = _.keys(this.dropdownParams);
_.assign(this.dropdownParams, _.pick(this.$route.query, keys));
}
Now, when the user changes the dropdown parameters, those changes will be reflected in the URL. And, if the user loads the component with URL query parameters already present, the component will set those values to the dropdown.
I have ui-router set up as follows
.state('root.event', {
url : '/event/:id',
templateUrl : 'templates/event.html'
})
(the controller is initiated in the template)
which gives nice looking Basic URL Parameters like:
www.mysite.com/event/1234
When a user navigates directly to my www.mysite.com/event path (ie param is missing) the template controller looks the most recent id parameter from either:
- a js variable stored in a value
- localstorage / cookie etc
I then return this to my state using $location.search('id', 1234)
...however, this results in URLs which have Query URL Parameters like:
www.mysite.com/event/?id=1234
Is there a technique to ensure that $stateparams updates present the url in basic format on update ?
...or is it possible to get the URL parameter & update the $state before the state change ?
(I looked at Resolve but this seems mostly to be about passing parameters to controllers)
I've had a look here, here and here - but most of the questions relate to how to avoid reload on update of $state params
$location.search does exactly that. It adds query URL parameter. I think what you're looking for is
$state.go('root.event', {id: 1234})
I am looking for simple solution with Angular how to handle routes.
I have page generated by server with simple google map and little logic which is in 3 separated controllers.
Now i want to hook routing inside of this. Just simple routing. When I move with map and get new coordinas i want to push them into current url as param "?position=10.11,50.23". I want to use history push state with hashbang backup.
In other part of application i want to listen on change of this parameter (some $watch maybe?). And i want to use same code for detecting change to be used when page is loaded first.
I used CanJS in previous project, where this was absolutely simple, but in Angular i cant event make baby step to correct result :)
PS: this is just cut of minimal usecase.
Thanks
You do not really need angular routing to do that. Routing in angular is usually used to replace ng-view with different templates though it can be used for other things as well.
Your requirements can be met by using the $location service and setting up a $watch:
$scope.$watch(function () { return $location.search().position; }, function (newVal) {
$scope.params = newVal || 'No params';
});
$scope.setParams = function (val) {
$location.search('position', val);
};
Working demo
Launch the live-preview in a separate window to see the parameters change in the window address bar.
Update: The Demo doesn't work on plnkr.co anymore. Possibly because they have changed how they use the embedded mode.
Do not know CanJS, but in angular it is pretty easy as well.
First use: $location.search({parameter1:'someValue', parameter2: 'someOtherValue'}) to set you url -- the history will be updated automatically.
Then the most elegant way to detect any changes in url is to use (one of) two built-in events:
$locationChangeStart and $locationChangeSuccess, like that:
$scope.$on("$locationChangeStart", function (event, next, current) {
// your staff goes here
});
$scope.$on("$locationChangeSuccess", function (event, next, current) {
// or here (or both if needed)
});
To get the search parameters just use $location.search() in one of the above methods.