k4200’s notes and thoughts

Programmer side of k4200

SiteMap examples

SiteMap is powerful, but a bit complex.

If you're using Lift, you might have had hard time using SiteMap. Yes, I'm one of those.

It's really powerful and an easy-to-read DSL, though it's a bit complex and requires quite a bit of Scala knowledge since it utilizes implicit conversions and some other techniques. Moreover, there's not enough information about it in "Exploring Lift", "Simply Lift" or the Lift Wiki.

When I was first trying out Lift, I was pretty new to Scala, so SiteMap was too hard for me to understand. I did a lot of trials and errors and got some working settings at that time. Now that I have almost a year of experience in Scala and am getting to understand SiteMap, so I think writing an entry about it might be of some use for those who are new to Lift and want to understand SiteMap.

I'll write as many examples as I can so you can use it with your project, play around with it for better understanding, etc. If you're interested in more details, please refer to the scaladoc.


What's SiteMap

First of all, what's SiteMap? A simple (but not precise) explanation is it's a list of Menu.

What's Menu?

Second of all, what's Menu? It's a bit complex, so let's not dig deeper into the problem, but in short, it consists of the following pieces of information.

  • name: like ID
  • link text: like label e.g. "About Us"
  • path: e.g. "/path/to/aboutus"

Actually, these things are defined in net.liftweb.sitemap.Menuable, not in Menu. Let's not go into this for now.

Example one: Default sitemap

The below is the default sitemap of the lift-basic project.

    def sitemap = SiteMap(
      Menu.i("Home") / "index" >> User.AddUserMenusAfter, // the simple way to declare a menu

      // more complex because this menu allows anything in the
      // /static path to be visible
      Menu(Loc("Static", Link(List("static"), true, "/static/index"), 
              "Static Content")))

It looks like DSL and easy to read. The above code makes the following menu entries:

  • Home
  • Login
  • Sign Up
  • Lost Password
  • Static

The first and last ones are obviously created by Menu.i("Home") and Menu(Loc(...)) respectively. The middle three are created by User.AddUserMenusAfter, which is defined in net.liftweb.proto.ProtoUser. Let's forget about ProtoUser for now.


Menu.i is probably the easiest way to create a menu. Remember there are three components of a menu, name, link text and path. The following code creates a Menu, whose name and link text are "Home" and path is "/index". Easy, huh?

Menu.i("Home") / "index"
    Menu(Loc("Static", Link(List("static"), true, "/static/index"), 
              "Static Content")))

You can also get a menu by passing an instance of net.liftweb.sitemap.Loc to Menu.


So, what's Loc then? As the name suggests, it represents a location. It has two apply methods. Let's look at one of them.

def apply (name: String, link: Link[Unit], text: LinkText[Unit], params: LocParam[Unit]*) : Loc[Unit]

Now, let's go back to the code.

    Menu(Loc("Static", Link(List("static"), true, "/static/index"), 
              "Static Content")))

The name of the menu is "Static" and the link text is "Static Content", and no params. The path is apparently supplied by Link. So, what's Link?


Link has the following apply method:

def apply (urlLst: List[String], matchHead_?: Boolean, url: String) : Link[Unit]

Lift's Scaladoc says the first parameter is "the URL to match", and the second param being true means "match anything that begins with the same path." So, any path that starts from "/static/" should match this menu. Am I correct? And url (or path) is "/static/index".


Now that I've covered every component of the code below.

    Menu(Loc("Static", Link(List("static"), true, "/static/index"), 
              "Static Content")))

This generates a menu with the following properties:

  • name: "Static"
  • link text: "Static Content"
  • path: "/static/index" (*)

(*) Any path under "/static/" match this Menu entry, meaning ... I'll write about it later (or another entry).

Example two: submenus

If you have a lot of pages, you want to use sub menus. Yes, you can do it with Lift SiteMap.

Here's a small example of sub menus.

      Menu(S ? "Foo") / "foo" / "index" submenus (
	Menu(S ? "Bar") / "foo" / "bar",
	Menu(S ? "Baz") / "foo" / "baz")

This snippet makes a menu containing two sub menus. Maybe no explanation is necessary to understand what it does. One thing to mention is S ? "foo" returns its localized text. S is defined in net.liftweb.http.

To be continued...

SiteMap and Menu are so powerful and there's too much to write in a single blog entry. I'll write another entry with some other examples hopefully soon.