Instantsearch.js: Let the user choose if they want to do the initial empty query

Created on 22 Jul 2015  路  24Comments  路  Source: algolia/instantsearch.js

Use case : page rendered from server with results that don't need to be updated

Needs Investigation

Most helpful comment

Ok,

So you can use:

var search = instantsearch({
  searchFunction(helper) {
    if (helper.state.query === '') {
      return;
    }

    helper.search();
  }
})

Let me know how it goes

All 24 comments

API discussion in #185

Hi, I think this should be reopened.

I have the use case specifically mentioned in the description:

page rendered from server with results that don't need to be updated

This use case is not covered by #182 and #185 in my opinion. Let me tell you a bit more about what I'm trying to achieve.

I have a backend search which uses Algolia through the backend and renders the results. This would also work for search engines and other crawlers. So when you visit http://example.com/search?q=term you would already have results on the page. I want to implement Algolia instant search on top of that. So if the user starts typing in the search box, the results would change immediately client-side without using the back-end search on ther server. The search box widget is playing nicely with the support to target an input directly. The hits widget though would trigger a search and replace the previous results if its container is the one filled with the back-end results.

Is there any other way to achieve this and tell Algolia instant search to not replace the results until another search query is entered? If not, I think this could be reopened.

Awesome feedback @hkdobrev I am reopening and we will need to solve it with a new API entry.

We have https://github.com/algolia/instantsearch.js/issues/776#issuecomment-172900988 do you think it would help? I guess you could use this query hook to check a flag you have in the page to not trigger the search?

This is doable now using searchFunction option of instantsearch({})

@vvo how exactly can I avoid empty search calls? Example would be helpful.

Do you still want the initial query to be triggered (we do an empty initial query) or do you just want to avoid any empty query being done, wether its the initial one or when a user removes the query.

(can you create a new issue to discuss that? thanks)

I want the initial query to be triggered (if there was one, for example from an previous search) but when the page loads for the very first time and there is no historic search available, I don't want the search to start at all.

Ok,

So you can use:

var search = instantsearch({
  searchFunction(helper) {
    if (helper.state.query === '') {
      return;
    }

    helper.search();
  }
})

Let me know how it goes

Yes, this blocks empty searches. But when the user deletes everything in the form input searchBox the search hit list stays with the result of the the last character that was deleted!

I want an empty hit list on init and also when deleting the search term in the searchBox. No initial "*" search should be triggered.

To do so, you can combine this with:

// on init, show what you want instead of the hits widgets, for example "hello world"

var search = instantsearch({
  searchFunction(helper) {
    if (helper.state.query === '') {
      return;
    }

    helper.search();
  }
});

search.addWidget(
  instantsearch.widgets.searchbox({
    queryHook: function(helper) {
      if (helper.query === '') showHitsReplacement(); // same, show "hello world" instead of hits, no more query
    }
  })
)

Since you are also using debounce, you would need to:

// on init, show what you want instead of the hits widgets, for example "hello world"

var search = instantsearch({
  searchFunction(helper) {
    if (helper.state.query === '') {
      return;
    }

    helper.search();
  }
});

search.addWidget(
  instantsearch.widgets.searchbox({
    queryHook: function(query, search) {
      if (helper.query === '') return showHitsReplacement(); // same, show "hello world" instead of hits, no more query

      debouncedSearch(query, search);
    }
  })
)

var debouncedSearch = debounce(function(query, search) {
  search(query);
});

Let me know how it goes :)

Ok, is it possible to trigger the widgets.hits() -> template: empty: ... section instead of the showHitsReplacement() To stay inside instantsearch and not adding another function like showHitsReplacement()? Maybe via transformData?

What I don't understand in your comment here: https://github.com/algolia/instantsearch.js/issues/4#issuecomment-199321325 Why can it happen that searchFunction AND queryHook be hit with an emtpy query?

I understood queryHook as a "on keyup" hook and searchFunction as an general hook to jump into right before a search query would be fired against the API. So why could it happen that both functions face this "empty search" situation? Is it because queryHook is not triggered on page load?

Adding another picture to help to understand what I expect: a behavior similar to the google search. When I open it, it does not show me 1.000.000 search results until I start typing and the number gets reduced. Also when I fully delete my search term the google search result section is empty again...

Yes queryhook is not triggered on the initial empty query, only when the user types, because its on the searchbox widget, is this an issue?

This was solved with the searchFunction option of instantsearch constructor

@vvo how exactly?

The original issue "Let the user choose if he wants to do the initial empty query" can be solved using searchFunction. If there are more needs API wise, can you open a new issue?

@vvo could you explain exactly what you are doing when using showHitsReplacement();?

I'm trying to get a query back to a blank slate if the user deleting the search term in the searchBox like @powtac mentioned.

I assume this involves creating something that will clear the hits, pagination and stats currently.

Hi @Giovanni-Mattucci can you open a question on https://discourse.algolia.com/? This issue is very old and I am not sure to get the full question here.

I achieved it with

searchFunction: function (helper) {
    if (helper.state.query === '') {
        document.querySelector('#hits').innerHTML = '';
        return;
    }

    helper.search();
}

Is there still no "official" way to deal with this obviously essential feature? I was looking for hours through the docs and it seems like it doesn't exist. Almost unreal. In most cases people only want to search when there is an actual query! Why is there no setting for this in the configuration?

I don't understand any of the above solutions right now. Also @alcalyn suggestion doesn't make sense to me right away and it looks like I need to understand the underlying code of instantsearch for this, which is even more difficult as I'm using vuejs (the vuejs version of instantsearch).

@elasticsteve I'm using the javascript version of instant search. Here is the full code if it may help to understand how I prevent search query when search field is empty (i.e when pressing backspace):

https://github.com/eole-io/sandstone-doc/blob/7d1f4f2b71b0d09d9de77b09e3df314102a88a99/js/main.js#L34-L41

and here is the result: https://eole-io.github.io/sandstone-doc/get-started (search is at top right)

Something to note: doing the initial query, even if it鈥檚 not visible will warm up the connection (dns, ssl), so that actual queries done by the user will be faster.

Algolia costs money and doing queries for no reason might not be what you want, especially if you have lots of users on the platform. I'd rather make a query when the users wants to know something and not before. That's why the solution to hide results if the query is empty is not welcome.

I'm still surprised that such a sophistacted package like instantsearch doesn't include this out of the box.

Was this page helpful?
0 / 5 - 0 ratings