The enhanced listGrid in 4.1 has some powerful features like the ability to intelligently format columns of data. For example, you may want to highlight high values in green and low values in red. You can now do that easily just be adding a dataFormatter.
Let's start with a standard listGrid with an internal dataSource:
<b:dataSource e:behavior="b:localData" dataType="application/xml">
<b:dataContainer>
<xi:include href="gridData.xml" />
</b:dataContainer>
</b:dataSource>
<b:listGridCol select="title" label="Title" width="150px">
<b:fieldEditor>
<input />
</b:fieldEditor>
</b:listGridCol>
<b:listGridCol select="genre" label="Genre" width="100px">
<b:fieldEditor>
<select>
<option value="" />
<option value="Action">Action</option>
<option value="Adventure">Adventure</option>
<option value="Crime">Crime</option>
<option value="Drama">Drama</option>
<option value="Horror">Horror</option>
<option value="Thriller">Thriller</option>
<option value="War">War</option>
</select>
</b:fieldEditor>
</b:listGridCol>
<b:listGridCol select="premiere" label="Premiere" width="90px">
<b:fieldEditor>
<b:calendar mode="popup" />
</b:fieldEditor>
</b:listGridCol>
<b:listGridCol select="rating" label="Rating" width="80px" align="right">
<b:fieldEditor>
<b:slider showLabels="false" />
</b:fieldEditor>
</b:listGridCol>
<b:listGridCol select="price" label="Price" width="70px">
<b:fieldEditor>
<b:spinner stringBefore="$" step="1" decimals="2" />
</b:fieldEditor>
</b:listGridCol>
</b:listGrid>
Now let's define some styles we can use to format the rating column:
.high {
color: green;
font-weight: bold;
}
.low {
color: red;
font-weight: bold;
}
</style>
Next we need to define a formatting function that will make the numbers green if higher than (say) 86 and red if lower than 80. Place the function inside a b:dataFormatter tag and it will automatically be registered as a valid format with the name provided, in this case the "traffic" format.
<b:dataSource e:behavior="b:localData" dataType="application/xml">
<b:dataFormatter name="traffic" type="application/javascript"><![CDATA[
var sClass = 'normal';
var val = parseInt(value, 10);
if (val > 86) {sClass = 'high' }
if (val < 80) {sClass = 'low' }
return '<span class="' + sClass + '">' + formattedValue + '</span>';
]]></b:dataFormatter>
<b:dataContainer>
<xi:include href="gridData.xml" />
</b:dataContainer>
</b:dataSource>
Note the function returns a valid HTML string. The function has available three arguments:
- value
- the value of the data
- formattedValue
- the string containing the formatted HTML - since several formatters can apply to a column, a formatter may want to wrap a previously formatted value like '$34.50'
- raw
- a javascript pointer to the value itself, whether it is an XML element or javascript object, etc.
The last step is to add the format attribute to the ratings column in the listGrid:
<b:fieldEditor>
<b:slider showLabels="false" />
</b:fieldEditor>
</b:listGridCol>
Refresh the page and see how the values are now formatted with a class based on which value range they fall into. Obviously the formatting function could be made more flexible by parameterizing the range values and having the function look them up at run time (left as an exercise for the reader ;-)
Another application is to replace some text values with icons.
Let's define a formatting function that adds the relevant icon in front of the text value.
return "<img src='" + value + ".gif' />" + formattedValue;
]]></b:dataFormatter>
You could just as easily replace the text value with an icon only. This formatter takes the concatenates the value with '.gif' to create an image before the previously formatted value. In the attached example, the formatted value is the plain text value of the film genre, but this formatter uses the formattedValue variable which could have been converted by a previous formatting function into some HTML, so it preserves the effect of that formatter and just adds to it. If you want this formatter to ignore any previous formatting, you would use the value variable instead.
Add the format to the genre column and we're done!
| Attachment | Size |
|---|---|
| Fields.zip | 3.41 KB |

Comments
Does this new functionality
27 November, 2007 - 17:36 — davidmiddletonDoes this new functionality also work for the JSF listgrid?
If so, can you give an example?
JSF listGrid?
1 January, 2008 - 03:33 — kahujaHi Richard,
I would like to know, if we can extend the same functionality in the JSF edition of the listGrid? If yes, can you point to examples or a reference implementation
Thanks
Kapil Viren Ahuja
Workaround for listGrid formatting
19 January, 2008 - 07:31 — RichardI checked the javadocs and I don't see how you'd set the format normally.
Here is a workaround:
First, the b:dataFormatter is a global element. Put it anywhere, just wrap it in f:verbatim tags like you do for all client-side code.
Second, add a client-side event handler (also in f:verbatim tags) to set the format attribute of the relevant listGrid column. This handler should be inside the listGrid.
<e:handler event="construct">
<c:setAttribute name="format" select="'myDataFormat'"
with="b:listGridCol[@select = 'myDataField']" />
</e:handler>
</f:verbatim>
This will set the format for the column showing values of myDataField (ie. has a select attribute with a value of 'myDataField'). You might need to investigate what attributes are set in the listGridCols to ensure that this targetting works. It might be that the dataField attribute is better to use -it depends which JSF uses.
With this kind of approach, you can add client-side features during the period after they are added to the Client and before they are exposed through the JSF API.