Instant Search with Solr and AngularJS

vectors are fun

Previously, we gave an example of a super simple search results widget that utilized jsonp and AngularJS. Since then, we’ve polished our Angular skills quite a bit. Enough so, that I was able to throw together this instant search widget, in less than an hour. Angular truly is an amazing UI tool.

Below is the source for the widget (and here it is on github and jsfiddle). Like our previous example, we use Angular directives to create a custom HTML element. Unlike our previous example, we’ve allowed some interactivity with a simple input tag. Enjoy!

'use strict';

angular.module('solrAngularDemoApp')
  .directive('searchResults', function () {
    return {
      scope: {
        solrUrl: '=',
        displayField: '=',
        query: '&',
        results: '&'
      },
      restrict: 'E',
      controller: function($scope, $http) {
        console.log('Searching for ' + $scope.query + ' at ' + $scope.solrUrl);
        $scope.$watch('query', function() {
          $http(
            {method: 'JSONP',
             url: $scope.solrUrl,
             params:{'json.wrf': 'JSON_CALLBACK',
                    'q': $scope.query,
                    'fl': $scope.displayField}
            })
            .success(function(data) {
              var docs = data.response.docs;
              console.log('search success!');
              $scope.results.docs = docs;

            }).error(function() {
              console.log('Search failed!');
            });
        });
      },
      template: '<input ng-model="query" name="Search"></input>' +
                '<h2>Search Results for {{query}}</h2>' +
                '<span ng-repeat="doc in results.docs">' +
                '  <p>{{doc[displayField]}}</p>'  +
                '</span>'
    };
  });

Notice how we added the $scope.$watch call in our controller. This directly binds some behavior to occur when a value in the $scope changes. Angular is well known for rerendering the page when $scope changes. What’s even more powerful is that Angular’s $watch lets you perform arbitrary behavior when a value in $scope changes. In our case, we’re reexecuting the search when the query member changes. The variable query is bound to the input tag, so nothing special is needed to invoke this code other than the user typing into the widget. Pretty snazzy!

Here’s how the widget is used:

<search-results 
    solr-url="'http://ec2-75-101-214-153.compute-1.amazonaws.com:8983/solr/statedecoded/search'"
    query="'car tax'"
    display-field="'catch_line'">
</search-results>

We continue to enjoy working in Angular. Like any other framework, it requires a bit of reworking your mind into how it thinks, but once you get there, the productivity gains are pretty enormous. In many ways the tight binding of user behavior and display reminds me of my favorite desktop UI framework, QT that I used to blog about here. Very analogous to Angular’s philosophy of two-way bindings, QT uses signals/slots to tightly integrate input, display, and behavior. Once figured out, the tight binding of these things can be enormously productive in either the web or the desktop environment.

Of course, we’d love to hear about your search UI needs! You too can take advantage of our expertise creating beautiful search and discovery interfaces (like say this one!)

Programming, solr

post-type:post

5 comments on “Instant Search with Solr and AngularJS

  1. Sweet! I need to get used to the fact that it’s okay in the modern JS world to have a single executable line of code that takes 36 lines to display!

  2. Pingback: AngularJS Highlights: Best of 2013 | SyntaxSpectrum

Leave a Reply

Your email address will not be published. Required fields are marked *

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>