Introduction to the dataSchema and dataField elements

This example explains how to use the dataSchema and dataField elements to create an interface or mapping between a data source and a data consumer, such as a Backbase Tag Library (BTL) listGrid. The use of such an interface makes it possible for a single data consumer to use data from different sources and can significantly reduce the maintenance overhead in applications where the same data source is used by multiple consumers. The formatting capabilities of the dataField element are also explained.

Prequisites and Intended Audience

This example is intended for Web developers interested in using the data binding capabilities of the Backbase Client Framework. To work through this example you need the Backbase Client Framework and intermediate level experience developing with BTL and JavaScript.

Overview

The dataSchema and dataField elements are used to provide a mapping between the names used to refer to fields in the data source, and the actual queries used to retrieve the data. This document begins by reviewing how data fields are referenced in a listGrid in the absence of a dataSchema, and explains the limitations of this approach. The document then explains the concept of dataSchemas and shows how to use a dataSchema to facilitate data retrieval. Finally, the in-built formatting capabilities of the dataField element (style and currency) are discussed and demonstrated.

Providing a consistent interface to the data

Consider the fragment of data listed below. This fragment shows two "movie" records, each having three fields. The third field is labelled inconsistently in the data source as either "genre" or "category".

<movie>
        <title>The Seven Samurai</title>
        <director>Akira Kurosawa</director>
        <genre>Drama</genre>
</movie>
<movie>
        <title>Star Wars</title>
        <director>George Lucas</director>
        <category>Adventure</category>
</movie>

Listing: A sample data fragment

A listGrid or treeGrid widget could consume the data listed above by specifying appropriate values for the select attribute in a set of listGridCol or treeGridCol elements. The following code fragment shows how the data could be consumed by a listGrid. The title and director fields are selected by name, while the genre/category field is selected using an XPath (because of the inconsistent naming of this field in the data source).

<b:listGrid>
        <b:listGridCol select="title" />
        <b:listGridCol select="director" />
        <b:listGridCol select="*[3]" />
</b:listGrid>

Listing: Directly specifying data fields in a listGrid using the select attribute

The approach illustrated above, directly specifying queries in the data consumer, is suitable so long as (a) the consumer will not be used to visualize data from different sources, and (b) the same data source is unlikely to be used by different consumers. If either or both of the above conditions are not met, then directly specifying queries in the data consumer introduces limitations and may result in increased maintenance overhead.

For example, in the case where a data consumer such as a listGrid is used to display data from multiple sources, it would not be possible to correctly display data from sources in which the field names and field order differed from that for which the data consumer was originally configured. In the case where a single data source is used by several data consumers, a change in the record structure or field names would require that all the consumers were updated.

An alternative approach which is more suitable when wishing to use a single consumer to visualize multiple data sets, and which minimizes the amount of updating required when the structure of a data source changes is to use a dataSchema. Each dataField child element of the dataSchema provides a mapping between an arbitrary (though preferably descriptive) name and a field in the data set. Within the listGrid, fields are selected by referencing the names of the corresponding dataFields. The following code fragment shows how the previous example can be re-written using a dataSchema.

<b:dataSource name="myDataSource" e:behavior="b:localData">
        <b:dataSchema>
                <b:dataField name="title" select="title" />
                <b:dataField name="director" select="director" />
                <b:dataField name="genre" select="*[3]" />
        </b:dataSchema>
</b:dataSource>
<b:listGrid dataSource="myDataSource">
        <b:listGridCol dataField="title" />
        <b:listGridCol dataField="director" />
        <b:listGridCol dataField="genre" />
</b:listGrid>

Listing: Using a dataSchema to provide a consistent interface to a data source

The key difference between the two approaches presented above is the point at which the mapping between the field names and the underlying queries is defined. In the first approach, the mapping is defined within the data consumer, whereas in the second, the mapping is defined within the source. An advantage of the second approach is that should the queries used to refer to fields in the data ever need to be updated, only the mapping defined in the dataSchema needs to be changed. Defining the mapping within the source rather than the data consumer also has the advantage that a data consumer can be used to display data from different sources, even when fields need to be retrieved using different queries. For example, consider the two data fragments below.

<!-- source 1-->
<records xmlns="">
        <record>
                <title>The Seven Samurai</title>
                <genre>Drama</genre>
                <rating>88</rating>
                <stocklevel>10</stocklevel>
                <price>9.99</price>
        </record>
</records>
<!-- source 2 -->
<records xmlns="">
        <record>
                <movie>Pulp Fiction</movie>
                <category>Crime</category>
                <stocklevel>5</stocklevel>
                <rating>60</rating>
        </record>
        <record>
                <movie>The Thin Red Line</movie>
                <category>War</category>
                <stock>0</stock>
                <rating>73</rating>
        </record>
</records>

Listing: Fragments from two differently structured data sets

With the exception of the rating field, the queries needed to extract data from specific fields differ between source 1 and source 2. In order to be able to display both data sets using the same listGrid, the two dataSchemas shown below can be used to provide a consistent interface to the underlying data.

<!-- dataSchema for source 1-->
<b:dataSchema>
        <b:dataField name="title" select="title" />
        <b:dataField name="category" select="genre" />
        <b:dataField name="rating" select="rating" />
        <b:dataField name="stock" select="stocklevel" />
</b:dataSchema>
<!-- dataSchema for source 2 -->
<b:dataSchema>
        <b:dataField name="title" select="movie" />
        <b:dataField name="category" select="category" />
        <b:dataField name="rating" select="rating" />
        <b:dataField name="stock" select="*[3]" />
</b:dataSchema>

Listing: Two dataSchemas which provide a consistent interface to different data sets

The Live Demo below shows a listGrid configured to retrieve data using dataField elements. The data source that is displayed in the grid can be selected using the comboBox. Since the dataSchemas associated with each data source provide a consistent mapping between the field names and the underlying data, the data will be displayed correctly even though, as shown above, the structures of the two data sources differ.

Live Demo: Using dataSource elements to display different data sets in a listGrid

Formatting fields in a data set

In addition to their role in referencing fields in a data set, dataField elements may also be used to format the data. The formatting to be applied is specified using the format attribute, the value of which should be the name of one or more dataFormatters separated by spaces. Currently the data binding mechanism provides two predefined dataFormatters, style and currency. Other custom formatters can be created as required.

Note: The listGridCol and treeGridCol elements also support the format attribute, and that a value set on these elements is applied after (and in addition to) a value set on a dataField.

The code fragment below illustrates how dataFormatters can be used to influence the appearance of data in a listGrid. The category column, which displays the data from the genre field, uses the predefined style formatter. The style to apply is passed as an argument to the dataFormatter using square brackets. The price column has two formatters applied,the predefined currency formatter and the custom replaceComma formatter. The currency dataFormatter prepends a currency symbol to the data. The custom replaceComma dataFormatter is used to replace any commas in the data values with decimal points.

<b:dataFormatter name="replaceComma">
        return formattedValue.replace(",", ".");
</b:dataFormatter>
<b:dataSchema>
        <b:dataField name="title" select="title" />
        <b:dataField name="category" select="genre" format="style[font-style:italic;font-weight:bold]" />
        <b:dataField name="rating" select="rating" />
        <b:dataField name="stock" select="stocklevel" />
        <b:dataField name="price" select="price" format="currency[euro] replaceComma" />
</b:dataSchema>

Listing: Applying formatting to fields in a data set

The following Live Demo shows a listGrid which illustrates the effects of the above formatting. Note that even though the prices for the last three items use a comma as a decimal indicator in the original data set, all prices in the grid are displayed using a decimal point.

Live Demo: A listGrid with formatting applied to selected columns

Download

You can download a zipped version of the examples provided on this page to try them out for yourself.

Note: Make sure to extract the content of this zip file to the root folder of your web server or application server (for example, htdocs), and then run it from your local development environment.

Additional Resources

For more information on data binding, refer to the following documentation: