emberjs / ember.js

Ember.js - A JavaScript framework for creating ambitious web applications
https://emberjs.com
MIT License
22.48k stars 4.21k forks source link

Add Query-String Support to the Router #1773

Closed wycats closed 11 years ago

ElteHupkes commented 11 years ago

@machty Indeed there's no reason we couldn't have that. Only determining which handlers need to be updated is not straightforward. Also it can't be done as a hack, you really need to modify some of the functions closed over by the router module (or copy a whole bunch of code). I suppose this is what has kept most people from implementing it, because I guess we're all working on getting our webapps to just work ;).

I agree the per-route querystrings make more sense conceptually, so I hope you guys have time to take a look at my implementation. Still needs some polishing, but the essential parts are there at least.

ElteHupkes commented 11 years ago

About the recognizer btw: it uses a state machine, where every state consists of a set of "validChars" or "invalidChars" and a "repeats" flag (which is used in dynamic segments / star routes). A static segment ("/posts") is represented by a state for each of the characters in its path with a validChar equal to its letter (p, o, s, t, s; ), where the final character is an accepting state with a handler. A dynamic- / star segment has one invalidChar ("/") and repeats (and is also accepting).

While it's technically possible to implement query strings into this state machine, it is currently generated as a tree; so adding optional states behind every handler would make the tree exponentially larger in the number of handlers. Apart from that it would also be difficult to implement. Actually I'd say this system is a sort of regex-engine; but then why not use the one that Javascript ships with ;).

The way I "solved" this problem is by replacing the single-character states with states that consist of a regular expression, so there's a state for every "/" separated portion of a path. This allows adding an optional query string to some of them. That being said it is still quite complicated; and I personally think it would not be a horrible idea to change it altogether.

igorbernstein commented 11 years ago

Can we have the cake & eat it too? Matrix params for route local context & query style for global context?

/posts/5/comments?author=alexspeller # author param affects all routes /posts;author=alexspeller/5/comments # affects only posts route /posts/5/comments;author=igor # affects only comments route /posts;author=alexspeller/5/comments;author=igor # split /posts;author=alexspeller/5/comments;author=igor?sort=oldestFirst # split w. global

machty commented 11 years ago

@igorbernstein Too much cake.

I can't really think of a compelling use case for this that couldn't be handled by a leafier route looking up information on the parent route that was passed a per-route query string. It shouldn't be ambiguous which route will be using the author= information. Forcing per-route query strings would remove that ambiguity.

edit: :cake: :cake: :cake:

ElteHupkes commented 11 years ago

Hmm also not sure it's desirable. I can probably think of a use case for it, but then you'd have to explain to everyone why there's two types of query strings, which takes preference and when and how they're updated.. We'd spend all day in the kitchen only to see our guests stare in doubt at our cake, which is an octahedron with whipped cream on all sides.

machty commented 11 years ago

Cake Wreck

Nthalk commented 11 years ago

I've got a decent workaround by create an outer controller that has no view or templates:

/todos/p/key:value,key:value
Application => Todos => TodosParams

It works with the controller context stack and reaching up in the stack to pull arguments from a params controller that sits below the desired controller's route.

When you need parameters, you need the params controller, and set a paramsBinding: "controllers.params"

A rough example how to do it manually is here: https://gist.github.com/Nthalk/5407240

A more involved helper function exists here: https://gist.github.com/Nthalk/5409344

Edit: This method doesn't work well, see my below comment for my revised strategy

alpacaaa commented 11 years ago

@Nthalk thanks for sharing, simple and useful!

toranb commented 11 years ago

Agreed! @Nthalk could you post a full jsfiddle with a sample app using this? I'm trying to use a model route and found that having "params" be a string that represents multiple model properties a bit awkward so I'm sure I'm just doing it wrong :)

Nthalk commented 11 years ago

Okay, after diving into that for a while, I realized my above solution didn't work that well, and there was a different, more usable way of dealing with it:

http://jsfiddle.net/fdkPY/7/ NOTE: jsfiddle isn't showing the underlying routes in the address bar. They're being hidden in some iframe, but they do reflect dynamic parameters.

The one major caveat of this method is that it crowds the url space. Whereas you once had:

todos              # todos.index
todos/:todo_id # todos.show

...You cannot use that uri space because it is taken by :params, so you must instead use something like...

todos/list/:params # todos.index
todos/:todo_id      # todos.show

...so you don't collide with the resource routes. It's a small price to pay, but you can see from the jsfiddle that this method does indeed work and allows extensions into the show routes:

todos/:todo_id/:params      # todos.show withParams

In my projects lib, I'm planning on adding a WithParams mixin that does the generic parameters lifting.

Additionally, there can be an observer that listens to changes on the params and updates the current URI via transitionToRoute, but that's best left to the developer to decide if calling transitionToRoute on an observer is sane.

jayphelps commented 11 years ago

This is super required for me to keep state within the url. Example: /session?tool=draw&theme=something&redirect_uri=something

Anyone taking a crack at this yet for a pull request?

alexspeller commented 11 years ago

@jayphelps have you tried my library?

jayphelps commented 11 years ago

@alexspeller I have indeed, but I require history and hash support both (I'm currently using my PR #2685 for AutoLocation). I'd be down adding that support to your library, but if this is indeed something the core team wants in the mainline I'm hoping we can get a PR rolling.

alexspeller commented 11 years ago

Ah ok. Well the problem is that my implementation is the most complete, however it's unlikely to be the officially adopted one. I haven't worked on matrix params at all, and am unlikely to in the very near future, although I'd be willing to at some point when I have more time.

ElteHupkes commented 11 years ago

Guys! I've been working on another query parameter workaround lately, and this one I'm pretty excited about. It can be found here: https://github.com/ElteHupkes/ember-query-params . Quick summary: global query string (not my preference, but less impossible to implement), works with linkTo / URL generation, Location independent, minor route configuration. For me personally this is the best solution thusfar - let me know what you think!

coderberry commented 11 years ago

@ElteHupkes great contribution. Do you have an example app which demonstrates it's usage and benefits?

ElteHupkes commented 11 years ago

@cavneb I've cooked something up real quick: http://liveweave.com/QLJ0f1 . Unfortunately these JSFiddle type-things don't show the URL-bar, which really is kind of the point when showing query parameters ^^. You can copy-paste that LiveWeave's code into a HTML-document and it should work though.

Any questions, please let me know :)!

coderberry commented 11 years ago

@ElteHupkes it worked great. Here's an example app: https://github.com/cavneb/ember-query-params_example

ElteHupkes commented 11 years ago

@cavneb Nice! I added a link in the README.

alexspeller commented 11 years ago

@ElteHupkes I've been a bit busy to update my libary for RC6 at the moment, but it seems our libraries are very similar, in fact when I do update my library I will probably be looking at yours and basing it mainly from your work as it does most of what I need. However I think there are one or two things my library does that yours doesn't (binding params to controller properties is the first one I can think of), and one thing I'm not too keen on with your library (I don't like the QueryParameters and don't think it's necessary).

In any case, I'd like to ask if you'd be willing to work together on this problem and find a way to combine our efforts?

ElteHupkes commented 11 years ago

@alexspeller Definitely! I'll probably be too busy the upcoming weeks for any serious meddling with the query params (ok part of that will be a vacation, so maybe "unavailable" is a better term ;]), but I think it's a very good idea to put our heads together and start thinking about how we can combine our efforts and make things better for everyone.

alexspeller commented 11 years ago

Great! I will start working on some stuff, and I'll file some pull requests to your repo and put a note on my library to look there for RC6 support. Enjoy your holiday, and let's talk when you get back.

coderberry commented 11 years ago

@ElteHupkes @alexspeller God bless both of you for working together to solve this. I wanted to try ember-query but it's not RC6 ready yet.. I already have an app that's near production using ember-query-params, which I really like.. I will integrate your combined efforts as they become available. Thanks again!

dustMason commented 11 years ago

Thanks for taking this on @alexspeller and @ElteHupkes! I just grabbed ElteHupkes/ember-query-params and added it to a project I'm working on to give it a spin and wanted to chime in to agree with one of @alexspeller 's recent comments:

I find the QueryParameters object a little unwieldy, especially regarding the linkTo helper. I'd like to be able to specify my query params right in the template much like I do in my rails apps. I'm not experienced enough with Ember to know how/if this would be possible, but it would feel most natural to me.

machty commented 11 years ago

Hi all,

This GH thread is becoming a Tolstoy novel, and I'd like to get some outside thoughts in since I doubt there's all that many people following this thread beyond some of the main contributors. So, if you will, please check out the following Discourse thread and summarize the various approaches you've taken, lessons learned, implementation status, etc., and see if we can't nail the best way to go going forward:

http://discuss.emberjs.com/t/query-string-support-in-ember-router/1962

alexspeller commented 11 years ago

I just pushed support for ember master here

MiladQamari commented 11 years ago

hi alex

ember-query doesn't work in IE 9 , I added new issue with error message

alexspeller commented 11 years ago

Hi all, there is now a PR for this, please see #3182

wagenet commented 11 years ago

Closing in favor of discussion on the PR.