Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

6.) Run your ofbiz demo application and go to the new tab you just added. You should have view as:viewed as:


Image Added

Creating Custom Decorator

Having your UI in Freemarker gives you freedom to experiment it, doing CSS tweaks and make your application the way user wants. In this section we will see how we can do that.

We will be doing it by defining custom decorator for your application view. A decorator in OFBiz is nothing but a screen that you define and reuse afterwards by including in your other screens of application. You are already doing it with default decorator (main-decorator –> ApplicationDecorator) which comes with OFBiz. Just observe your screens you have prepared so far, you will find that, you were using this main decorator, please refer below line in OfbizDemoScreens.xml.

OfbizDemoScreens.xml


<decorator-screen name="main-decorator" location="${parameters.mainDecoratorLocation}">


Info

The mainDecoratorLocation is available in parameters map as it is defined in webapp's web.xml

web.xml


<context-param>
    <description>The location of the main-decorator screen to use for this webapp; referred to as a context variable in screen def XML files.</description>
    <param-name>mainDecoratorLocation</param-name>
    <param-value>component://ofbizDemo/widget/CommonScreens.xml</param-value>
</context-param>


Now is the time to define your own decorator with custom styling. 

In the sample given below we are going to use Bootstrap to style our sample Freemarker screen we developed in last part of this tutorial. Follow below given steps to build your own decorator.

1.) Download Bootstrap v3.3.7 directory, you can download it from here and unzip it.

2.) Create two new directories namely "css" and "js" at location $ OFBIZ_HOME/plugins/ofbizDemo/webapp/ofbizDemo/

3.) Copy bootstrap-3.3.7/dist/css/bootstrap.min.css to $ OFBIZ_HOME/plugins/ofbizDemo/webapp/ofbizDemo/css

4.) Copy bootstrap-3.3.7/dist/js/bootstrap.min.js to $ OFBIZ_HOME/plugins/ofbizDemo/webapp/ofbizDemo/js.

5.) Open $ OFBIZ_HOME/plugins/ofbizDemo/webapp/ofbizDemo/WEB-INF/web.xml and make entries for css and js directories in allowedPaths at the end as shown below:

web.xml


<init-param>
    <param-name>allowedPaths</param-name>
    <param-value>/error:/control:/select:/index.html:/index.jsp:/default.html:/default.jsp:/images:/includes/maincss.css:/css:/js</param-value>
</init-param>


6.) Add new directory named "includes" at location $ OFBIZ_HOME/plugins/ofbizDemo/webapp/ofbizDemo/ and create two new files in this new directory you just added named PreBody.ftl and PostBody.ftl. We will be using(including) these two files in our decorator screen to build complete HTML page.


PreBody.ftl


<html>
  <head>
    <title>${layoutSettings.companyName}</title>
    <meta name="viewport" content="width=device-width, user-scalable=no"/>
    <#if webSiteFaviconContent?has_content>
      <link rel="shortcut icon" href="">
    </#if>
    <#list layoutSettings.styleSheets as styleSheet>
      <link rel="stylesheet" href="${StringUtil.wrapString(styleSheet)}" type="text/css"/>
    </#list>
    <#list layoutSettings.javaScripts as javaScript>
      <script type="text/javascript" src="${StringUtil.wrapString(javaScript)}"></script>
    </#list>
  </head>
  <body data-offset="125">
    <h4 align="center"> ==================Page PreBody Starts From Decorator Screen========================= </h4>
    <div class="container menus" id="container">
      <div class="row">
        <div class="col-sm-12">
          <ul id="page-title" class="breadcrumb">
            <li>
                <a href="<@ofbizUrl>main</@ofbizUrl>">Main</a>
            </li>
            <li class="active"><span class="flipper-title">${StringUtil.wrapString(uiLabelMap[titleProperty])}</span></li>
            <li class="pull-right">
              <a href="<@ofbizUrl>logout</@ofbizUrl>" title="${uiLabelMap.CommonLogout}">logout</i></a>
            </li>
          </ul>
        </div>
      </div>
      <div class="row">
        <div class="col-lg-12 header-col">
          <div id="main-content">
              <h4 align="center"> ==================Page PreBody Ends From Decorator Screen=========================</h4>
              <h4 align="center"> ==================Page Body starts From Screen=========================</h4>


PostBody.ftl


<#-- Close the tags opened in the PreBody section -->
          </div>
        </div>
      </div>
    </div>
    <h4 align="center"> ==================Page PostBody and Page body in general ends here from Decorator Screen=========================</h4>
  </body>
</html>


7.) Open Common Screens file of your component $ OFBIZ_HOME/plugins/ofbizDemo/widget/CommonScreens.xml, this is the file we will define our custom decorator.

8.) Update screen named "OfbizDemoCommonDecorator"(which will serve as custom decorator for your app) as shown below:

CommonScreens.xml


<screen name="OfbizDemoCommonDecorator">
    <section>
        <actions>
            <property-map resource="OfbizDemoUiLabels" map-name="uiLabelMap" global="true"/>
            <property-map resource="CommonUiLabels" map-name="uiLabelMap" global="true"/>
   
<set field="layoutSettings.companyName" from-field="uiLabelMap.OfbizDemoCompanyName" global="true"/>
            
<!-- Including custom CSS Styles that you want to use in your application view. [] in field can be used to
                 set the order of loading CSS files to load if there are multiple -->
            <set field="layoutSettings.styleSheets[]" value="/ofbizDemo/css/bootstrap.min.css"/>
   
            <!-- Including custom JS that you want to use in your application view. [] in field can be used to
                 set the order of loading of JS files to load if there are multiple -->
           <set field="layoutSettings.javaScripts[+0]" value="/ofbizDemo/js/bootstrap.min.js" global="true"/>
        </actions>
        <widgets>
            <section>
                <condition>
                    <if-has-permission permission="OFBIZDEMO" action="_VIEW"/>
                </condition>
                <widgets>
                    <platform-specific><html><html-template location="component://ofbizDemo/webapp/ofbizDemo/includes/PreBody.ftl"/></html></platform-specific>
                    <decorator-section-include name="pre-body"/>
                    <decorator-section-include name="body"/>
                    <platform-specific><html><html-template location="component://ofbizDemo/webapp/ofbizDemo/includes/PostBody.ftl"/></html></platform-specific>
                </widgets>
                <fail-widgets>
                    <label style="h3">${uiLabelMap.OfbizDemoViewPermissionError}</label>
                </fail-widgets>
            </section>
        </widgets>
    </section>
</screen>


In the code above you may have noticed the layoutSettings.styleSheets[] and layoutSettings.javaScripts[+0] notations. You can use the layoutSettings. notation for any files.

If you want to order styleSheets or javaScripts with empty square brackets you simply add the file at the end of the layoutSettings.styleSheets or layoutSettings.javaScripts list, with [+0] you add it at front of it.


9.) Use this decorator in your Freemarker screen that you created in last part as:

OfbizDemoScreens.xml


<screen name="AddOfbizDemoFtl">
    <section>
        <actions>
            <set field="titleProperty" value="OfbizDemoAddOfbizDemoFtl"/>
            <set field="headerItem" value="addOfbizDemoFtl"/>
            <script location="component://ofbizDemo/webapp/ofbizDemo/WEB-INF/actions/crud/ListOfbizDemo.groovy"/>
        </actions>
        <widgets>
            <decorator-screen name="OfbizDemoCommonDecorator" location="${parameters.mainDecoratorLocation}">
                <decorator-section name="body">
                     <label style="h4" text="${uiLabelMap.OfbizDemoListOfbizDemos}"/>
                     <platform-specific>
                         <html><html-template location="component://ofbizDemo/webapp/ofbizDemo/crud/ListOfbizDemo.ftl"/></html>
                     </platform-specific>
                     <label style="h4" text="${uiLabelMap.OfbizDemoAddOfbizDemoFtl}"/>
                     <platform-specific>
                         <html><html-template location="component://ofbizDemo/webapp/ofbizDemo/crud/AddOfbizDemo.ftl"/></html>
                     </platform-specific>
                </decorator-section>
            </decorator-screen>
        </widgets>
    </section>
</screen>


10.) Update your FTL files to follow HTML web standards and apply CSS on it as:

AddOfbizDemo.ftl


 <form method="post" action="<@ofbizUrl>createOfbizDemoEventFtl</@ofbizUrl>" name="createOfbizDemoEvent" class="form-horizontal">
  <div class="control-group">
    <label class="control-label" for="ofbizDemoTypeId">${uiLabelMap.OfbizDemoType}</label>
    <div class="controls">
      <select id="ofbizDemoTypeId" name="ofbizDemoTypeId">
        <#list ofbizDemoTypes as demoType>
          <option value='${demoType.ofbizDemoTypeId}'>${demoType.description}</option>
        </#list>
      </select>
    </div>
  </div>
  <div class="control-group">
    <label class="control-label" for="firstName">${uiLabelMap.OfbizDemoFirstName}</label>
    <div class="controls">
      <input type="text" id="firstName" name="firstName" required>
    </div>
  </div>
  <div class="control-group">
    <label class="control-label" for="lastName">${uiLabelMap.OfbizDemoLastName}</label>
    <div class="controls">
      <input type="text" id="lastName" name="lastName" required>
    </div>
  </div>
  <div class="control-group">
    <label class="control-label" for="comments">${uiLabelMap.OfbizDemoComment}</label>
    <div class="controls">
      <input type="text" id="comments" name="comments">
    </div>
  </div>
  <div class="control-group">
    <div class="controls">
      <button type="submit" class="btn">${uiLabelMap.CommonAdd}</button>
    </div>
  </div>
</form>


ListOfbizDemo.ftl


<table class="table table-bordered table-striped table-hover">
    <thead>
        <tr>
          <th>${uiLabelMap.OfbizDemoId}</th>
          <th>${uiLabelMap.OfbizDemoType}</th>
          <th>${uiLabelMap.OfbizDemoFirstName}</th>
          <th>${uiLabelMap.OfbizDemoLastName}</th>
          <th>${uiLabelMap.OfbizDemoComment}</th>
        </tr>
    </thead>
    <tbody>
        <#list ofbizDemoList as ofbizDemo>
            <tr>
              <td>${ofbizDemo.ofbizDemoId}</td>
              <td>${ofbizDemo.getRelatedOne("OfbizDemoType").get("description", locale)}</td>
              <td>${ofbizDemo.firstName?default("NA")}</td>
              <td>${ofbizDemo.lastName?default("NA")}</td>
              <td>${ofbizDemo.comments!}</td>
            </tr>
        </#list>
    </tbody>
</table


10. Now restart OFBiz as you have made entries to allowedPaths in web.xml. As it reloads hit https://localhost:8443/ofbizDemo/control/AddOfbizDemoFtl you should see page with custom styles that you have used instead of using default OFBiz theme. It should look like:

Image Added

Here you can now play with it as you want. Try changing header or having new one, adding footer, putting in validations etc. So this way you can customize UI layer of OFBiz with Freemarker templates, CSS and JS.

You may want to add your own CSS or JS files, you can include those the same way we did for Bootstrap files.

Whats next?

If you have followed all the steps and developed practice application from this tutorial then this will help you in understanding other implementation in OFBiz. These things are basic foundation of working in OFBiz. Now you know, how you can start development in OFBiz. Don't leave behind the extra links provided in this tutorial as they will help you a lot in understanding the things which are given there in detail.
Here is another good reading can be of help is available at FAQ Tips Tricks Cookbook HowTo.
Now the next thing comes in the way is the business processes which are really needed to be understood well for understanding OOTB process flow in OFBiz and OOTB data model, so for this, books are available at : OFBiz Related Books. Understanding well the OFBiz OOTB available data model and business processes will help in building better business solutions top of it.

Now you are ready to dive in. Welcome to OFBiz world.