How to create client side callout onchange function

From InfiniteERP Wiki
Jump to: navigation, search

Objective

The objective of this article is to show you how to create a new callout. A callout is a piece of Javascript code associated with a particular field on a tab. This code is executed whenever the field changes. It is a type of Ajax substitute, changing parts of a tab/window without the need of refreshing it.

It works by calling the FIC when a field with an associated callout is changed. The FIC (Form Initialization Component) refreshes the needed fields based on the callout logic.

This how-to will implement the following new functionality: When entering a new product, one has the option of entering the Search Key for the product, the Name and the Category it belongs to. But what if our client wants the search key to be constructed automatically by taking the product's name, removing all spaces, appending the underscore (_) and the category name it belongs to.

For example, this way the Search Key of a product that has the Name Bon Fountain and belongs to the Water Product Category would become BonFountain_Water. Let's see how this could be done using a callout.

The steps involved in creating a new callout are:

  1. Create the source file(s) of the callout (usually a java file).
  2. Define the new callout within the application dictionary (menu Application Dictionary > Setup > Callout).
  3. Associate this callout with a table column (Application Dictionary > Table and Column: Callout field withinin Column tab).
  4. Compile the window/tab(s) where this Column is used.

IMPORTANT NOTE: Developments related to points (1) and (2) must belong to a module that is not the core module. Please follow the How to create and package a module section to create a new module. For the development related to point (3) about modifying a core located column, a new template is needed. You can read the How to change an existing Window article to obtain more information.

Bulbgraph.png   This article assumes you have created both module and template according to the howtos just mentioned.


Creating the Callout Servlet

Existing callouts are located in src/org/openbravo/erpCommon/ad_callouts.

The right way to create a callout is by extending the SimpleCallout class. This class simplify the callout code, hide some of the internals of the callout and keep you focused on the operations required. To access database data DAL is used.

Theory

To develop a new callout based on this class you only have to create a new java class that extends SimpleCallout and overwrite the following method:

<source lang="java"> protected void execute(CalloutInfo info) throws ServletException; </source>

In this method you can develop the logic of the callout and use the info object of class CalloutInfo to access window fields, database and other methods. The most important are:

  • public String getStringParameter(String param, RequestFilter filter) : Returns the value of a field named param as an String using the filter to accept values.
  • public BigDecimal getBigDecimalParameter(String param) throws ServletException : This method returns the value of of a field named param as a BigDecimal.
  • public void addResult(String param, String value) : This method sets the value of a field named param with the String value indicated.
  • public void addResult(String param, Object value) : This method sets the value of a field named param with the value indicated. This method is useful to set numbers like BigDecimal objects.
  • public void addSelect(String param) : Starts the inclusion of values of a field named param of type select.
  • public void addSelectResult(String name, String value) : Adds an entry to the select field and marks it as unselected.
  • public void addSelectResult(String name, String value, boolean selected) : Adds an entry to the select field.
  • public void endSelect() : Finish the inclusion of values to the select field.
  • protected void showMessage(String value) : Shows a message in the browser with the value indicated.
  • protected void showError(String value) : Shows an error message in the browser with the value indicated.
  • protected void showWarning(String value) : Shows a warning message in the browser with the value indicated.
  • protected void showInformation(String value) : Shows an information message in the browser with the value indicated.
  • protected void showSuccess(String value) : Shows a success message in the browser with the value indicated.
  • protected void executeCodeInBrowser(String value) : Executes the javascript code indicated in the value in the browser.
  • public String getLastFieldChanged() : Returns the name of field that triggered the callout.
  • public String getTabId() : Returns the Tab Id that triggered the callout.
  • public String getWindowId() : Returns the Window Id that triggered the callout.
  • public VariablesSecureApp vars : This instance field contains the VariablesSecureApp associated to the callout servlet.

It is important to keep coherence with each expected data type (String, BigDecimal, ...)

See the following class as an example of a class that currently uses SimpleCallout: SL_Project_Service. This callout simply takes the numeric value of two fields, calculates the sum and writes it into another field. This is the interesting part of the code that performs the logic:

<source lang="java"> @Override

protected void execute(CalloutInfo info) throws ServletException { 

    BigDecimal serviceSerCost = info.getBigDecimalParameter("inpservsercost");
    BigDecimal serviceOutCost = info.getBigDecimalParameter("inpservoutcost"); 

    BigDecimal serviceTotalCost = serviceSerCost.add(serviceOutCost);

    info.addResult("inpservcost", serviceTotalCost);
}

</source>

Extend a Callout

It is possible to implement a callout that extends from another callout. For more information visit this How to create a callout that extends from another callout tutorial.

Bulbgraph.png   This feature is available from version 3.0PR16Q4

Product Search Key Calculation using SimpleCallout

Let's define the tasks that need to be performed by the callout:

  1. Retrieve the name of the product as entered by the user
  2. Retrieve the ID of the category selected from a dropdown by the user
  3. Get the name of the product category inside the database using the product category ID retrieved
  4. Strip spaces out of the product and category names
  5. Construct the Search Key

<source lang="java">// the package name corresponds to the module's manual code folder // created above package org.openbravo.howtos.ad_callouts;

import javax.servlet.ServletException;

import org.openbravo.utils.FormatUtilities; import org.openbravo.erpCommon.ad_callouts.SimpleCallout; import org.openbravo.base.secureApp.VariablesSecureApp; // classes required to retrieve product category data from the // database using the DAL import org.openbravo.dal.service.OBDal; import org.openbravo.model.common.plm.ProductCategory;

// the name of the class corresponds to the filename that holds it // hence, modules/modules/org.openbravo.howtos/src/org/openbravo/howtos/ad_callouts/ProductConstructSearchKey.java. // The class must extend SimpleCallout public class ProductConstructSearchKey extends SimpleCallout {

 private static final long serialVersionUID = 1L;
 @Override
 protected void execute(CalloutInfo info) throws ServletException {
   // parse input parameters here; the names derive from the column
   // names of the table prepended by inp and stripped of all
   // underscore characters; letters following the underscore character
   // are capitalized; this way a database column named
   // M_PRODUCT_CATEGORY_ID that is shown on a tab will become
   // inpmProductCategoryId html field
   String strProductName = info.getStringParameter("inpname", null);
   String strProductCategoryId = info
                   .getStringParameter("inpmProductCategoryId", null);
   // inject the result into the response
   info.addResult("inpvalue", getConstructedKey(info.vars, strProductName, strProductCategoryId));
 }
 protected String getConstructedKey(VariablesSecureApp vars,
       String strProductName, String strProductCategoryId) {
   // Retrieve the product category name
   final ProductCategory productCategory = OBDal.getInstance().get(ProductCategory.class,
           strProductCategoryId);
   String strProductCategoryName = productCategory.getName();
   // construct full key
   String generatedSearchKey = FormatUtilities.replaceJS(strProductName
               .replaceAll(" ", ""))
               + "_" + strProductCategoryName.replaceAll(" ", "");
   // return generated key
   return generatedSearchKey;
 }

} </source>

Defining the Callout within the Application Dictionary

NOTE: You need to have ONLY your module as "In Development" at this stage.

Using the role System Administrator navigate to Application Dictionary || Setup || Callout. Create a new record as indicated by the screenshot below:

Bulbgraph.png  

The name of the callout should not have spaces or illegal javascript characters.


Save and navigate to the Callout Class tab of the same window. You will notice that the Java Class Name was automatically generated for you, however, not correctly since the name could not match the Callout name you have provided. Correct it in line with your callout package/class name. See screenshot below:



Now Openbravo knows that a callout exists and is implemented by the class you have just specified.

Bulbgraph.png  

Remember to perform

ant export.database

in order to persist your changes in your module.

Associating the Callout with a Column

NOTE: You need to have ONLY your template as "In Development" at this stage.

Using the role System Administrator navigate to Application Dictionary || Tables and Columns and find the M_Product DB Table. This is the underlying table of the main tab of the Product window.

Go to Column tab, find the Name record and edit it. Find the Callout dropdown that should at this point be empty. Select our Product_Construct_SearchKey callout and save the record:



Do the same for the Product Category record since a change in any of them should also regenerate the Search Key.

Bulbgraph.png  

Remember to perform

ant export.database

and

ant export.config.script

in order to persist your changes in your template.

Compiling the Window

Finally, for the callout to take effect, the window that uses it needs to be recompiled and deployed to Tomcat. If using Eclipse, use the eclipse.compile ant task and enter Product into the dialog that pops up. If manually compiling Openbravo, use the

ant smartbuild 

or

ant compile.development -Dtab=Product

IMPORTANT NOTE: once the compilation has finished, restart Apache Tomcat server.

See more on Build Tasks.

Now it is time to test the result!


The Result

Using the role Openbravo Admin (or your defined 'administrator' role), navigate to the Master Data Management || Product window. Enter a new product with Name = Bon Fountain and leave the Name field. Notice how the Search Key changes. Then, change the Product Category to something else and see how the change is reflected inside the Search Key field.



Save.

You have now successfully created your first new callout and seen how it came to life within Openbravo ERP. Congratulations!