View source | Discuss this page | Page history | Printable version   
Toolbox
Main Page
Upload file
What links here
Recent changes
Help

PDF Books
Add page
Show collection (0 pages)
Collections help

Search

How to add a button to the toolbar

Contents

Introduction

This howto discusses how a button can be added the main toolbar shown in grids and forms. The toolbar contains two types of buttons, the application buttons on the left (visualized using an icon) and the custom buttons on the right (shown with a label). This howto describes how to add a button to the left part, the application buttons.


Toolbar-before-howto-30.png


To follow this howto you need to be able to, at a junior level, develop javascript as well as server-side java and understand Data Access Layer concepts.

Example Module

This howto is supported by an example module which shows example of the code shown and discussed in this howto.

The code of the example module can be downloaded from this mercurial repository: https://code.openbravo.com/erp/mods/org.openbravo.client.application.examples/

The example module is available through the Central Repository (See 'Client Application Examples'), for more information see the Examples Client Application project page.

Bulbgraph.png   The example module also contains implementations of other howtos.

Implementing a toolbar button

Bulbgraph.png   When implementing your own components it often makes sense to extend existing components. Make sure that your module then depends on the module that provides the base types. This ensures that the javascript is loaded in the correct order. You must add a dependency from your module to the Openbravo 3.0 Framework (org.openbravo.v3.framework) module

The button which we will implement will compute and show the sum of a set of selected orders to the user. This howto is divided in 2 parts, the first part focuses on visualizing the button in the correct windows and tabs and making sure the button is enabled/disabled appropriately. The second part will discuss how to implement backend logic and how to call the server side logic when the button gets clicked and show its results.

The first part consists of the following steps:

These steps will visualize the button but not actually do anything yet. The follow up steps will add logic:

Each of these steps is described in more detail below.

Visualizing the button - Implementation steps

Defining the icon and a css

The icon and its related style is defined through an icon file. For standard visualization using the Openbravo style the icon should be 24x24 without a background colour.

The icon should be placed in a specific directory in your module: web/org.openbravo.userinterface.smartclient/openbravo/skins/Default/[modulename]. Normally it makes sense to store the icon in a subfolder. The example module has the icon file in: web/org.openbravo.userinterface.smartclient/openbravo/skins/Default/org.openbravo.client.application.examples/images.


Howto-toolbar-icon-file-30.png


Then add a css file which links this icon to a specific css style. The css file must also be located in this directory in your module: web/org.openbravo.userinterface.smartclient/openbravo/skins/Default/[modulename]. In the example module the css file is located here: web/org.openbravo.userinterface.smartclient/openbravo/skins/Default/org.openbravo.client.application.examples/ob-example-styles.css Within the css file add a style defined like this:

.OBToolbarIconButton_icon_obexapp_sum {
  background-repeat: no-repeat;
  background-position: center center;
  background-image: url(./images/iconButton-sum.png);
}

Note: the name of the css class is important, it should start with 'OBToolbarIconButton_icon_', the part after that (obexapp_sum) is used later in this tutorial. It makes sense to use the module's dbprefix in this last part to prevent name collisions with other modules.

The javascript to create and register the button

The next step is to implement the javascript which defines the button and registers it to be shown on tabs. Start by creating a javascript file in this location: web/org.openbravo.client.application.examples/js/example-toolbar-button.js. In the example module this file is present: web/org.openbravo.client.application.examples/js/example-toolbar-button.js.

This is the overall javascript:

(function () {
  var buttonProps = {
      action: function(){
        alert('You clicked me!');
      },
      buttonType: 'obexapp_sum',
      prompt: OB.I18N.getLabel('OBEXAPP_SumData'),
      updateState: function(){
          var view = this.view, form = view.viewForm, grid = view.viewGrid, selectedRecords = grid.getSelectedRecords();
          if (view.isShowingForm && form.isNew) {
            this.setDisabled(true);
          } else if (view.isEditingGrid && grid.getEditForm().isNew) {
            this.setDisabled(true);
          } else {
            this.setDisabled(selectedRecords.length === 0);
          }
      }
    };
  
  // register the button for the sales order tab
  // the first parameter is a unique identification so that one button can not be registered multiple times.
  OB.ToolbarRegistry.registerButton(buttonProps.buttonType, isc.OBToolbarIconButton, buttonProps, 100, '186');
}());

Let's walk through the different parts. The javascript starts and ends with this part:

(function () {
...
}());

This is done to prevent the local variables to be available globally, it creates a function and executes it immediately.

Then the first part of the buttonprops"

      action: function(){
        alert('You clicked me!');
      },
      buttonType: 'obexapp_sum',
      prompt: OB.I18N.getLabel('OBEXAPP_SumData'),
Howto-toolbar-prompt-message-file-30.png

The updateState function is called to enable and disable the button when the user navigates through the system.

     updateState: function(){
          var view = this.view, form = view.viewForm, grid = view.viewGrid, selectedRecords = grid.getSelectedRecords();
          if (view.isShowingForm && form.isNew) {
            this.setDisabled(true);
          } else if (view.isEditingGrid && grid.getEditForm().isNew) {
            this.setDisabled(true);
          } else {
            this.setDisabled(selectedRecords.length === 0);
          }
      }

The function enables/disables the button if the form or grid is new and if there are no records selected.

Then this code registers the button for the tab with id '186':

  OB.ToolbarRegistry.registerButton(buttonProps.buttonType, isc.OBToolbarIconButton, buttonProps, 100, '186');

Note:

Note: in 3.00MP0 a button can only be registered for one specific tab or for all tabs. In 3.00MP2 this will be solved by allowing an array of tab ids (see this issue to track the solution)

The ComponentProvider

The previous steps added static resources (javascript and css) to the system. Now Openbravo should know where to find these resources when initializing and generating the user interface. For this the css and javascript and resources have to be registered. This is done through a ComponentProvider. For more detailed information on the ComponentProvider concept visit this page.

 
@ApplicationScoped
@ComponentProvider.Qualifier(ExampleComponentProvider.EXAMPLE_VIEW_COMPONENT_TYPE)
public class ExampleComponentProvider extends BaseComponentProvider {
  public static final String EXAMPLE_VIEW_COMPONENT_TYPE = "OBEXAPP_ExampleViewType";
 
  /*
   * (non-Javadoc)
   * 
   * @see org.openbravo.client.kernel.ComponentProvider#getComponent(java.lang.String,
   * java.util.Map)
   */
  @Override
  public Component getComponent(String componentId, Map<String, Object> parameters) {
    throw new IllegalArgumentException("Component id " + componentId + " not supported."); 
    /* in this howto we only need to return static resources so there is no need to return anything here */
  }
 
  @Override
  public List<ComponentResource> getGlobalComponentResources() {
    final List<ComponentResource> globalResources = new ArrayList<ComponentResource>();
    globalResources.add(createStaticResource(
        "web/org.openbravo.client.application.examples/js/example-toolbar-button.js", false));
    globalResources.add(createStyleSheetResource(
        "web/org.openbravo.userinterface.smartclient/openbravo/skins/"
            + KernelConstants.SKIN_VERSION_PARAMETER
            + "/org.openbravo.client.application.examples/example-styles.css", false));
 
    return globalResources;
  }
 
  @Override
  public List<String> getTestResources() {
    return Collections.emptyList();
  }
}

A short explanation:

To explain how Openbravo can find the ComponentProvider: Openbravo/Weld will analyze the classpath and find all the classes which have a @ComponentProvider annotation.

The result

To see the result, restart Tomcat, clear the cache of the browser (sometimes css styles are not picked up) and go back to the application and then specifically the sales order window. You should see this:

Note: the button is not visualized in other windows/tabs because it is registered for only the sales order header tab.


Howto-result-1-file-30.png


Adding server side logic - Implementation steps

The next step in this how to is to add the server side logic and calling this logic from the client. The server side logic is implemented using the action handler concept. The action handler concept allows you to create classes on the server which are callable from the client. This how to will illustrate this.

Implement the server side action handler

The server side action handler (SumOrderActionHandler.java) receives an array of order numbers of the selected orders. It will sum the order values and then return the total as a JSON string.

This is the implementation of the server side:

public class SumOrderActionHandler extends BaseActionHandler {
 
  protected JSONObject execute(Map<String, Object> parameters, String data) {
    try {
 
      // get the data as json
      final JSONObject jsonData = new JSONObject(data);
      final JSONArray orderIds = jsonData.getJSONArray("orders");
 
      // start with zero
      BigDecimal total = new BigDecimal("0");
 
      // iterate over the orderids
      for (int i = 0; i < orderIds.length(); i++) {
        final String orderId = orderIds.getString(i);
 
        // get the order
        final Order order = OBDal.getInstance().get(Order.class, orderId);
 
        // and add its grand total
        total = total.add(order.getGrandTotalAmount());
      }
 
      // create the result
      JSONObject json = new JSONObject();
      json.put("total", total.doubleValue());
 
      // and return it
      return json;
    } catch (Exception e) {
      throw new OBException(e);
    }
  }
}

Notes:

Calling the server side from the client, displaying the result

Then on the client the action method of the button has to be implemented to call the server. Here is the implementation. See the web/org.openbravo.client.application.examples/js/example-toolbar-button.js for the full listing:

      action: function(){
        var callback, orders = [], i, view = this.view, grid = view.viewGrid, selectedRecords = grid.getSelectedRecords();
        // collect the order ids
        for (i = 0; i < selectedRecords.length; i++) {
          orders.push(selectedRecords[i].id);
        }
        
        // define the callback function which shows the result to the user
        callback = function(rpcResponse, data, rpcRequest) {
          isc.say(OB.I18N.getLabel('OBEXAPP_SumResult', [data.total]));
        }
        
        // and call the server
        OB.RemoteCallManager.call('org.openbravo.client.application.examples.SumOrderActionHandler', {orders: orders}, {}, callback);

Note:

Then when the server returns the callback is called which will display a prompt. Note that the label used in the callback uses parameter substitution. Parameters are specified using a %0, %1 etc.:


Howto-toolbar-message-result-30.png

The result

The result shows the sum of the 2 selected order headers:


Howto-toolbar-final-result-30.png

Retrieved from "http://wiki.openbravo.com/wiki/How_to_add_a_button_to_the_toolbar"

This page has been accessed 46,597 times. This page was last modified on 28 March 2013, at 17:53. Content is available under Creative Commons Attribution-ShareAlike 2.5 Spain License.