Adventures in MonoRail, Part II : In Search of Auto-Completion - Abstract Deviance
Tuesday, July 24, 2007 7:38 PM craig

Adventures in MonoRail, Part II : In Search of Auto-Completion

Being, as previously stated, an Ajax n00b, I found myself today needing to implement text field auto-completion. Since MonoRail has all the nifty AjaxHelper stuff built in, I decided to use the help that was offered, assuming that I'd be able to make it work without actually knowing how it works.

I was, as you've no doubt guessed, mistaken. I shall attempt to document my morning's suffering as a simple example so that others might be spared the pain.

For those of you who are desirous of shiny Ajax goodness, MonoRail "ships" with the prototypejs and script.aculo.us JavaScript libraries which give you all sorts of useful and pretty effects, and makes it pretty easy to reference them in your layout as well. Assuming you have the Castle project templates installed, create a new MonoRail project. To get the project templates you'll need to install Castle using the MSI available for RC2, but don't forget to update the libraries with one of the later builds - I'm using build 442 at the moment. We'll edit the default layout template for our sample to add the JavaScript libraries which will leave it looking like this:

   1:  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
   2:  <html>
   3:  <head>
   4:      <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
   5:      <title>MonoRailAjaxAutoComplete</title>
   6:      <link rel="stylesheet" type="text/css" href="$siteroot/content/css/base.css" />
   7:      $AjaxHelper.GetJavaScriptFunctions()
   8:      $ScriptaculousHelper.GetJavascriptFunctions()
   9:  </head>
  10:  <body>
  11:      $childContent
  12:  </body>
  13:  </html>

That's all you need to get started. Now in our index view for our home "area" we simply use our trusty AjaxHelper to create a text input field that is already all set up for auto-completion, something like this:

   1:  <p>Autocompletion with MonoRail</p>
   2:  <p>$AjaxHelper.InputTextWithAutoCompletion("test", "/home/completionlist.rails", "%{}", "%{}")</p>

Okay, so that will generate a text input field with an id of "test", and we still don't need any code in the corresponding Index() method of our HomeController, since its not doing any real work. But we can see that according to the URL we've provided to our auto-completer, we'll need to add a CompletionList() method, as well as the corresponding view in the "views/home" folder, so that our asynchronous Ajax method has something to call to get a list of options. Now this method will need to return a list of items to display in the auto-completion drop-down list, but it will also need to do some basic filtering of the list based on the current user input. So we'll construct something simple:

   1:          public void CompletionList()
   2:          {
   3:              string query = this.Context.Request.Form["test"];
   4:              List<string> results =
   5:                  new List<string>(new string[] {"Mazda", "BMW", "Mercedes Benz", "Toyota", "Ford", "Volkswagen"});
   6:              if (!string.IsNullOrEmpty(query))
   7:                  results = results.FindAll(delegate(string s) { return s.StartsWith(query, StringComparison.OrdinalIgnoreCase); });
   8:   
   9:              PropertyBag["results"] = results;
  10:          }

There, we have a list of car manufacturers that will be filtered by the input provided by the user, which as you can see is available in our form parameters collection since it is sent by HTTP post with the id of "test" we provided for out text input field. So now we need to fill out our completionlist.vm view so that it returns those results in a manner that will be meaningful to the Ajax script. The script is expected nothing other than an unordered HTML list, so our view is very simple:

   1:  <ul>
   2:  #foreach ($result in $results)
   3:  <li>$result</li>
   4:  #end
   5:  </ul>

And that is pretty much all there is to it.. we have an auto-completing text box. With a few CSS classes added swiped from a script.aculo.us sample to make the result a little prettier, it looks like this:

And, without further ado, here's the sample code.

Filed under: , ,

Comments

# re: Adventures in MonoRail, Part II : In Search of Auto-Completion

Tuesday, July 24, 2007 9:58 PM by hammett

Craig, why

string query = this.Context.Request.Form["test"];

instead of

public void CompletionList(string test)

?

# re: Adventures in MonoRail, Part II : In Search of Auto-Completion

Wednesday, July 25, 2007 9:39 AM by craig

Urgh, because I'm a n00b :|

# re: Adventures in MonoRail, Part II : In Search of Auto-Completion

Thursday, October 04, 2007 1:03 PM by Armand du Plessis

Thanks Craig. Was searching for this and got your blog as first hit :)

# Monorail Dynamic Actions = Reusable Goodness!

Friday, August 29, 2008 11:15 PM by Patrick Steele's .NET Blog

Monorail gives you a nice, easy to use MVC implementation on top of ASP.NET. Dynamic Actions is a feature

# Monorail Dynamic Actions = Reusable Goodness!

Friday, August 29, 2008 11:25 PM by Patrick Steele

Monorail gives you a nice, easy to use MVC implementation on top of ASP.NET. Dynamic Actions is a feature