Templates may be used to generate any type of content. It is common to use a template to generate the items on a menu or in a listbox or tree. The syntax is the same regardless of what type of content is being created. In the previous example, we hard-coded a menulist with the list of countries, but we could also generate this list from the datasource. The same datasource may used for both the photos list and the menulist. Even though the same datasource is used, it will only be loaded once and both templates will be notified when the data has loaded.
We will need to add some information to the datasource in order to specify the list of countries that are available. There are two possibilities. First, a separate Seq could be added listing the countries. Then, a simple <member> condition can be used to iterate over it. Or, we could use an RDF type to specify the countries. Then, we could just look for all resources that were of the 'Country' type. We'll use this method here since we've already seen examples of generating results from a container.
An RDF type can be assigned to a node by using the predicate 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type' set to a resource for that type. In RDF/XML, a syntax shortcut may be used which involves replacing the Description tag with the type. We need to add the type to the two countries in the datasource, as well as ensure that the namespace is declared on the root RDF tag:
<nso:Country about="http://www.daml.org/2001/09/countries/iso#IT" dc:title="Italy"/> <nso:Country about="http://www.daml.org/2001/09/countries/iso#NL" dc:title="Netherlands"/>
The type of these two resources, when expanded with the namespace (not shown here), will be 'http://www.daml.org/2001/09/countries/country-ont#Country'. The resulting RDF triples for the first country will be:
http://www.daml.org/2001/09/countries/iso#IT -> http://www.w3.org/1999/02/22-rdf-syntax-ns#type -> http://www.daml.org/2001/09/countries/country-ont#Country http://www.daml.org/2001/09/countries/iso#IT -> http://purl.org/dc/elements/1.1/title -> ItalyThe type is just like any other triple in the datasource, so we don't need any special syntax to navigate over it. We just need to use the right predicate to look for all the countries. You might wonder what the ref attribute or starting point should be set to since there is no container for the countries. Actually, we can just use the type as the starting point.
<menulist datasources="template-guide-photos4.rdf" ref="http://www.daml.org/2001/09/countries/country-ont#Country">
Remember that the only requirement is that the starting point be a resource, but it doesn't matter what resource is used. The conditions will need to iterate over the arcs pointing into the type resource. Since we want the arcs pointing into the type, we need to determine the source or subject of a triple. Look at the resulting RDF triples above again if this is unclear. The starting node is 'http://www.daml.org/2001/09/countries/country-ont#Country'. We need to iterate over the 'type' predicate to find the individual countries. A second triple is used to get the title for the country.
<conditions> <content uri="?start"/> <triple subject="?country" predicate="http://www.w3.org/1999/02/22-rdf-syntax-ns#type" object="?start"/> <triple subject="?country" predicate="http://purl.org/dc/elements/1.1/title" object="?countrytitle"/> </conditions>
The action body will need to generate a <menuitem> for each result. It will also need to include a <menupopup> around all of the items. Since we only want to generate a single menupopup, it should go outside of the element with the uri attribute. Only the contents at the element with the uri attribute and below are copied for each result. The elements above are not.
<action> <menupopup> <menuitem uri="?country" label="?countrytitle" value="?country"/> </menupopup> </action>
The result will be two generated menuitems, one for each country, inside a menupopup. The value attribute is assigned the ?country variable so that the applyFilter function can use this value easily for filtering. The complete example shows this working. Note that due to a bug with template generation in menulists when the datasource hasn't loaded yet, you may have to load the example twice to get it work. This issue only affects the menulist element. Several workarounds can be used in this simple example. First, you could move the <menupopup> element outside of the template and put the datasources attribute on it instead of the <menulist> element. This will work in this simple example, but has the disadvantage that the builder won't be able to generate the content lazily only when the popup is opened. Another workaround is to just rebuild the template once the data has been loaded.
Next, we will look at how to add the All choice to the menu, which won't be generated from the datasource.