create new tag
, view all tags
-- PedroRio - 19 Jan 2011

XEO Web Components - Introducing the API

In the previous chapters you generated viewers using XEO Studio's Scaffolding tool and went through an explanation of the basics of XEO Viewers as well as customized an edit viewer for the LIB_Book Object Model. In this chapter we'll introduce the Java API to use when creating your own custom viewers and beans, before that, however, you should create some instances of Object Models so that some of things you'll do in this chapter are visible.

Go the Main_Library.xvw viewer and add an entry for the list viewer of the LIB_Publisher Object Model with the following code:

<xvw:menu text='Publishers'
 value="{viewerName:'LIB_Publisher/list.xvw', boql:select LIB_Publisher}"
 target='Tab' serverAction="#{viewBean.listObject}" icon='resources/LIB_Publisher/ico16.gif'/>

And create a publisher with any name you like (Wrox Press, for example). Now add two book instances (for example book Beginning Spring Framework 2 and Professional Apache Tomcat 6), for the author you can use the previously created "John Doe" (or create a new one) and for the publisher use the newly created "Wrox Press" instance. The task in this section is to add a new tab to the LIB_Publisher and LIB_Author edit viewers, to display the list of each books that publisher/author has worked on. This will also be used to introduce the Java API that can be used.

Start by creating a new Java class in the org.examples.viewer.beans package with the name LibPublisherEditBean and make it extend the netgest.bo.xwc.xeo.beans.XEOEditBean class, then open the LIB_Publisher/edit.xvw file and change the classBean property to org.viewers.examples.viewers.beans.LibPublisherEditBean this will associate the viewer with this bean.

Next, add a new tab element, to the tabs container already present in the viewer, just like the following:

<xvw:tab label="Nucleus">
      <xeo:bridge bridgeName='nucleus' >
              <xvw:columnAttribute width="150" label="Nucleus" dataField="SYS_CARDID"/>
          <xvw:tab label="Published Books">

In order to display a list of Object Model instances you'll use the xeo:list component which is essentially like the xeo:bridge component used before, but tailored to display any list of instances (and not only lists that come from collection attributes). Since you'll be displaying books just use the book's title for the column. Type the following code in your viewer:

<xvw:tab label="Published Books">
   <xeo:list targetList="#{viewBean.dataList}" >
           <xvw:columnAttribute width="150" dataField="title"/>

Notice the "targetList='#{viewBean.dataList}'" property. It tells the xeo:list component that its data source should come from the dataList property of the current bean. Switch to the LibPublisherBean and create a method like the following (you'll need to import netgest.bo.xwc.components.connectors.DataListConnector):

public DataListConnector getDataList(){ }

The DataListConnector interface represents a list of elements to display in a xvw:gridPanel component (or any component that derives from the xvw:gridPanel component, actually, like the xeo:bridge and xeo:list components). For the xeo:bridge and xeo:list components there's an implementation of the interface that allows to use elements from a boObjectList instance. Compose the method with the following:

public DataListConnector getDataList(){
        String boqlExpression = "";
        boObjectList listBooksOfPublisher = ObjectListManager.list(getEboContext(), boqlExpression);
        return new XEOObjectListConnector(listBooksOfPublisher);

To create a list of instances you only need a XEOQL expression and a Context to pass to the list method of the ObjectListManager class. The resulting set of instances is passed to the constructor of the XEOObjectListConnector which is an implementation of the DataListConnector interface for lists of XEO Model instances. The getEboContext() method is available for any bean that extends the XEOBaseBean (the case of the XEOEditBean which is the bean you're extending in this situation)

The only situation here is what will be the XEOQL expression to retrieve all books from the current publisher, to do that, use the following query:

String boqlExpression = "select LIB_Book where publisher = " + getXEOObject().getBoui();

The getXEOObject() method is available in the XEOEditBean and returns the current boObject instance being edited (in this situation, the publisher instance); since relations between instances are done using the instance's BOUI (Business Object Unique Identifier), you use the getBoui() method to complete the query. If the BOUI of the current publisher is 12345, the query would be select LIB_Book where publisher = 12345.

If you do this, open the list of Publishers, open the "Wrox Press" instance and select the "Published Books" tab you should see the list of books like depicted in figure XWCIA.1.

Figure XWCIA.1 - List of books published by "Wrox Press"

A note before moving on to the next viewer. List ( xeo:list) components are usually found inside list viewers which are associated with the XEOBaseList bean, and that bean has a specific method to open an edit viewer from the double click of an item in the list. The XEOEditBean does not have such a method and if you try double clicking on a line of the "Published Books" list it will trigger an error, to prevent that from happening you'll either have to implement a method to respond to the double click event, or disable that via the onRowDblClick property, like in the following code:

<xeo:list targetList="#{viewBean.dataList}" onRowDblClick="">
      <xvw:columnAttribute width="150" dataField="title"/>

Also, a xeo:list component includes a default toolbar with the "New" button, which creates a new instance for that list. The problem here, again, is that the "New" button assumes the existence of a method that will perform that action and that method is available in the XEOBaseList bean (but it's not on the XEOEditBean). So, if anyone presses the "New" button on this viewer an error will be triggered; the solution to that will be either disabling the button, or implementing the method. Since there's not much sense in creating a book directly from the publisher's page, hiding the button seems a better choice and to do that use the renderToolBar property of the xeo:list component, which will hide the entire toolbar of the list. The following code is the final version for this viewer.

<xeo:list targetList="#{viewBean.dataList}" onRowDoubleClick="" renderToolBar="false">
       <xvw:columnAttribute width="150" dataField="title"/>

As an exercise, do the same to the LIB_Author edit viewer (i.e. add a tab with all books that that author has ever published). You'll need to do exactly the same as in the publisher's viewer, but the XEOQL expression is a little different.

Custom rendering of columns

Very often you'd like to make a custom render for a given column, instead of just presenting its value. The xvw:columnAttribute component which is used in gridPanels, list and bridges has precisely a property that lets you create your own custom render. For this example you'll take the list viewer of LIB_Book and change of state column so that instead of the state being the label "Available" / "Unavailable" it will display a small icon representing each state.

The first step is creating a new Java bean, based on the XEOBaseList (to replace the one in the LIB_Book list viewer), name it LibBookListBean and make it extend the netgest.bo.xwc.xeo.beans.XEOBaseList bean (create it in the org.example.viewer.beans package). Open the LIB_Book list viewer and replace the beanClass property with org.example.viewer.beans.LibBookListBean. Next you'll need the icons representing the state of the book, you can use the two following icons ( book_add.png book_delete.png ) and save them as "book_available.png" and "book_unavailable.png" in the webapps/default/Extras/Icons folder (you can use any other icon you'd like).

Open the LibBookListBean and create the following method:

public GridColumnRenderer getMyRenderer() { }

The GridColumnRenderer is an interface that ColumnAttribute components accept in order to change the renderer of its value. The GridColumnRenderer interface has a single method definition which is:

public String render(GridPanel grid, DataRecordConnector record, DataFieldConnector field)

The render method will return the value to be displayed on a given column (for each row), it returns a string which can be HTML code (allows you to display images, tables, or anything html provides). This method will be called once for every line in the corresponding gridPanel/list/bridge component for the given column where the renderer is being applied.

The render method receives three parameters. The GridPanel (could be a List or Bridge component, because both extend from GridPanel) where the column attribute is placed, a DataRecordConnector instance and a DataFieldConnector instance. A DataRecordConnector is an interface representing a specific line in a list of elements. You used the DataListConnector interface before to display the list of books of a publisher; each of those books in a DataListConnector is represented by a DataRecordConnector. The DataFieldConnector is yet another interface which is tied to the DataListConnector and DataRecordConnector because it represents the value (and metadata) of a given column within a single line.

In order to complete this custom renderer, change the LIB_Book list viewer to the following:

            <xeo:list enableGroupBy='true'>
                    <xvw:columnAttribute width="100" dataField="title" groupable='true'/>
                    <xvw:columnAttribute width="20" dataField='state' renderer='#{viewBean.myRenderer}'/>
                    <xvw:columnAttribute width="100" dataField="publisher"/>
                    <xvw:columnAttribute width="100" dataField="edition"/>
                    <xvw:columnAttribute width="100" dataField="authors"/>
                    <xvw:columnAttribute width="100" dataField="isbn"/>

Now go back to the bean and type/paste the following (inside the getMyRenderer method):

return new GridColumnRenderer() {
   public String render(WebXEO.GridPanel grid, DataRecordConnector record, DataFieldConnector field) {
      String state = field.getValue().toString(); //Retrieve the value of state lov
            return "<img src='Extras/Icons/book_add.png' title='Available'/>";
            return "<img src='Extras/Icons/book_delete.png' title='Unavailable'/>";

If you recall from the LIB_Book Modeling phase, the state attribute was connected to a XEO Lov, which had two values, "0" for Available and "1" for Available. You'll only have to check what's the value of the state attribute and return an HTML string with the link to the image (as depicted in the previous code). Save the bean, launch the project and go the list of books, the result should now be like the one depicted in figure XWCIA.2, bellow.


Figure XWCIA.2 - List viewer with custom renderer for a column


In the next chapter you'll learn how to create a more complex viewer, for the Movement Model.

Topic attachments
I Attachment Action Size Date Who Comment
PNGpng LibBookListCustomRenderer.png manage 9.5 K 2011-01-21 - 11:37 PedroRio  
PNGpng LibPublisherBooks.png manage 16.3 K 2011-01-20 - 15:43 PedroRio  
PNGpng book_add.png manage 0.7 K 2011-01-21 - 09:34 PedroRio  
PNGpng book_delete.png manage 0.7 K 2011-01-21 - 09:34 PedroRio  
Topic revision: r10 - 2011-04-04 - NicolauGrosskopf

No permission to view TWiki.WebTopBar

This site is powered by the TWiki collaboration platform Powered by Perl

No permission to view TWiki.WebBottomBar