While reviewing my latest post’s outbound click-through stats, I noticed that most of you found Rik LomasquickSearch more interesting than the rest. In light of that interest, I’ve decided to show you an example of how you might implement its functionality in conjunction with ASP.NET.

For this demonstration, I’m going to use Delicious as a source of sample data to apply the technique to. I’m sure you’re getting tired of my RSS feed as demo data, and the Delicious API provides an abundance of topical data via jQuery tag feeds.

In this post I will show you how to use LINQ to XML to query the Delicious API, display that data in a table, apply the quickSearch plugin to that table, work around a problem that arises when using quickSearch with ASP.NET, and lay the groundwork for a “no results” state.

Working with the Delicious API

The Delicious APIs are fairly straightforward to work with. Their XML API takes the shape of an RSS feed containing items matching a query that you specify within the request URL. This is sometimes referred to as a RESTful API.

For example:


That request would return an RSS document describing the 25 most recent items appearing on the “popular” list for the jQuery tag. The actual XML returned for each item would look something like this (slightly abridged):

Now that we have a handle on how to request the data and what the data looks like, we can easily build a LINQ to XML expression to query the API.

Using LINQ to XML to query the API

If you’ve dealt with XPath for querying XML documents in the past, you’re going to love LINQ to XML. For example, these few lines of code are all that is required to execute the API request and extract a collection for databinding:

This code will execute the REST request and then extract an IEnumerable collection containing the titles, URLs, and up to five tags for each item returned by the API.

Presenting the result of the API call

Presenting the data is a fairly standard affair. For this example, I’m going to use a table to display the results.

One detail we must attend to is that our table is rendered with a <tbody> element. Otherwise, it will be difficult to prevent the filtering functionality from applying to the table header as well.

To maintain the necessary control over the rendered HTML, let’s use a Repeater:

The only tricky aspect of this is rendering the tags. Since those are contained in a List<string> nested inside each item’s Tags property, we need to nest a Repeater within the ItemTemplate to iterate over and display each item’s tags.

The trick to this is assigning the Tags property as the datasource for each of the nested Repeater controls. Using the SeparatorTemplate of a comma, we get a CSV rendering of the strings in the Tags List.

With a bit of CSS styling, our rendered table looks something like this:

What our rendered table looks like.

Using quickSearch to implement progressive search

Now that we’ve built an appropriate table of data, using quickSearch to implement the progressive search functionality is the easiest step:

It should make sense now why rendering the <tbody> was important. It provides us an avenue to more easily construct a jQuery selector which correctly identifies the DOM elements that we intend to identify as searchable content.

Most of the options are self explanatory. This page on the author’s site contains more information about those settings and their defaults.

If you’re new to jQuery, the position option may give you trouble at first. Position has four possible values which match corresponding jQuery manipulation functions: prepend, append, before, and after. See those documentation pages for examples of how each option works, relative to the attached element.

Note: When quickSearch is attached to a table, avoid using prepend or append. Inserting its form inside a table’s markup will cause bad things to happen.

Now, if only that had worked

There’s one big problem with all of this: it doesn’t work!

You probably know that ASP.NET WebForms controls, such as the Repeater used above, must be enclosed within a <form runat=”server”> element. However, what you may not have known is that the quickSearch plugin renders itself in a form tag as well.

Unfortunately for us, HTML simply does not allow nested form elements. So, if you try to render the quickSearch interface within a WebForm, things don’t go well.

Some browsers handle this nested form problem gracefully, but others don’t. In any case, you certainly should not rely on the browser correcting this for you.

Making it work

In this simple example, we could attach quickSearch above the WebForm’s <form> element and it would work. That isn’t a good general solution though.

So, I updated the plugin to render a <div> instead of a <form>. Problem solved.

The modified version is included in the source download below. Feel free to use it in your own projects.

After I wrote this, Rik was kind enough to add an option to the official plugin to fix this for us: isFieldset. Setting this option to true will cause the search form to be rendered as an HTML <fieldset> element, which solves our problem just as well as a <div> and is more semantically correct to boot.

Thanks, Rik!

Displaying a “no results” message

A commenter on my last post made a good point, mentioning that the plugin lacks support a “no results” message when your search string filters all elements.

By adding an onAfter event handler, we can easily add that functionality ourselves:

I’ll leave the presentation specifics up to you. Just don’t use <blink>!

Conclusion: worth the effort

When applied to the appropriate situation, this real-time filtering technique is very compelling. Your users will absolutely love it.

Also be sure to check out Rick Strahl’s recent post on highlighting search matches, instead of filtering them.

If you have a Delicious account, why not take a few seconds and save this post to Delicious. Maybe we can get this post on the popular list used in the demo!


quickSearch-demo.zip (63kb)