--
PedroRio - 17 Jan 2011
XEO Library Viewers
In the
previous chapter you created the list/edit/lookup viewers for the LIB_Author Object Model (without the need to create a specific Java Bean to implement custom behavior). In this chapter you'll create the remaining viewers and the respective Java Beans (when necessary) to implement custom behavior.
The first step to speedup the viewer creation is using XEO Studio's scaffolding tool as before to generate the basic structure for most of the viewers. Again, go to the "XEO Studio" menu, choose "Utilities" -> "XEO Scaffolding", press "ok" to skip the warning and choose the LIB$1.0 Package from the list (if you had already customized the Author viewers you would have to be careful not to choose that Object Model, because Scaffolding overrides existing viewers)
If you do that, you'll have one folder for each Object Model created inside the
webapps/default/viewers folder. (
Entries added to the Main.xvw viewer?). Create a new entry in the Main_Library.xvw viewer for the list of books.
Just like in the previous chapter, add the following entry to the Main_Library.xvw, right bellow the entry for the list of authors:
<xvw:menu text='Books'
value="{viewerName:'LIB_Book/list.xvw', boql:select LIB_Book}"
target='Tab' serverAction="#{viewBean.listObject}" />
You can leave the list viewer, for now, this part we'll focus on the Book's edit viewer. XEO Studio's Scaffolding will have generated an edit viewer that should look like the one depicted in figure
LibViewers.1
Figure LibViewers.1 - The preview of the viewer generated by scaffolding to edit a LIB_Book instance
As you can see in figure
LibViewers.1, the attributes of a book are all displayed one beneath the other, and collection attributes are displayed as tabs. The general structure of this viewer is the following:
- xeo:formEdit
- xvw:rows
- xvw:row and xvw:cell per xvw:attribute
- xvw:tabs
- xvw:tab with xeo:bridge component
- xvw:tab with xeo:bridge component
To give it a more clean look you'll rearrange the components and introduce some new ones, to achieve the result depicted in figure
LibViewers.2 (and
LibViewers.3).
Figure LibViewers.2 - Preview of the final result desired for the first tab (General)
And the "Additional Information" tab will be like the one depicted in figure
LibViewers.3
Figure LibViewers.3 - Preview of the final result desired for the second tab (Additional Information)
Building the viewer step-by-step
In order to give you a more in-depth view of composing a viewer, we'll create it step-by-step. First, start by removing all of the content generated by the Scaffolding tool (except the basic components
xvw:root,
xvw:viewer and
xeo:formEdit). Add a
xvw:tabs component (a tab container) under the
xeo:formEdit. As child elements of the
xvw:tabs component, add two xvw:tab components (actual tabs) add the label property to each of them ("General" to the first and "Additional Information" to the second), the viewer definition should be like the following:
<xvw:root xmlns:xvw="http://www.netgest.net/xeo/xvw" xmlns:xeo="http://www.netgest.net/xeo/xeo">
<xvw:viewer beanClass="netgest.bo.xwc.xeo.beans.XEOEditBean" beanId="viewBean">
<xeo:formEdit>
<xvw:tabs>
<xvw:tab label='General'></xvw:tab>
<xvw:tab label='Additional Information'></xvw:tab>
</xvw:tabs>
</xeo:formEdit>
</xvw:viewer>
</xvw:root>
Use the built-in preview (remember to launch the project before) in XEO Studio to check the result. It will be like the one depicted in figure
LibViewers.4.
Figure LibViewers.4 - Preview of the LIB_Book edit viewer in XEO Studio
Next you'll make creative use of the
xvw:rows component in order to put the book fields in the left side of the viewer and an image of the book cover in the right side. You can imagine the
xvw:rows component like a table, with several rows and columns. To achieve the desired effect you'll need to create a
xvw:rows component with one row and two (side-by-side) cells. The first cell will contain the all the attributes to fill and the second cell will have the book cover image. The trick to maintaining the structure is to reuse another
xvw:rows component in the first cell.
So the structure will be like the following for the "General" tab:
<xvw:tab label='General'>
<xvw:rows>
<xvw:row>
<xvw:cell><!-- Book fields will be here --></xvw:cell>
<xvw:cell><!-- Book cover will be here --></xvw:cell>
</xvw:row>
</xvw:rows>
</xvw:tab>
Previewing in XEO Studio will not produce any result as the
xvw:rows,
xvw:row and
xvw:cell components to not have any visible visual representation. To put the book fields in the
first cell, use the following code:
<xvw:cell>
<xvw:rows>
<xvw:row><xvw:cell><xvw:attribute objectAttribute='title' /></xvw:cell></xvw:row>
<xvw:row><xvw:cell><xvw:attribute objectAttribute='isbn' /></xvw:cell></xvw:row>
<xvw:row><xvw:cell><xvw:attribute objectAttribute='state' /></xvw:cell></xvw:row>
<xvw:row><xvw:cell><xvw:attribute objectAttribute='publisher' /></xvw:cell></xvw:row>
<xvw:row><xvw:cell><xvw:attribute objectAttribute='frontCover' /></xvw:cell></xvw:row>
<xvw:row><xvw:cell><xvw:attribute objectAttribute='edition' /></xvw:cell></xvw:row>
</xvw:rows>
</xvw:cell>
Previewing the result in XEO Studio will be like depicted in figure
LibViewers.5
Figure LibViewers.5- Preview of the edit viewer for LIB_Book with form fields
To display the image stored in the frontCover attribute of LIB_Book you'll require the
xvw:attributeImage component which is designed to render an image file stored inside an attribute of type binary data. The attributeImage component requires an alternate image (in case the attribute does not contain an image). Google any image you like in google (or use the image "emptyImage" in annex) and save it in a new "Extras/Images" folder inside the default webapplication with the name "emptyImage.jpg".
Now put the following code inside the second xvw:cell component:
<xvw:attributeImage width='100' height='180'
emptyImage='Extras/Images/emptyImage.jpg' objectAttribute="frontCover" />
The
xvw:attributeImage component requires the
objectAttribute property to know where to fetch the image to display and an
emptyImage attribute with the path to an image to display when no file is found in the
objectAttribute.The
width and
height properties allow you to control the image's dimensions. If you preview the viewer in XEO Studio you'll see your image displayed. You can use the preview to interact with the viewer, choose an actual image for the front cover attribute and watch it display that image in place of the default emptyImage. This scenario is depicted in figure
LibViewers.6
Figure LibViewers.6 - Image composition displaying the LIB_Book edit viewer with the xvw:attributeImage rendering the default image and a sample image for a given book.
Having added a preview to the images you can now add the two collection attributes (authors and categories) to the first tab of the edit viewer. If you recall from figure
LibViewers.2 in the "General" tab, you could see two inner tabs (with labels "Authors" and "Categories" respectively). To create inner tabs you use the same
xvw:tabs and
xvw:tab components, put them after the xvw:rows component, like the following:
</xvw:rows> <!-- End of the rows component -->
<xvw:tabs>
<xvw:tab label="Authors"></xvw:tab>
<xvw:tab label="Categories"></xvw:tab>
</xvw:tabs>
</xvw:tab><!-- End of the "General tab" -->
<xvw:tab label='Additional Information'></xvw:tab>
To display a collection attribute, you'll need the
xeo:bridge component (historically a collection attribute is also known as a bridge). The
xeo:bridge component, if used in a viewer tied to the
XEOEditBean only requires you to set the
bridgeName attribute and the set of columns you want to be displayed from the instances in the collection. In the
authors collection attribute you'll only need to display the
name attribute (as it's the only attribute the LIB_Author Model has). The same is valid for the
categories collection attribute.
To use the
xeo:bridge collection for authors and categories use the following code:
<xvw:tab label="Authors">
<xeo:bridge bridgeName="authors">
<xvw:columns>
<xvw:columnAttribute dataField="name"></xvw:columnAttribute>
</xvw:columns>
</xeo:bridge>
</xvw:tab>
<xvw:tab label="Categories">
<xeo:bridge bridgeName="categories">
<xvw:columns>
<xvw:columnAttribute dataField="name"></xvw:columnAttribute>
</xvw:columns>
</xeo:bridge>
</xvw:tab>
The result after this update is depicted in figure
LibViewers.7, bellow.
Figure LibViewers.7 - LIB_Book edit with first tab complete
To finalize the viewer, you now only need to compose the "Additional Information" tab with the remaining attributes. From figure
LibViewer.3 you can see that the "Additional Information" tab has the
backCover attribute, the
summary attribute as well as two labels for the
frontCover and
backCover. Those two labels, actually will be the labels for the
xvw:attributeImage component that you are going to use here, to display the front and back cover of the book. To build this tab, you'll again use the
xvw:rows component, this time with three rows, one for the back cover, one for the summary and one for the two images. Use the following code to achieve the result:
<xvw:tab label='Additional Information'>
<xvw:rows>
<xvw:row>
<xvw:cell><xvw:attribute objectAttribute="backCover" /></xvw:cell>
</xvw:row>
<xvw:row>
<xvw:cell><xvw:attribute objectAttribute="summary" /></xvw:cell>
</xvw:row>
<xvw:row>
<xvw:cell>
<xvw:attributeImage width='200' height='360'
emptyImage='' objectAttribute="frontCover" />
</xvw:cell>
<xvw:cell>
<xvw:attributeImage width='200' height='360'
emptyImage='' objectAttribute="backCover" />
</xvw:cell>
</xvw:row>
</xvw:rows>
</xvw:tab>
A small note about the html editor used for the
summary attribute. When one declares a long text attribute in an Object Model you can also select the type of editor used to edit that attribute's content. By default, a longtext attribute uses the HTML editor, but you can choose a simple textarea to edit the attribute's content. Open the LIB_Book Object Model, find the
summary attribute change the "Editor" property to "TEXT". Save the Object Model and return to the LIB_Book edit viewer to preview the changes, select the "Additional Information" tab and check that you no longer see the html editor, but instead a regular textarea, as depicted in figure
LibViewers.8
Figure LibViewers.8 - Summary attribute without the HTML editor.
Since we used scaffolding to generate all of the viewers, the lookup viewer for the LIB_Publisher Object Model exists and you can now use it within the edit viewer of a book to select a publisher.
Next
you learn a bit about the Java API that's available when customizing viewers and components.