List Model

Sometimes you wish to represent a collection of data for which a part of the template should be repeated, once for each collection element. These collections are represented by the TemplateCollectionModel interface. Whenever an object is specified to FreeMarker inside a <list> or <foreach> block, the engine casts it into this interface.

This interface is quite simple, as it consist of only a single method:

public TemplateIterator iterator()
                throws TemplateModelException;
        

This method returns an iterator object that will be used to enumerate the elements of a collection. The TemplateIterator interface itself is has a single method:

public TemplateModel next()
                throws TemplateModelException;
        

This method is called repeatedly to fetch the next element of the collection, until it returns null, which indicates there are no more elements.

There is another functionality commonly associated with ordered collections of elements (that is, lists) and that is access to elements using a numeric index. If your collection model supports this kind of access, it should implement the TemplateSequenceModel interface. This interface consists of two methods:

public TemplateModel get(int index)
                throws TemplateModelException;
public int size()
                throws TemplateModelException;
        

Getting started quickly

To quickly roll your own sequence model, you can use either the freemarker.template.SimpleSequence class, or you can wrap any native Java array or an arbitrary implementation of java.util.Collection interface using the static methods provided by the freemarker.ext.beans.BeansWrapper class.

Historical Notes

The the two interfaces we describe above did not exist prior to FreeMarker 2.0. Instead, FreeMarker 1.x featured an interface named TemplateListModel which is retained for backward compatibility, but deprecated. It was in fact a rewindable iterator and as such it was inherently thread unsafe, which is a big problem if your data model is used concurrently from separate threads (which can easily happen in a server application environment).

The class freemarker.template.utility.ExtendedList has been removed, since the default implementation SimpleSequence now implements all of the extra functionality that this class provided..

  • You can use myList?size to get the number of elements in a list.
  • You can use myList?first or myList?last to get the first and last items respectively.
  • We have implemented a variable named iterationVariable_has_next to indicate within a loop whether there is another item following this one.