Skip to Content

“Load data when it’s actually needed. Do not

load data in advance.” – Lazy Data Access principle, the main WebDynpro principle.

In previous blog Effective WebDynpro Applications, (part 1): lazy Value Helps (SVS, EVS)  (Effective WebDynpro Applications, [part 1]: lazy Value Helps (SVS, EVS)) I proposed example of Help Value selector based on Input Field (EVS) with lazy-loading behaviour. Now let me show how to implement lazy selector based on Drop-Down (SVS).

Difference between SVS and EVS

Well, the main difference is that Drop-Down displays user-friendly often localized texts instead of technical keys, guids, etc. as EVS does. This, of course, affects runtime behaviour of SVS which has one peculiar thing. DropDownByKey always tries to convert a key contained in attribute selectedKey (to which the control is bound) into a text to display.

This means that SVS at runtime always touches the value set attached to it in order to resolve the ‘key -> text’ mapping. And this happens also initially when a view is just being initialized before displaying to user. The same behavior has DropDownByIndex control.

At the same time our goal is to load a data into the value set only when user expands the Drop-Down. Fortunately, WebDynpro API provides a solution.

Two Value Sets inside one

The Bound value set, which WDValueServices.createBoundValueSet(…) creates, has also an additional internal value set called Current set. The temporary value set should keep key/text pairs until a regular value set gets fully loaded state. Then the Bound value set switches from the current set to a regular one.

image

Bound Value Set structure


From the other side, for Drop-Down control it’s transparent which value set is active at that moment. It’s able to work with both value sets. The main requirement at time of the initial state of the control is at least one key/text pair is contained in the value set.

A set of API methods allows us to manipulate a content of the current value set. The methods belong to interface IWDOnDemandValueSetService – super interface of IWDBoundValueSet. Below it’s shown the effects each API method invocation causes on the bound value set.

image

Bound Value Set states and API


In our case transition to the Loaded state means activation of the supply-function with BAPI invocation. This is what we are going to postpone as last as possible until user manually expands the selector. In other words, we should never invoke any of the API contained in the green box above.

IWDBoundValueSet.setCurrentKeyValuePair(key, value):

     – Forms the current value set equals to the key/value pair.

IWDBoundValueSet.addKeyValuePair(key, value):

     – Adds the key/value pair to the current value set.

The API working with Current value set does nothing if the state is already Loaded.

Input parameter +value +shall not be null or empty, at least the space ” ” shall be provided. In case of empty value, such invocations will be interpreted in the same way as setCurrentKey(key) & addKey(key) that bring us to Loaded state.

Lazy SVS on a form

Mainly the example is very similar to the lazy EVS example from the previous blog.

Drop-Down selector is bound to attribute FormData[0..1]->countryCode(string). The FormData node represents the business object which the

form on UI is working on.

image

View context structure and design

Node ZBapi_Get_Country_List_Input[0..1] is a time-consuming BAPI imported as a model which allows to retrieve the list of countries. It has supply-function which executes the BAPI. We will use the output of the BAPI from node Et_Countries as help

values for our selector.

public void supplyZBapi_Get_Country_List_Input(IPrivateX.IZBapi_Get_Country_List_InputNode node, IPrivateX.IContextElement parentElement)
{
 //@@begin supplyZBapi_Get_Country_List_Input(IWDNode,IWDNodeElement)
 ZBapi_Get_Country_List_Input srvInput = new ZBapi_Get_Country_List_Input();
 node.bind(bp_Srv);
 srvInput.setIv_Region("Asia");
 srvInput.execute();
 //@@end
}

Then we write a code which will modify the type of attribute FormData->countryCode and create a bound value set. The value set is bound to node ZBapi_Get_Country_List_Input->Output->Et_Countries. Help value key is represented by attribute Et_Countries->Country_Code; help value text – by attribute Et_Countries->Country_Name. The code shall be executed just one time at time of view creation, so view’s wdDoInit() is a proper place for it:Initially the form shows selector working with a single pair contained in the current set: key=””, text=”<unspecified>”. When user expands the selector it tries to load values in the regular set and our BAPI is being invoked:

image

Lazy Drop-Down on form

It’s important that key in the current set shall be the same as the initial value of FormData->countryCode. In our example this is “”.

❗ Access to HV node Et_Countries with code wdContext.nodeZBapi_Get_Country_List_Input().nodeOutput().nodeEt_Countries() will not bring to BAPI execution. All the nodes ZBapi_Get_Country_List_Input -> Output -> Et_Countries will still have the invalid (not validated) state. Here it’s important that all the nodes are singletons (singleton=true).

Lazy SVS in a table

In general everything is the same as for a form – you should prepare the current value set to make Drop-Down lazy. The current set shall cover all the keys – values of the DD attribute selectedKey. In our example this attribute is countryCode. As a table can contain many rows the current set also would be not a singleton.

To form the current set we need also the set of texts corresponding to the keys. Very well if the texts coming from the table’s data source together with the keys. Then we can put the current set initialization code in the same supply-function which is responsible for a table data loading:

public void supplyTableData(IPrivateHVTest.ITableDataNode node, IPrivateHVTest.IContextElement parentElement)
{
 //@@begin supplyTableData(IWDNode,IWDNodeElement)
 ITableDataElement el = node.createTableDataElement();
 el.setCountryCode("");
 el.setCountryName("");
 node.addElement(el);
 el = node.createTableDataElement();
 el.setCountryCode("DE");
 el.setCountryName("Germany");
 node.addElement(el);
// temporary value set for Country Code HV
 countryCodeVS.resetCurrentKeys(); // (optional)
 for (int i = 0; i < node.size(); ++i) {
      countryCodeVS.addKeyValuePair(el.getCountryCode(), el.getCountryName());
 }
 //@@end
}

Initially the table shows lazy selectors working with the following current set:

{{key=””, text=”<unspecified>”}, {key=”DE”, text=”Germany”}}.

When user expands the selector in any row it tries to load values in the regular set and our BAPI is being invoked:

To report this post you need to login first.

1 Comment

You must be Logged on to comment or reply to a post.

  1. Chris van de Wouw
    Thanks for your insightful blogs about lazy loading in relation to value help selectors. It was very helpful for me in many ways, as it also triggered me exploring more about the lazy loading concept. The combination of proper use of supply functions, calculated values, manually handling component usages, lazy value helps, etc., makes my applications fly 🙂

    I do have one problem though. It seems that toolbare dropdowns are first opened as evh, even with a small set of data. The second time I click the drop down, it’s opened as svh.

    I know that with a normal dropdown, an evh is opened when more then 50 results are loaded (threshold can be set in VA->tc~wd~dispwda default.properties), but a toolbar dropdown doesn’t seem to follow this setting.

    Any thoughts?

    (0) 

Leave a Reply