Creating a Widget with Google Web Toolkit and opentaps

From Opentaps Wiki

Jump to: navigation, search

This tutorial shows you how to create a widget with the Google Web Toolkit (GWT) for opentaps. In opentaps, we have already implemented common user interface components, such as screenlets, form fields, auto completion, and lists, based on GWT-Ext, which is an open source library that extends the standard GWT. This tutorial will show you how to build a widget using these opentaps GWT components, put them on your applicaiton's screens, and link them to the business logic tier in the back end.

Contents

Our Example

For this tutorial, we will be replacing an existing "screenlet" with a GWT widget. The screenlet we will be replacing is "New Case" under the CRMSFA > Cases tab:

Image:Original-new-case.png

Currently, this screen lead is a small HTML form which posts to the server to create a case in the CRM system. We will be replacing it with a GWT widget so that our user can create new cases without each time waiting for the server to refresh the entire screen.

Setting up the Files

The first step is to set up your files. In opentaps, the commonly used GWT base classes, components, and widgets are located in hot-deploy/opentaps-common/src/common/org/opentaps/gwt Each application then has its own GWT widgets, located in directories such as hot-deploy/crmsfa/src/org/opentaps/gwt/crmsfa, and these widgets are built when that application is built. Inside of this directory, you will find subdirectories for the accounts, contacts, leads, orders, and partners widgets.

Because there are currently no cases widgets, the first thing we would need to create is the subdirectory for cases: a new hot-deploy/crmsfa/src/org/opentaps/gwt/crmsfa/cases<tt>. Here, we put the <tt>cases.gwt.xml file, which is a configuration file for GWT:

<module>
  <source path="client"/>
  <inherits name='org.opentaps.gwt.common.common'/>
  <entry-point class='org.opentaps.gwt.crmsfa.cases.client.Entry'/>
</module>

This file tells GWT that we will be inheriting from org.opentaps.gwt.common.common, and it identifies the Java class which is the entry point for the widgets related to cases. Happily, this is the only XML configuration file we would need for our GWT widget. The rest of the widget is written in Java.

The next thing is to add the cases widget to the build path for your application. You can do this by editing hot-deploy/crmsfa/build.xml and adding cases to the list of gwt modules:

 <property name="gwt.module.list" value="contacts,accounts,leads,partners,orders,cases"/>

Now we are ready to get started with our widget.

Creating the Widget

The first step is to create the entry point for all the cases widgets by creating a file called hot-deploy/crmsfa/src/org/opentaps/gwt/crmsfa/cases/client/Entry.java. This file is used to load up GWT:

import org.opentaps.gwt.common.client.BaseEntry;

public class Entry extends BaseEntry {

    private static final String QUICK_CREATE_CASE_ID = "quickNewCase";
    private QuickNewCaseForm quickNewCaseForm = null;

    public void onModuleLoad() {
        if (RootPanel.get(QUICK_CREATE_CASE_ID) != null) {
                loadQuickNewCase();
        }
    }

    private void loadQuickNewCase() {
        quickNewCaseForm = new QuickNewCaseForm();
        RootPanel.get(QUICK_CREATE_CASE_ID).add(quickNewCaseForm);
    }
}

What this class does is define where the quick new case widget would appear on your screen by referencing the id of a div tag. The value of the div tag's id is defined here:

private static final String QUICK_CREATE_CASE_ID = "quickNewCase";

Then, the onModuleLoad, which is run every time this widget is activated, will check if the RootPanel, or the web page, contains a div with this tag:

public void onModuleLoad() {
   	if (RootPanel.get(QUICK_CREATE_CASE_ID) != null) {

If it does, then it will call loadQuickNewCase, which instantiates and loads the quick new case form on to the RootPanel, or web page, inside of this div:

  quickNewCaseForm = new QuickNewCaseForm();
  RootPanel.get(QUICK_CREATE_CASE_ID).add(quickNewCaseForm);

Now we can create QuickNewCaseForm and QuickNewCaseConfiguration. QuickNewCaseForm is the actual form which does the work:

  public QuickNewCaseForm() extends ScreenletFormPanel {

        // label at the top
        super(Position.TOP, UtilUi.MSG.crmNewCase());

        // the URL, linked to opentaps controller
        setUrl(QuickNewCaseConfiguration.URL);

        // subject is a required text input field 
        subjectInput = new TextField(UtilUi.MSG.opentapsSubject(), QuickNewCaseConfiguration.SUBJECT, INPUT_LENGTH);
        addRequiredField(subjectInput);

        // this parameter is required for the crmsfa.createCase service
        addField(new Hidden(QuickNewCaseConfiguration.CASE_TYPE_ID, QuickNewCaseConfiguration.DEFAULT_CASE_TYPE_ID));
        // this is not required, but we're setting it to a default value for completeness
        addField(new Hidden(QuickNewCaseConfiguration.PRIORITY, QuickNewCaseConfiguration.DEFAULT_PRIORITY));

        // account is a required field and will be the account autocomplete
        accountNameInput = new AccountAutocomplete(UtilUi.MSG.account(), QuickNewCaseConfiguration.ACCOUNT_PARTY_ID, INPUT_LENGTH);
        addRequiredField(accountNameInput);

        // add the button with ui label
        addStandardSubmitButton(UtilUi.MSG.crmCreateCase());
    }

This form extends the base ScreenletFormPanel, which is a common GWT widget in opentaps. It sets the CSS style, title, and collapsibility of the screenlet. The ScreenletFormPanel extends an even more basic BaseFormPanel, which handles such things as the behavior of the form fields and buttons of the form, so you can put together your form without worrying about these low level details.

The features of this GWT form are:

  • The UI labels are available through UtilUi.MSG. These are automatically generated from opentaps UI labels. For example, UtilUi.MSG.crmCreateCase() is CrmCreateCase
  • The call to the super method sets the label at the top of the widget.
  • setUrl sets the URL for the widget
  • addRequiredField and addField add required and non-required fields to the form. Required fields are highlighted in red, and one of the good things about GWT is that it will validate the values on the client side, in the browser, so you don't have to click on the submit button, wait, and then be told you forgot to enter a required value.
  • TextField and Hidden are GWT-Ext form fields
  • AccountAutocomplete<tt> is an opentaps auto completion field for accounts.
  • <tt>addStandardSubmitButton adds a submit button with the specified UI label.

QuickNewCaseConfiguration is used to hold the literal values on the QuickNewCaseForm, such as the names of the fields, URL, and default values. They could be strings in QuickNewCaseForm as well, but by separating them, we are making it more configurable.

Putting it on the Screen

To load the GWT widget on the opentaps screen, add it to the list of GWT scripts for your screen. This is done by modifying the screen widget XML definition in hot-deploy/crmsfa/widget/crmsfa/screens/cases/CasesScreens.xml and adding our GWT widget to the main decorator, which causes it to show up for all the case screens:

   <screen name="main-section-decorator">
       <section>
           <actions>
               <set field="gwtScripts[]" value="crmsfagwt/org.opentaps.gwt.crmsfa.cases.cases" global="true"/>
               <set field="sectionName" value="cases" global="true"/>

Next, link your Entry.java to opentaps page by modifying hot-deploy/crmsfa/webapp/crmsfa/cases/screenlets/quickCreateCase.ftl and adding:

<@gwtWidget id="quickNewCase"/>

This creates a div your HTML page with the ID quickNewCase, which is exactly what our Entry.java above used to load the quick new case widget.

Linking it to the Services

Linking front end GWT widgets to your back end business logic is surprisingly easy: opentaps has a special event handler, gwtservice service, which you can use in your controller, like this:

     <request-map uri="gwtQuickNewCase">
       <security https="true" auth="true"/>
       <event type="gwtservice" invoke="crmsfa.createCase"/>
       <response name="success" type="none"/>
       <response name="error" type="none"/>
   </request-map>

It will automatically parse the request parameters and call the service through the service engine. It will pass the results or error messages back to your GWT widgets with JSON, so you do not need any response page. Hence, the response type for both success and error can be none

All Done

And that's it. Here's what the new widget looks like:

Image:New-new-case.png

Note the auto completion for the account field. Now, if you fill in the account and then try to submit without filling in the subject, you will simply get a red exclamation mark in your widget telling you to fill in that field. This was done completely in your browser, so it's much faster for your user than waiting for a response from your server:

Image:New-new-case-validation.png

When you fill out both fields and click on [Create Case], you'll see a spinner while the widget is talking to the opentaps server:

Image:New-case-spinning.png

When it's done, it'll return to normal, without affecting the rest of the screen.



© Open Source Strategies, Inc. Development of this documentation site is sponsored by Open Source Strategies, Inc.
Help support opentaps with a subscription to this documentation site.