Thursday 29 November 2012


BSP Guide : How to create a basic BSP…

1: The basicest of basics

Go in to txn SE80, and instead of “program” in the ddown[D1]  menu on the LHS[D2]  of the screen, select “BSP Application”. Enter a new BSP application name. Just like regular ABAP, if SAP doesn’t know what the application is, it will create one for you. Give it a description, generate it as  local object,
Activate the project as it is.

Rightclick on the top of the (as yet empty) tree structure and select “Create->Page”.
SAP asks you for a name for your page, I’ve called mine ‘pag1.htm’. Leave the .htm suffix in situ, and give it a meaningful description. Leave the pagetype as “Page with flow logic” and enter through.
Activate the page using the Ctrl-F3 or the button. (as per regular ABAP).

This should now look as follows:

Believe it or not, you can now run this!

You get asked for a username and password, since internet explorer is now trying to connect to SAP. Enter your SAP username and password, and you get passed to the page.


Notice in the URL of the internet explorer, you’ve got a load of junk, but also some telling information:


For example, the z_qp_01/pag1.htm is what I called the program and the page.
The start of the URL is the SAP Server upon which the bsp is written. 1080 is the port that’s been configured in SAP for the release of the BSPs. 

2 : Breaking down the screens.

BSPs use what’s called ‘page fragments’ to break down a screen. They work a lot like includes in ABAP, or better yet, windows in SAPScripts. The good thing about them is that you can reuse them over and over, so you can create a header screen that holds the company logo in it, and put it onto every screen in an application. Or you could have one that presents the username and timestamp.

From your basic screen, (pag1) change:


<%@page language="abap"%>
<%@extension name="htmlb" prefix="htmlb"%>

<htmlb:
content design="design2003">
  <htmlb:page 
title = "Page 1 ">
    <htmlb:
form>

      <htmlb:textView     
text          = "Hello World!"
                          design        = 
"EMPHASIZED" />

      <htmlb:
button       text          = "Press Me"
                          
onClick       = "myClickHandler" />

    </htmlb:
form>
  </htmlb:page>
</htmlb:
content>

Into :

<%@page language="abap"%>
<%@extension name="htmlb" prefix="htmlb"%>

<htmlb:content design="design2003">
  <htmlb:page 
title = "Page 1 ">
    
<%@ include file = "top.htm" %>
  </htmlb:page>
</htmlb:
content>

Now the include file doesn’t exist yet, so if you rclick on the top of the tree hierarchy on the lhs of the screen, you can create another page.
We’ll call this one top.htm (since that’s what we’ve ref’d in the pag1.htm)
This page will be different to the first one – it will be a “page fragment”.


Now we’ll drop what we removed from the pag1.htm and put it into top.htm, so it now looks like this:

<%@page language="ABAP"%>

    <htmlb:
form>

      <htmlb:textView     
text          = "Hello World!"
                          design        = 
"EMPHASIZED" />

      <htmlb:
button       text          = "Press Me"
                          
onClick       = "myClickHandler" />

    </htmlb:
form>

Activate top1.htm, and activate pag1.htm, which now references top1.htm instead of containing the text and the button.

You also need to include the fact you’ll be using “HTMLB” within the page fragment…
So put that in underneath
<%@page language="ABAP"%>
thus…
<%@page language="ABAP"%>
<%@extension name = "htmlb" prefix="htmlb" %>

Activate and run the application from pag1.
Result should most likely be that the program runs the same as it did on the first page. Still, we’ve proved the point of page fragments.

3 : Making the program a bit more interactive.

Thus far we’ve seen the htmlb standards for outputting a bit of text, and creating a button. But nothing happens when we press the button at the moment.

If you’ve missed that, it’s the bit in the page fragment

      <htmlb:button       text          = "Press Me"
                          
onClick       = "myClickHandler" />


Change the button to :

      <htmlb:button           id      = 'id_1'
                             
text          = "Press Me"
                          
onClick       = "onInputProcessing()" />

This has the effect of giving the button a program id (like the process code in a dialog screen) and makes the clicking of the button point to the onInputProcessing part of the main screen.

Save and activate the fragment top.htm.

Now got back to the main page – pag1.htm.
There’s an “event handler” tab which deals with interactions between the user and the screen. When the button gets pressed, it invokes the “onInputProcessing” code, which works like a PAI in dialog. So in the event handler, use the dropdown list to find the “onInputProcessing” event for the page.

The following code handles HTMLB events:

IF event_id = CL_HTMLB_MANAGER=>EVENT_ID.

  
DATAevent TYPE REF TO CL_HTMLB_EVENT,
        button_event 
TYPE REF TO CL_HTMLB_EVENT_BUTTON,
        tv 
type ref to cl_htmlb_tableview,
        tv_data 
TYPE REF TO CL_HTMLB_tableview.

  
data: wa_zcaps1 type ZCAPS1.
  
data: vl_cookiename TYPE char30.

  
event = CL_HTMLB_MANAGER=>get_event( runtime->server->request ).

  
IF event->name = 'button' AND event->event_type = 'click'.
    button_event ?= 
event.
    
case button_event->id.
      
when 'id_1'.
        navigation->goto_page( 
'pag2.htm' ).
    
endcase.
  
endif.
endif.
The key to this bit of code is the bit near the end…



  IF event->name = 'button' AND event->event_type = 'click'.
    button_event ?= 
event.
    
case button_event->id.
      
when 'id_1'.
        navigation->goto_page( 
'pag2.htm' ).
    
endcase.

Essentially this says “If the event ID is id_1, go to pag2”.

Now we’ve not created pag2.htm yet, so we go to the navigator on the lhs of the screen, rclick the “Pages with flow logic” and create a new page. (page with flow logic)

This automatically creates another page just like the first one. We don’t want this, since we won’t be able to tell the difference!.

So we’ll get rid of all the htmlb form, and replace it with a success message.
So the contents of pag2.htm should now look like this:

<%@page language="abap"%>
<%@extension name="htmlb" prefix="htmlb"%>

<htmlb:
content design="design2003">
  <htmlb:page 
title = "Second Page ">
    success!!!
   </htmlb:page>
</htmlb:
content>

Now the trick to this is that whilst most html output is tagged to help with formatting and so forth, you can actually just put text in an html page. Internet explorer shouldn’t find this a problem.

Activate the target page pag2.htm.

Go to pag1.htm and run it. Clicking on the button directs us to pag2.htm.

4: More interaction..
4.1 Simple Text Entry
So far so good. But we most likely want users to enter some information, or to output some stuff from SAP. Or mayhap a combination of both.

First declare your data in the “Page Attributes” tab of pag1.htm
We’ll declare name1 type name1.


We’ll flag it as automatic as well. This allows calling pages to pass the data in (kind of like in a fm call where you pass data in.)

Activate the page, so when we go to the top.htm page fragment, top will be able to “see” the newly declared attribute.
Now we’ve declared it, we can use it in the top.htm page fragment.

The HTMLB syntax for a data entry of this type is as follows:

 <INPUT type="text" name="name1"
                  
value=<%= name1 %>  >

This needs to go inside the <htmlb:form> <htmlb:form/> tags.

This can then be handled inside the eventhandler if needs be.
The <%= name1 %> indicates that we’re using an ABAP variable here.
Within the BSP, it is in fact possible to switch between ABAP and HTML/HTMLB
The <%= %> indicates the commencement and ending of ABAP.


We’ll demonstrate handling of this in the eventhandler by coding in a condition that if the name1 is a particular value, then we’ll do something else.
    case button_event->id.
      
when 'id_1'.
        
if name1 = 'bugs'.
         navigation->goto_page( 
'pag3.htm' ).
        
else.
         navigation->goto_page( 
'pag2.htm' ).
        
endif.
    
endcase.
And as usual, we’ll need to create pag3.htm giving it the following contents :
<%@page language="abap"%>
<%@extension name="htmlb" prefix="htmlb"%>

<htmlb:
content design="design2003">
  <htmlb:page 
title = "Page 3 ">
    <htmlb:
form>
      Page 
3
    </htmlb:
form>
  </htmlb:page>
</htmlb:
content>

Activate everything, go back to page1 and test.
You should find that if the contents of the field on the screen is “bugs” then we go to page 3, and if not then we go to page 2.


4.2 Dropdown Lists.

The classic HTML dropdown list is as follows:

<select name="cars">
      <option value="volvo">Volvo</option>
      <option value="saab">Saab</option>
      <option value="fiat">Fiat</option>
      <option value="audi">Audi</option>
</select>

However, in SAP, we can get round the need to repetitively give the user options by using the BSP’s capability to code a bit in ABAP and a bit in HTML.

Create a pag1.htm page attribute called v_vbeln of type vbeln. Activate the page.
For this exercise we’ll also need a table of vbelns. This gets defined in the pag1
“type definitions” tab. This is exactly the same as a declaration in a regular ABAP program.

typesBEGIN OF ty_vbeln,
        vbeln 
TYPE vbeln,
      
end of ty_vbeln.

types: tty_vbeln TYPE TABLE OF ty_vbeln.

 This gives you a type tty_vbeln and a 1 field structure we can use.

Then in the PageAttributes Tab, declare a table and wa of these types:

t_vbeln            TYPE  TTY_VBELN
wa_vbeln         TYPE  TY_VBELN

Now for the fun part…

In the top.htm, code in the following after the name1 input tags, but still within the form tags.
<%
select vbeln from vbak into table t_vbeln
where erdat = '20080610'.
%>

<
select name="v_vbeln" value<%= v_vbeln %>
                         
title"SD Doc Number" >
<%
 
loop at t_vbeln into wa_vbeln.
%>
    <
option value=<%= wa_vbeln-vbeln %><%= wa_vbeln-vbeln %>
    </
option>
<%
  
endloop.
%>
</
select>


So what we’re doing here is selecting the data out of SAP using regular ABAP,
Then defining a dropdown selection, using HTML
Then going into a loop using ABAP again.
Then putting the contents of the loop into the HTML options table.
Then closing the loop using ABAP again.
Then closing the select using HTMLB.

Activate everything and test it from pag1.htm.

You should see the dropdown list.

4.3 Date Entry
To reap the benefits of other people’s work in creating calendar dropdowns, add in the following in the top.htm still within the htmlb:form/> tags.

<htmlb:inputField id = "opening_date"
value = "<%= opening_date %>"
showHelp = 
"TRUE"
type = "date"
/>

You will also need to establish the data in the first place at the top of page1 – opening_date type datum.

Activate. Run. See the dropdown.


5 Making it a bit prettier…

5.1 Breaks.

<br> is the html for “new line”
Hence our top.htm example can go from looking like this:



to this:


Next up we probably want to label the fields a bit. The button’s okay as it is as it kind of speaks for itself, but the text, the date and the document number most likely want labelling. The easiest way would be to just type the text in before the field…

E.G.
<br>
NAME1
<
INPUT type="text" name="name1"
                  
value=<%= name1 %>  >


<
br>
But this doesn’t look particularly great:

So what we’ll do is get them lined up by means of a table.

5.2 Grids.
An html page grid serves as a way of tidying up the display. The problem is they’re fairly complicated in terms of the amount of html code they take up versus the improvement they make on the screen.
That said, users can be picky, and this is the way to make them happy.

First define how big you want the grid to be, and then use the following example to wrap the fields we’ve got already in a table that lines it all up. Since the table will handle the new lines, we can get rid of the <br> formatting.

<htmlb:gridLayout columnSize = "4"
                  rowSize    = 
"8" >



</htmlb:gridLayout>
sits around the whole thing.

And then
<htmlb:gridLayoutCell columnIndex = "3" rowIndex    = "1" >
</htmlb:gridLayoutCell>
sits around each cell, to describe where it sits in the grid.
So put the “opener” tag in front of everything you want “placed” i.e. the texts and the fields themselves. Columns should alternate between 1 and 2, and at every new column, increment the row by 1.


Code should now look like this :
<%@page language="ABAP"%>
<%@extension name = "htmlb" prefix="htmlb" %>
    <htmlb:
form>
<htmlb:gridLayout columnSize = 
"4"
                  rowSize    = 
"8" >
htmlb:gridLayoutCell columnIndex = 
"1" rowIndex    = "1" >
      <htmlb:textView     
text          = "Hello World!"
                          design        = 
"EMPHASIZED" />
</htmlb:gridLayoutCell>
<htmlb:gridLayoutCell columnIndex = 
"1" rowIndex    = "2" >
      <htmlb:
button           id      = 'id_1'
                             
text          = "Press Me"
                          
onClick       = "onInputProcessing()" />
</htmlb:gridLayoutCell>
<htmlb:gridLayoutCell columnIndex = 
"1" rowIndex    = "3" >
NAME1
</htmlb:gridLayoutCell>

<htmlb:gridLayoutCell columnIndex = 
"2" rowIndex    = "3" >
<
INPUT type="text" name="name1"
                  
value=<%= name1 %>  >
</htmlb:gridLayoutCell>
<htmlb:gridLayoutCell columnIndex = 
"1" rowIndex    = "4" >
DOCUMENT
</htmlb:gridLayoutCell>

<htmlb:gridLayoutCell columnIndex = 
"2" rowIndex    = "4" >
<%
select vbeln from vbak into table t_vbeln
where erdat = '20080610'.
%>
<
select name="v_vbeln" value<%= v_vbeln %>
                        
title"SD Doc Number" >
<%
 
loop at t_vbeln into wa_vbeln.
%>
    <
option value=<%= wa_vbeln-vbeln %><%= wa_vbeln-vbeln %>
    </
option>
<%
  
endloop.
%>
</
select>
</htmlb:gridLayoutCell>
<htmlb:gridLayoutCell columnIndex = 
"1" rowIndex    = "5" >
DATE
</htmlb:gridLayoutCell>

<htmlb:gridLayoutCell columnIndex = 
"2" rowIndex    = "5" >
<htmlb:inputField 
id = "opening_date"
value = "<%= opening_date %>"
showHelp = 
"TRUE"
type = "date"
/>
</htmlb:gridLayoutCell>

</htmlb:gridLayout>
</htmlb:
form>


And the result is that the fields have lined up nicely:


5.3 Graphics
An easy way to impress users and make them happier with a web-page is to put a few graphics on there. Graphics are stored in the MIME repository on SAP. Getting graphics into the repository, and calling them on a BSP is a pretty simple process.

Get the graphic in by rclicking on the root of the navigation tree on the lhs of the screen, and go to “Create->MIME Object->Import”.

6 More Data manipulation.

6.1 – Passing Data between screens.

The data doesn’t actually “survive” between screens. You can demonstrate this by entering data on page 1, pressing the “pressme” button, then going “BACK” to the first screen using the navigator button “Back” in Internet explorer.

There are a number of ways of doing this. One of these is a server cookie, which stores the data on the database, as a complete structure or table.

For the time being, we’ll create an object that the BSP can sit on. This will survive between BSP Screens, and it’s known as the “Application Class” for the BSP. Name the application class in the Properties Tab of the Application.



Create the class in SE24, and give it attributes that mirror what’s in your BSP. At this stage it’s most likely name1, vbeln, and datum.
Make them PUBLIC INSTANCE ATTRIBUTES of types becoming of their names.
Save and activate the class.

Now handle the data entry by passing the variables from the bsp into the variables in the class. In the “onInputProcessing” set the object “Application” attributes to the Page Values.

application->attr_name1 = name1.
application->ATTR_DATE1 = opening_date.
application->ATTR_VBELN = v_vbeln.

This stores the data in the object, after pag1 is processed. To retrieve it again, the pages need to set the values to the object values onInitialisation. This is like the PBO of a dialog screen.

So we just reverse the above code to.
name1 = application->attr_name1.
opening_date = application->ATTR_DATE1.
v_vbeln = application->ATTR_VBELN.

And put it in the onInitialisation of the pag1 screen. This means that when pag1 is invoked, it picks up the data from the object.

Activate and test this – enter data, press the “Pressme” button, then navigate back to the pag1.htm using “Back”. The data should still be on the screen.

6.2 Present some data in a table.

We’ll create a new page fragment called SO_TABLE to present the data in, and put this on pag2.htm

In pag2.htm we’ll need a list of salesord line items, so declare the tabular variable in the “Page Attributes” tab of pag2.htm. This will need to be “Typed” first in the “Type Definitions” tab.

Go to the “onInitialisation” tab, and populate the table based on the vbeln of the application data.

select * from vbap into table t_vbap
   
where vbeln = APPlication->attr_vbeln.

Next you need to output this in a table. Syntax for outputting in a table
is:
<%@extension name = "htmlb" prefix="htmlb" %>
<htmlb:
form>
<htmlb:tableView 
id = "sales_order"
              
table = "<%= t_vbap %>"
              selectionMode = 
"SINGLESELECT"
              >
<htmlb:tableViewColumns>
<htmlb:tableViewColumn columnName=
"VBELN">
</htmlb:tableViewColumn>
<htmlb:tableViewColumn columnName=
"POSNR">
</htmlb:tableViewColumn>
<htmlb:tableViewColumn columnName=
"ARKTX">
</htmlb:tableViewColumn>
<htmlb:tableViewColumn columnName=
"UMZIZ">
</htmlb:tableViewColumn>
<htmlb:tableViewColumn columnName=
"MEINS">
</htmlb:tableViewColumn>
<htmlb:tableViewColumn columnName=
"NETWR">
</htmlb:tableViewColumn>

</htmlb:tableViewColumns>
</htmlb:tableView>
</htmlb:
form>
ACTIVATE and Run. This creates a table control for you to use in the program.


6.3 Data checking.

You may want to add in a bit of logic that ensures that the user is prompted for further information if they’ve not entered enough, or if the data on the screen is inconsistent they are prompted to fix it.

To do this, we must introduce some very basic javascript.

The javascript is processed as part of the html, so you can code in any java functions in the page fragment itself.They go in a “Header” section of the html. So in the fragment which contains the entry field “Name1”, first code in the following :

<head>
<
script type="text/javascript">

function checkFormular1(htmlbevent)
  {
  
var txt="";
  if(document.Formular1.name1.
value.length==0){
    alert(
"Please enter a name!");
  }
  }

</
script>
</
head>

Since the onClick event is already being used by the htmlb, we can use the onClientClick which can be used for checking the data at the client side. This saves server roundtrips, where the client (e.g. internet explorer) has to go and look at the server (e.g. SAP)

Then change the attributes of the <form> we are using to encapsulate the data entry. We give it the if “Formular1” to match the “Formula1” in the function above.

So in the page fragment,
<htmlb:form>

becomes
<htmlb:form id="Formular1">

This handles the message output.
However, the onInputProcessing will still go ahead, so we’ll put a check in there also.
Check name1 is not initial
This prevents any further processing from occuring.
Worth doing the check after the object has been populated.