Debouncing query-params-new


#1

We’re attempting to debounce query parameters to implement a paginated live search using query-params-new. We’re using the refreshModel: true flag to indicate that we want to go back to the server when the param changes.

Here is a fiddle demonstrating that: emberjs.jsbin.com/qopacixi/1/edit

You’ll notice that it refreshes the model whenever the search param changes, as desired.

However, at some point you may want to debounce the model refresh from triggering to allow the user to type a more meaningful search before firing it off to your server.

Here is a fiddle demonstrating this: emberjs.jsbin.com/qejiloyu/2/edit

In order to get this to work we had to define a query parameter proxy that the template binds to, observe when it changes, and transition after a debounce. Is there an easier way to achieve this effect? If not, could there be another option to the route’s query params configuration (perhaps debounce: 1000)? Or maybe a queryParamsWillChange action (a la queryParamsDidChange)?

And finally, when someone inputs a new search query, after we debounce we want to reset the page to 1.

Here is a fiddle where we do that: emberjs.jsbin.com/nitarezi/2/edit

Notice that we set the page back to 1 in the transitionToRoute - it would be nice if the aforementioned “hook” provided a place to mutate the query parameters before their changes are applied.

Anyone else doing things like this? Please share your experience.


#2

I think the way that you’re handling it is about how I’ve handled this scenario in the past.

Only difference is that I’ve set the property in the controller directly rather than triggering a transition manually.

You have:

searchObserver: function() {
  Ember.run.debounce(function() {
    that.transitionToRoute({queryParams: { search: that.get('searchProxy') }});
    }, 1000);
  }.observes('searchProxy')

Where I might have done this instead (essentially the same):

Ember.run.debounce(function() {
  that.set('search', that.get('searchProxy'));
},1000);

That being said, I think the question you’re really asking is about wether the Ember.run.debouce is best handled by observing, then calling the debounce, etc. Perhaps this needs to be its own issue, but I wonder if there’s some room for improvements with Observers so that they can easily hook into Ember.run.

But, what if your debouce code looked something like this instead:

searchObserver: function() {
  this.set('search', this.get('searchProxy'));
}.observes('searchProxy').run('debouce', 1000)

This would also help when we want to observe multiple properties, but we only want the observer to run once:

Old way:

_execute: function() {
  // Do Something
},
executeObserver: function() {
  Em.run.once(this, '_execute');
}.observes('prop1', 'prop2')

New way?

executeObserver: function() {
  // Do something
}.observes('prop1', 'prop2').run('once')

#3

Doing it that way (http://emberjs.jsbin.com/yicus/1/edit)

You’d need to setProperties({search: that.get(“searchProxy”), page: 1}) - otherwise you won’t reset the page. Also, will that update the url correctly? Hard to tell from the jsbin. The .run looks nice.


#4

That will indeed update the URL correctly.