Creating a Solr <search> HTML element with AngularJS!

Note: The following post is fantastic… but this one is about the same topic and is even better.

Of late we’ve been playing around with EmberJS for putting together slick client-side apps. But one thing that bothers me is how heavy-weight it feels. Another thing that concerns me is that AngularJS is really getting a lot of good attention and I want to make sure I’m not missing the boat! Here, look, just check out the emberjs/angularjs Google Trends plot:

Screen Shot 2013-08-11 at 5.55.23 PM

So since all my major life decisions are dictated by Google Trends plots, I took a little time this weekend to familiarize myself with AngularJS. And frankly, I’m impressed!

When building a JavaScript framework, the framework designer has to strike a delicate balance between power and heft (that is, how intrusive and heavy-weight the framework is). Usually the more powerful the framework is, the more invested you have to be in the framework: the more the difficult it is to learn, and the more you simply have to accept its opinions a being the right way to go (even if you secretly disagree). AngularJS, somewhat miraculously, appears to at once be both powerful and lightweight! After taking a casually stroll through the main page of the AngularJS website I was immediately able to start working with it.

Currently one of my favorite things about AngularJS is the ability to create your own custom HTML tags. For instance, in a prototype I’m building, I just used AngularJS to create a new <lawsearch> element which loads up a set of search results and displays them on the page. Let’s take a look at how this works.

First I create code that defines this new element, enables the data binding, and governs its behavior, (make sure to read the comments here):

//define a module (yay! modular code!)
angular.module('law', [])
//within that module, define the idea of a lawsearch element
.directive('lawsearch', function () {
    return {
        restrict: 'E', // this indicates that we're describing a new element
        scope: {}, //every element will have it's own scope

        //this is where the behavior is defined
        controller: function ($scope, $element) {
            $scope.init = function (q) {
                $scope.q = q;

                //here we issue the actual query using jQuery
                $.ajax({
                    url: "http://ec2-75-101-214-153.compute-1.amazonaws.com:8983/solr/statedecoded/search",
                    data: {
                        "q": $scope.q,
                        "wt": "json",
                        "rows":3
                    },
                    traditional: true,
                    cache: true,
                    async: true,
                    dataType: 'jsonp',
                    success: function (data) {
                        //and when we get the query back we 
                        //stick the results in the scope
                        $scope.$apply(function () {
                            $scope.results = data.response.docs;
                        });
                    },
                    jsonp: 'json.wrf'
                });
            }
        },
        //finally, here's the presentation our new lawsearch element
        template:
            '<div>'+
            '    <h1>{{q}}</h1>'+
            '    <ul class="unstyled">'+
                     //check out how easy it is to iterate through elements
            '        <li ng-repeat="result in results">'+
            '            <h4>{{result.catch_line}}</h4>'+
            '            <p>{{result.text}}</p>'+
            '        </li>'+
            '    </ul>'+
            '</div>',
        replace: true
    };
})

I love that AngularJS has totally nailed the model-view-controller pattern. Usually when someone says they’re using a MVC-based framework I enjoy asking them what that means and how their framework fulfills the MVC pattern. I guess I’m sadistic, but I like hearing them mumble and sputter as they try to answer the question.

But here, AngularJS has made it pretty clear. The model is the data that hiding behind the lawsearch element (this is the data that we keep shoving into the $scope object), the view is the template that describes how the data will be presented, and the controller is the function (labeled “controller” above) that acts as the intermediary between the model and the view. When the model changes, the controller relays the necessary information to the view and when users interact with the view, the controller can relay changes back to the model. I love it.

Now that the JavaScript piece is done, let’s see how one would use this (again, read the comments here):

<html>
<head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <title>Law Search</title>
    <script type="text/javascript" src="//code.jquery.com/jquery-2.0.2.js"></script>
    <!-- We've got to include angular... duh... -->
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>
</head>
<body ng-app="law"><!-- this extra bit indicates that the law 
                 module is in charge of everythin in this tag -->
    <!-- and then we just create several searches! 
         the init calls code in the controller -->
    <lawsearch ng-init="init('vehicle')"></lawsearch>
    <lawsearch ng-init="init('house')"></lawsearch>
    <lawsearch ng-init="init('pet')"></lawsearch> 
</body>
</html>

It’s hard to get much simpler than that. Want to see this in action? Here it is, live.

And… if you didn’t find that impressive, you’re sure to love this: I’ve used AngularJS to resurect the blink element!


Check out my LinkedIn Follow me on Twitter

Tags: ,
solr

post-type:post

5 comments on “Creating a Solr <search> HTML element with AngularJS!

  1. Any specific reason why you’re using Jquerys $.ajax call and not angulars native $HTTP service? This saves you from having to use “outside” code and manually running a $apply to call a digest. AngularJS $http service does indeed support jsonp.

  2. @Bolero there’s no good reason to not use $http, and many good reasons too use it. This is our n00b approach and we didn’t understand how to use $http with jsonp off the bat. But we’ve definitely figured it out by now.

    Check out this this example of a simple solr search widget. Similar to above, just with better angular practices. Specifically this file has the corresponding code.

    Enjoy!

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>