Frontend views

Asynchronous Search with JSON and AJAX

Wagtail provides JSON search results when queries are made to the wagtailsearch_suggest view. To take advantage of it, we need a way to make that URL available to a static script. Instead of hard-coding it, let’s set a global variable in our base.html:

<script>
  var wagtailJSONSearchURL = "{% url 'wagtailsearch_suggest' %}";
</script>

Now add a simple interface for the search with a <input> element to gather search terms and a <div> to display the results:

<div>
  <h3>Search</h3>
  <input id="json-search" type="text">
  <div id="json-results"></div>
</div>

Finally, we’ll use JQuery to make the asynchronous requests and handle the interactivity:

$(function() {

  // cache the elements
  var searchBox = $('#json-search'),
    resultsBox = $('#json-results');
  // when there's something in the input box, make the query
  searchBox.on('input', function() {
    if( searchBox.val() == ''){
  resultsBox.html('');
  return;
    }
    // make the request to the Wagtail JSON search view
    $.ajax({
  url: wagtailJSONSearchURL + "?q=" +  searchBox.val(),
  dataType: "json"
    })
    .done(function(data) {
  console.log(data);
  if( data == undefined ){
    resultsBox.html('');
    return;
  }
  // we're in business!  let's format the results
  var htmlOutput = '';
  data.forEach(function(element, index, array){
    htmlOutput += '<p><a href="' + element.url + '">' + element.title + '</a></p>';
  });
  // and display them
  resultsBox.html(htmlOutput);
    })
    .error(function(data){
  console.log(data);
    });
  });

});

Results are returned as a JSON object with this structure:

{
  [
    {
  title: "Lumpy Space Princess",
  url: "/oh-my-glob/"
    },
    {
  title: "Lumpy Space",
  url: "/no-smooth-posers/"
    },
    ...
  ]
}

What if you wanted access to the rest of the results context or didn’t feel like using JSON? Wagtail also provides a generalized AJAX interface where you can use your own template to serve results asynchronously.

The AJAX interface uses the same view as the normal HTML search, wagtailsearch_search, but will serve different results if Django classifies the request as AJAX (request.is_ajax()). Another entry in your project settings will let you override the template used to serve this response:

WAGTAILSEARCH_RESULTS_TEMPLATE_AJAX = 'myapp/includes/search_listing.html'

In this template, you’ll have access to the same context variables provided to the HTML template. You could provide a template in JSON format with extra properties, such as query.hits and editor’s picks, or render an HTML snippet that can go directly into your results <div>. If you need more flexibility, such as multiple formats/templates based on differing requests, you can set up a custom search view.

Custom Search Views

This functionality is still under active development to provide a streamlined interface, but take a look at wagtail/wagtail/wagtailsearch/views/frontend.py if you are interested in coding custom search views.