Lift provides built in snippets to allow easy pagination of data. Here is a brief reference for the SortedMapperPaginatorSnippet (SMPS henceforth). As you can tell from the name, it specifically allows sorted pagination of mapper data.
The Lift documentation provides more general information on PaginatorSnippets here.
Let’s say you have a snippet called listProducts. You’d like listProducts to display a sorted pagination of all your products, which are stored in your database. Of course, you’ve already created Mapper classes to relate to the data. The very first thing to do is add a couple of imports to your snippet:
import net.liftweb.mapper.{By, OrderBy, MaxRows, Like,Cmp,NotNullRef,NullRef, QueryParam, StartAt, Ascending, Descending}
import net.liftweb.mapper.view.{MapperPaginatorSnippet, SortedMapperPaginatorSnippet}
Now let’s create the paginator.
val paginator = new SortedMapperPaginatorSnippet(Product, Product.createdAt, “createdAt” -> Product.createdAt, “price” -> Product.price) {
}
The first argument sets the mapper class we are querying. The next one specifies the column we want to sort by initially. Finally we have the two columns we will allow the user to sort by. These are actually both part of the third argument, but thanks to scala’s repeated parameters, we can have as many choices as we’d like. The third argument(s) should be pair(s) of column labels [String] and MappedFields.
Now let’s say we want to add some custom query criteria. For example, let’s only return products who have their inStock field set to true. To do this, we must set the constantParams var that is built into SMPS. This variable takes the format of a Seq[QueryParam]. So inside our paginator, add the following code:
var params: List[net.liftweb.mapper.QueryParam[Product]] = Nil
params = By(Product.inStock, true) :: Nil
constantParams = params
The first line sets up the Seq[QueryParam] format of the variable. Then, we set the list to have 2 elements: first is a By QueryParam and second is a Nil. If we had set the variable to just the QueryParam, then Scala would have changed the variable type to QueryParam. By prepending a Nil to the end, it maintains its status as a sequence of elements. The By param takes two arguments. First is the Mapper field to check and second is the value it must be. So in this case, we are checking the inStock is true. Finally set constantParams equal to params. This adds our custom query to the SMPS’s logic.
This is all you need to do to set up an SMPS in a snippet. To add it to a template, you need to bind each page to something in the xhtml. An example of how to do this would be to add this code to the snippet (outside of the paginator!):
def all(xhtml: NodeSeq) : NodeSeq = paginator.page.flatMap(a => bind(“p”,xhtml,”createdAt” -> a.createdAt, “price” -> a.price, “inStock” -> a.inStock))
Paginator creates a “page” that is essentially a list of Products that is sorted and offset based on which page the user has selected. The code above simply binds each product in the paginator.page to some xhtml code. We could use this on a Lift template like this:
<lift:listProducts.paginator.paginate>
<tr><th><sort:createdAt /></th><th><sort:price /></th></tr>
</lift:listProducts.paginator.paginate><lift:listProducts.all>
<tr><td><p:createdAt /></td><td><p:price /></td><td><p:inStock /></td></tr>
</lift:listProducts.all>
<lift:listProducts.paginator.paginate> <nav:first/> | <nav:prev/> | <nav:allpages/> | <nav:next/> | <nav:last/> | <nav:records/>
</lift:listProducts.paginator.paginate>
Note that all of the tags inside both the <lift:listProducts.paginator.paginate> areas are built into SMPS, which the code inside <lift:listProducts.all> is populated by the custom all function we defined above. Also note that all this can (and should) be customized for your own needs.
A final point about SMPS is that the current sort field, offset, and sort order can all be set by url query strings:
paginatorpage?sort=0 would cause our SMPS above to sort by the createdAt field. sort=1 would cause it to sort by price.
paginatorpage?offset=100 would cause our SMPS’s current page to start at record 100.
paginatorpage?asc=false would cause our SMPS to sort in descending order.
Of course these can be combined such as: paginatorpage?sort=1&asc=true
Trackbacks