I was just walking through all the sample web apps in the Spark project converting them from ${H(expr)} and ${expr} to ${expr} and !{expr}. One thing I hate to admit is how frequently I had demo data like product names going out without html encoding - so for me that’s kind of case in point on that particular feature.

The other thing I noticed was when I was working updating a _NavItem.spark partial file in a MonoRail web app. I saw a comparison of a value with a Context.Request.RawUrl and had an idle curiosity about what other properties might have been available.

So I thought, hey! Great time to see if that intellisense thing is working. Ctrl+space and Bam! That property is deprecated.

_ShowNav.spark

But even better than that is how well it informs you of the vast array of properties available at every level. I really wish we’d had this available a few projects ago. I guess you should never underestimate the value of your development tools.

Here’s a montage of how easy it is to find what I believe is the proper value to use.

This is also a pretty interesting partial file. I’d like to take some time and look at what it’s doing.

<div id="${navId}">
  <!--
  The "INavProvider Nav" being used here is added to
  the abstract base class View in the project

  If you don't want to use a project wide base class you can
  add a property with global type="INavProvider" Nav="null"
  in a spark file and it would also be "set" when the
  Windsor container instantiates the view
  -->
  <ul>
    <li each="var item in Nav.GetNav(Context, navId).Items"
        class="${IsSelectedClass(item)}">
      <a href="!{SiteRoot + item.Url}">${item.Caption}</a>
    </li>
  </ul>
</div>
<macro name="IsSelectedClass" item="NavItem">
  #if (SiteRoot + item.Url == Context.UrlInfo.UrlRaw) return "selected";
</macro>

One thing to note is this example is using the Windsor container to instantiate the view classes, providing service and dependency injection. The views are configured to use a base class in the project which has a public INavProvider Nav {get;set;} property. That’s what the Nav.GetNav(Context, navId) is invoking.

Another thing that’s interesting is how a macro IsSelectedClass is being called. That’s probably a bad name, isn’t it… The idea is it’s seeing if the given NavItem is selected and it’s returning a css class based on that. So your tab/nav can reflect your location.

It’s a trivial example (and only works for a single exactly equal Url so that’s impractical for real application) but it’s showing how you can also return values from macros. Normally a macro will return the accumulated html of the template material it contains, but because <macro name="IsSelectedClass" item="NavItem"> is really just a string IsSelectedClass(NavItem item) you can cut to the chase and return any value you want.

When it comes right down to it you can think of a macro as a helper function declared in the Spark language.