I would like to add a dynamic search form functionality to my ember app. What is best practice?
It seems to me that using request parameters is not a recommended approach, but then how?
I would imagine I could do something like the following in my routes?
posts/search/:search_term
But what if the search is made up of a collection of drop-down selections or similar input controls (like a form) or not just a text search? For such a search, one or more of these search filters may be active for a given search operation. LEt’s say I have 1-3 search filters. Would this be the way to go?
posts/search/:search1/:search2/:search3
Or if I have only 2 filters active?
posts/search/:search1/:search2
I assume that the first matching route is executed, so I could do:
But this still seems like repitition and anti-pattern.
Would I simply have a posts/search route and then manually extract the request params from the request in my router (handler)? Does this even work with the /#/ hash routing?
Thank you for bringing this up – it only just dawned on me that I haven’t seen any mention of this in Ember docs (for the router) or the little I’ve seen of the extant data adapters (for the service calls). Hmm. Kind of a big gap in support for restful pages and services.
Yeah, that is the “naïve” approach that we would use in a traditional Model2 MVC app, such as Rails or Spring, but… not sure how it would work with Ember, since it uses the “anchor” part of the url (after the # to resolve a path). I guess I can use window.location.hash, but I wonder if the Router simply discards whatever part of the URL remains after it has matched a route? I can find no mention of how to access the url params, only the “params” which as I understand it only refer to the dynamic part of a Route path.
/#/posts/search/:search
So a query of the form “Copenhagen 2 km radius” could be decoded to form a valid Ember route:
var options = decodeURIComponent(window.location.search.slice(1))
.split('&')
.reduce(function _reduce (/*Object*/ a, /*String*/ b) {
b = b.split('=');
a[b[0]] = b[1];
return a;
}, {});
JS reduce can be used just fine with modernizer.js.
However, it looks like Ember normalizes the url into the form /x/y/z and discards anything after ?
Otherwise #/posts/1?a=7 would result in a lookup posts: {post_id: ‘1?a=7’}. It doesn’t look like the discarded options and made accessible from within the route or router. Not sure if this is intentional by design or if it’s a good or bad thing. It looks to me that going the URL options route is a “no go” at this point. Perhaps in the future, the ApplicationRoute could me made to extract the options before normalizing the URL path?
Yeah, I remember I saw kind of the same question on stackoverflow. The solution that I read there, was to put the query string before the #, so you can access it later.
This is an incredibly helpful forum post, thank you all for bringing up the discussion!
I’m new to Ember, and am still struggling with routing…I’m trying to do something similar to this:
App.Router.map(function() {
this.route('search', {path: '/search/*query'});
this.route('incidents', {path: '/incidents/*query'});
});
App.SearchRoute = Ember.Route.extend({
model: function(params) {
// using jquery-bbq-deparam
return $.deparam((params && params.query) || '');
},
setupController: function(controller, model) {
controller.set('model', model);
}
});
App.IncidentsRoute = Ember.Route.extend({
model: function(params) {
var filter = $.deparam(params.query);
return Ember.RSVP.Promise(function(resolve, reject) {
// use filter object to construct AJAX request...model comes from REST service
});
},
setupController: function(controller, model) {
controller.set('model', model);
}
});
Here are my questions:
Is there some way I can update the url just before the transition from #/search to #/incidents/fromDate=yyyy-mm-dd;toDate=yyyy-mm-dd so when the user hits the back button, the search form can be restored to its last state?
Should I not be using a model in my search controller to store current form values? I know it’s “application state” and not “persisted state,” but I want the user to be able to modify their query without starting from scratch…so, doesn’t this have to be held in the URL?