Skip to Content

Daniel McWeeney opened the ball with his weblog How-To:  Create AJAX Applications in SAP. I found the example very interesting, although (as someone commented) lacking a bit in SAP-related scenarios. Why use Ajax instead of the usual request/response cycle? Well, I think Ajax defends itself. Sometimes, not having to go through the request/response cycle is very convenient; both for small tasks that really don’t justify reloading a whole page, and if one wants to launch a series of requests to various providers or services without wanting to wait through the whole process. My task, I figured out, would be to try and create just that SAP-related scenario.</p>

The scenario

My first intention was to create a simple htmlb-based BSP with a tableview; allowing users to click on entries in the table in order to invoke Ajax functionality. First, I had to build a simple app to test various ways of incorporating Javascript functionality within a BSP (not to mention refreshing my old, somewhat dusty Javascript knowledge!). After a few attempts I came up with a solution that actually works.

The foundations for this application are two BSP pages; one for providing the data in xml format, and another page for calling and displaying the results.

Let’s start by describing the scenario:

Our main page will show a tableview of SAP users (my security background clearly shows here. I could have chosen flights instead) When clicking on a userID in the tableview, a list of that user’s vital data will show up in a dedicated area. This happens instantly, without the need to reload the page (or parts of it).

Let’s talk about X-M-L…

<p>OK, on to the BSP pages. We need two. The first one, which retrieves data and scrambles the XML, is called data.xml. It has the following layout:</p>
<br>
<TEXTAREA ROWS=”4″ COLS=”80″>
<?xml version=”1.0″?>
<%@page language=”abap”%>
<%=xml%>
</TEXTAREA>

<br>
<br>
<p>The onRequest event handler is where the work is done:</p>
<br>
<TEXTAREA ROWS=”15″ COLS=”80″>

data: wa_usr02 type usr02,

      wa_usr21 type usr21,

      wa_adrp type adrp,

      wa_smtp_addr type AD_SMTPADR.

clear: wa_usr02, wa_usr21, wa_adrp.

  • Retrieve the username from the calling page

username = request->get_form_field( name = ‘user’ ).

select single * from usr02 into wa_usr02

  where bname = username.

if sy-subrc eq 0.

  • We have to make sure all fields are filled, otherwise

  • the resulting page will give a “missing object” error

  if wa_usr02-class is initial or wa_usr02-class eq ‘ ‘.

    move ‘X’ to wa_usr02-class.

  endif.

  select single * from usr21 into wa_usr21

    where bname = username.

  if sy-subrc eq 0.

    select single * from adrp into wa_adrp

      where PERSNUMBER = wa_usr21-PERSNUMBER.

    if sy-subrc eq 0.

      if wa_adrp-name_first is initial.

        move ’empty’ to wa_adrp-name_first.

      endif.

      if wa_adrp-name_last is initial.

        move ’empty’ to wa_adrp-name_last.

      endif.

      select single smtp_addr from adr6

        into wa_smtp_addr

        where PERSNUMBER = wa_usr21-PERSNUMBER.

      if wa_smtp_addr is initial.

        move ‘unknown’ to wa_smtp_addr.

      endif.

    endif.

  • Compile the resulting XML

  • (using XSLT would be even nicer – for next blog?)

    concatenate ‘

Put Ajax to work

is invoked with the user’s ID as parameter (bname). Here’s the code for the onCreate event:

  • Retrieve the users from the main user table (USR02)

SELECT bname ustyp class FROM  usr02

                into corresponding fields of table wt_usr02

                where class eq ‘TESTCLASS’.

  • Loop at the resulting internal table; create <a href> tag

loop at wt_usr02 into wa_usr02.

  move-corresponding wa_usr02 to wa_usr02b.

  shift wa_usr02-bname left deleting leading space.

  concatenate ‘

And now, the results:

All we do is select entries from the USR02 table, then create a source table for the tableView which contains the user names in slightly modified versions. We simply wrap a tag invoking the javascript function getName around each username; the result being a clickable table (note the underlined user names, indicating a link):

image

By clicking any of these entries, the getName function is invoked, and the user’s data displays in the textViews handily set aside for that purpose:

image

Final word

I’m sure much could be improved here, but my principal aim has been to demonstrate the feasibility of Ajax in a BSP application. I hope this weblog has inspired you to try this out in your own BSP applications!

To report this post you need to login first.

6 Comments

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

  1. Ulli Hoffmann
    Hi Trond,

    I’ve copied your coding, commented out the where-clause in the usr02 select statement and everything worked. Very nice example how to involve htmlb.
    In the BSP forum there is a thread called ‘new weblogs’. Just write a post there, many have it on their watch list, they will like it.

    Ulli

    (0) 
    1. I should have removed that ‘where’ clause before posting 🙂

      Another thing worth mentioning is that you need to set the MIME type of the data.xml page to ‘text/xml’. This is done in the page properties. Failing to do so could lead to the feared ‘object expected’ error when the calling page tries to apply the XML DOM to your resulting XML document. In one of my WAS systems, this setting was automatically done properly when I created the data.xml page, whereas in my miniWAS 6.20 the setting was ‘text/html’ by default.

      Trond

      (0) 
  2. Sergio Ferrari
    Thanks a lot for the weblog.
    I modified the javascript in order to support mozilla. Now it works both with IE e FireFox.

    function getName(bname){
    var url = “data.xml?user=” + bname;

    // Instantiate the object
    // Mozilla/Safari
    if (window.XMLHttpRequest) {
    req = new XMLHttpRequest();
    req.overrideMimeType(‘text/xml’);
    }
    // IE
    else if (window.ActiveXObject) {
    req = new ActiveXObject(“Microsoft.XMLHTTP”);
    }

    // SEND the request to the server
    if (req){
    req.onreadystatechange = processReqChange;
    req.open(“GET”, url, true);
    req.send(null);
    }
    else{
    alert(“Failed to Create XML Request Object.”);
    }
    }
    function processReqChange(){
    // alert(“Received XML node”);
    if (req.readyState == 4){
    if (req.status == 200){
    var response;
    response = req.responseXML;
    // try catch is to be implemented
    BNAME.innerHTML = response.getElementsByTagName(“BNAME”)[0].firstChild.data;
    GLTGV.innerHTML = response.getElementsByTagName(“GLTGV”)[0].firstChild.data;
    TRDAT.innerHTML = response.getElementsByTagName(“TRDAT”)[0].firstChild.data;
    LTIME.innerHTML = response.getElementsByTagName(“LTIME”)[0].firstChild.data;
    NAME_FIRST.innerHTML = response.getElementsByTagName(“NAME_FIRST”)[0].firstChild.data;
    NAME_LAST.innerHTML = response.getElementsByTagName(“NAME_LAST”)[0].firstChild.data;
    EMAIL.innerHTML = response.getElementsByTagName(“EMAIL”)[0].firstChild.data;
    }
    }
    }

    (0) 
    1. I personally prefer the mouseover variety; I’ve experimented with it as well. It’s a nicer option especially for smaller chunks of data, like here.

      If, on the other hand, you’re working with large chunkc of info (say, you want to display the text of a document when selecting it’s header from a list) you’re probably better off using the onClick… Javascript can be fun sometimes!

      Trond

      (0) 
    2. Mark Antonny
      Hi,

      This concatenate doesn’t seems to be working fine. I want to have a mouseover in my page. Could you please send me the working code sample.

      Thanks.
      Mark.

      (0) 

Leave a Reply