In this post we will create our OFBiz product list screen. First, a simple html screen to print on screen all the products in our system.
This exercise is based on the “hwm” component we have setup in the last blog post OFBiz Tutorial – Custom Components In OFBiz: all the code we will implement will be contained in the custom component.
Here are the steps required to build the new screen:
All the steps we will do doesn’t require to compile/build OFBiz and can be done while OFBiz is running; in this way you will be able to test the effects of your experiments immediately.
A form widget definition is an xml representation of a list or single form.
In OFBiz, the main entity (aka database table) for storing product related information is named “Product”.
Here is the code to define a form of “list” type, together with the code to retrieve all the records from the Product entity and display them in a list based format:
<form name="ListProducts" type="list"> <actions> <entity-condition entity-name="Product"> <order-by field-name="productId"/> </entity-condition> </actions> <auto-fields-entity entity-name="Product" default-field-type="display"/> </form>
things to consider:
A screen widget definition is an xml representation of a screen (page) in the application.
Here is the code to define a new screen that contains the form defined in the above step:
<section> <actions> </actions> <widgets> <decorator-screen name="HwmCommonDecorator" location="component://hwm/widget/CommonScreens.xml"> <decorator-section name="body"> <include-form name="ListProducts" location="component://hwm/widget/HwmForms.xml"/> </decorator-section> </decorator-screen> </widgets> </section> </screen>
Things to consider:
Controller entries are needed to define the URL to reach the screen; for each screen you have to create two entries, a request-map and a view-map:
<request-map uri="ProductList"> <security https="true" auth="true"/> <response name="success" type="view" value="ProductListScreen"/> </request-map> ... <view-map name="ProductListScreen" type="screen" page="component://hwm/widget/HwmScreens.xml#ProductList"/>
Things to consider:
If you have followed all the steps above you are now ready to test your work; no need to compile or restart OFBiz, just enter the following URL in your browser: https://localhost:8080/hwm/control/ProductList
You should see a screen like this: (Click on image to zoom)
Things to consider:
Again, you can do all these changes without restarting OFBiz: just do them and reload the page after each and every change, this is a great way to explore the different options available.
The products are now sorted by productId in ascending order; if we want to sort them in descending order we just have to add the “-” symbol as a prefix of the field name in the “order-by” element of the “entity-condition”:
<entity-condition entity-name="Product"> <order-by field-name="-productId"/> </entity-condition>
if we want to sort by productTypeId and then productId:
<entity-condition entity-name="Product"> <order-by field-name="productTypeId"/> <order-by field-name="productId"/> </entity-condition>
If we want instead to filter all the product of type “finished good” and sort the result by productId:
<entity-condition entity-name="Product"> <condition-expr field-name="productTypeId" value="FINISHED_GOOD"/> <order-by field-name="productId"/> </entity-condition>
We can now add a label to the screen to explain that these are all the “finished products” in the system; in order to do this you will add a “label” element to the screen definition (see line 8):
<screen name="ProductList"> <section> <actions> </actions> <widgets> <decorator-screen name="HwmCommonDecorator" location="component://hwm/widget/CommonScreens.xml"> <decorator-section name="body"> <label text="Finished Products" style="h1"/> <include-form name="ListProducts" location="component://hwm/widget/HwmForms.xml"/> </decorator-section> </decorator-screen> </widgets> </section> </screen>
Instead of typing the URL of our screen in the browser we want to add a link to it from the top level menu of the “Hwm” application.
Here is the code to do this (new code at line 3):
<menu name="MainAppBar" title="${uiLabelMap.HwmApplication}" extends="CommonAppBarMenu" extends-resource="component://common/widget/CommonMenus.xml"> <menu-item name="main" title="${uiLabelMap.CommonMain}"><link target="main"/></menu-item> <menu-item name="ProductList" title="Product List"><link target="ProductList"/></menu-item> </menu>
Things to consider:
In the last two paragraphs we have added two textual labels in English, one as a “label” element in the screen and the other as the “title” of the menu item. A better way of doing this, especially if you are interested in building internationalized applications that can be translated in many different languages, is to use the OFBiz i18n layer. In order to do this you have to add the following key in the component’s UiLabel file:
<property key="HwmProductList"> <value xml:lang="en">Product List</value> <value xml:lang="it">Lista Prodotti</value> </property>
and then use the key instead of the hardcoded “Product List” string; for example for the menu item the code is:
<menu-item name="ProductList" title="${uiLabelMap. HwmProductList}"><link target="ProductList"/></menu-item>
We have mentioned before that the data preparation code can stay in the form’s actions section or in the screen’s actions section; in the first paragraph of this post we have implemented the code in the form; we now move it to the screen’s actions section:
<screen name="ProductList"> <section> <actions> <entity-condition entity-name="Product" list="products"> <order-by field-name="productId"/> </entity-condition> </actions> <widgets> <decorator-screen name="HwmCommonDecorator" location="component://hwm/widget/CommonScreens.xml"> <decorator-section name="body"> <label text="Finished Products" style="h1"/> <include-form name="ListProducts" location="component://hwm/widget/HwmForms.xml"/> </decorator-section> </decorator-screen> </widgets> </section> </screen>
The entity-condition code is exactly the same with the only difference that now we have specified the “list” attribute: this is important because it represents the name of the variable that will contain the list of products selected; this name must match the same list-name attribute in the form definition that is now:
<form name="ListProducts" type="list" list-name="products"> <actions> </actions> <auto-fields-entity entity-name="Product" default-field-type="display"/> </form>
The “actions” section in the form is now empty and can be safely removed.
Now that we have the data preparation code in the screen, we can more easily implement an additional screen, that reuses the same form definition to list all the products of type “raw material” (productTypeId=”RAW_MATERIAL”): the implementation of the new screen, new controller entries, menu item, ui labels is a useful exercise.
In the next posts we will explore some of the features of form widgets (and we will enhance our product list form) and we will see how we can implement a PDF and CSV versions of the screen.
– Jacopo
HotWax Systems is the leading global innovator of Apache OFBiz. Stay tuned for more helpful tutorials.