-
Notifications
You must be signed in to change notification settings - Fork 3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
dynamic query params #84
Comments
Using an example from the Angular docs... // Given:
// URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby
// Route: /Chapter/:chapterId/Section/:sectionId
//
// Then
$routeParams ==> {chapterId:1, sectionId:2, search:'moby'}
// But if this URL were defined on a state...
$stateParams ==> {chapterId:1, sectionId:2} Of course we could adapt the route definition to the state.url of '/Chapter/:chapterId/Section/:sectionId?search', but again, we would literally have to predefine every possible query parameter. It's a little messy, and a bit more brittle. |
The problem is determining which parameter changes need to cause a state transition and which don't, especially when nested states are involved. Presumably you have some specific code to actually deal with every possible query parameter that you handle, so having to list them in one place doesn't seem that onerous. I would actually consider it to be less brittle than just passing through everything into $stateParam -- a bit like declaring function parameters. Apart from the fact that query parameters are treated as optional, there is no difference between path and query parameters as far as ui-state is concerned at this point, and I'm not sure there should be any fundamental difference. There have been multiple requests to support 'dynamic' parameters which can change without causing a state transition. It would be quite neat if those supported 2-way binding between their value in $stateParams and $location (I suppose parameter -> location would be performed with .replace() so that history entries are only generated when there is a state transition). Can you provide some more details around how you use/want to use those dynamic parameters, and how you currently update $location when they change? |
Perhaps only the parameters that are listed would trigger state transitions, while non-listed query params would get added to the stateParams for convenience, but not trigger state changes? Or, if the current implementation needs a 'clean' stateParams for transition management, a full list of query params could be attached separately, e.g. state.allSearchParams. Part of me thinks that sounds ugly, but another part feels like the query params are all getting parsed, so why not keep them all easily accessible. But it is workable as is - as a sort of white-list of query parameters. I just mentioned it because I noticed the difference versus routeParams (and one very long state.url on an advanced search form). |
With the stock router we can tell it not to reload on query parameter changes for certain routes, which is quite useful at times. Is that possible with the ui-router? |
@FAQinghere no, that's not supported yet, but support for that is planned. Would you be able to provide an example for how you use that feature, and how you detect changes in those query parameters? |
from Angular docs... [reloadOnSearch=true] - {boolean=} - reload route when only $location.search() changes. So we could just set the route's reloadOnSearch to false and then listen for the $routeUpdate event. Imagine two independent subviews, say a list view and a detail view. On the left we have tabs for two possible lists, say recent records, or search records. On the right we have the actual record. url: '/records/:tab/:recordId '/records/recent/23' -> nav to '/records/recent/24' => we want the left view to remain unchanged and the right view to change. We can do this with ui-router because of the hierarchical design. '/records/recent/23' -> '/records/search/23' => we want the right view to remain unchanged, but the left view to change tabs. We cannot do this now because the /:tab portion of the url is not independent of the :recordId portion, so the (same) record will get reloaded. If we could make the :tab a query parameter instead, and not automatically reload on query parameter changes, then we could make the :tab and :recordId completely independent, and the URL would still be able to correctly track state. 'records/23#tab='recent' or 'records/23?tabs='recent'&text='something', etc. We could do this with the stock router, but then a change to the :recordId would still reload the list view because there is no view hierarchy. We would have to also move the recordId into the query params. But if we did, and we set reloadOnSearch to false, we could make it work. |
Hm well controlling independent views is a step further than just not reloading on certain parameter changes. Is that your primary use-case for wanting reload=false for certain parameters? |
I think not auto-reloading on a per-parameter basis would be extremely powerful, allowing the URL to fully capture any state without the forced reloading of controllers where they are known not to need reloading. Presently this is only possible if it's the parent who does not need reloaded, and we achieve it by only modifying parameters of the child state. But short of that, I think the minimum would be to at least allow not reloading on changes to the query parameters, as that functionality is present in the stock router, and probably fairly commonly used (we get updated parameters and use AJAX to update a model in the current controller/context rather than completely re-instantiating the entire controller). |
Also, related indirectly with the original post, if all parameters were accessible via stateParams, it would be possible for a parent state to have access to all active state parameters, including its children's. Example: The both the parent and child states are active, but the parent doesn't have access to the :id parameter. It is, however, an 'active' parameter that could be very useful (though it could be null, obviously, if the parent is not abstract and we're at the parent url). For example, if we're on cars/23 with the routes 'cars' being a list, we could use access to the :id parameter to highlight car 23 within the list. |
There are some great features of ui-router that I am using but by taking this strong stance on query params your making the assumption that the ui-router is actually performing all control tasks for the application. This is creating a fundamental issue in assuming that all applications written using this framework will be client side driven. I have a case where we're working with a back end driven routing system using a templateProvider to resolve internals of each template and that provider needs to take all query string parameters into account (even the ones that the developer of the provider had no knowledge of). So basically what I'm saying is that when you look a more enterprise content system where the routing is server side this causes quite the problem as the only developer that knows this new routing is detached from the angular ui-router code as they are working in the back end routing system. This application developer will define their routing structure in that backend and the client side (ui-router) just needs to use it.
So @ksperling what your assuming here, while correct that the application developer ultimately knows about all query parameters, as the platform developer I do not, so I need a way to pass this information to them but you've hidden it from me. Again I do understand your position and having that interaction as the default is all well and good but I believe I won't be alone in needing a way to get at these parameters for some reason so having an option to get these is a must. Now obviously I can do this with window.location.href but it would be nice if this information could be used to trigger the provider on any change (again just an option) so that these routes being defined by the application developers will properly trigger updates. Thanks so much for all your hard work on this router, between angularjs in general and this router I believe these communities have created the future of web, moving us from static committee created grammars (html, svg, etc.) into a world where developers can create the grammars and handlers they need to drive the web forward. |
@xmltechgeek I guess in your case passing them all through makes sense (apart from corner cases like name collisions between a path parameter and a query parameter)... so do you simply want to have the option for ui-router to consider any query parameter to apply to the state, e.g. via some syntax like '/foo/bar?*', so that a change in any query parameter would cause a state transition? Or are you wanting them to appear in $stateParams, but not cause a transition? I guess the most flexible solution would be to support both. |
@ksperling That first option with the wild card would be awesome and I agree supporting both would be the most flexible as long as it could be done without too much new syntax. If you don't have time for this I'll see if I can get too it in the next week. If I do get to this would it be preferred for me to create a new pull request for it or attach it to this issue? Thanks for the quick response. |
I agree. Accessing search parameters would be excellent |
I'm working through this now on my fork (in an issue-84 branch) we'll see how far I get in the next couple days. I've figured out how to parse out the proper parts of searchParams however I'm having trouble with figuring out the best place to update the transition. So far I've tried just getting the toParams to reflect the optional params by updating the urlMatcherFactory. This seems to work for the params by the locals check fails so I doesn't get to a transition. I could hack around this but I'm wondering if you (@ksperling) have a suggestion for a more concise way. Note at this point in my code params contains the asterisk as one of the parameters while toParams is the resolved form of this. |
Are default query parameter values supported? I can't seem to find anything about it, but didn't want to open a new thread. |
No they aren't. |
@Broeks There's an existing issue. It's in-progress. |
Dupe |
Could we have the stateParams show all query params actually in the url, rather than only those that are predefined on the state's url property?
I believe that Angular's routeParams does show all actual query parameters.
If we have an advanced search filter it can get rather messy listing every possible parameter in the url, especially since they are not actually used for matching (missing parameters does not prevent the state match, which is a good thing).
The text was updated successfully, but these errors were encountered: