Creating HTML5 Applications from scratch for ABAPers – Part 3
Part III: Creating a User Lookup Application using the SAPUI5 framework
In the last blog i’ve promised to guide you through the wijmo framework. But when i got the new release of the Neptune Application Designer (NAD) with the integrated SAPUI5 framework I couldn’t resist to check it out. It’s so cool that i thought it might be interesting for you as well.
So let’s start and create a user lookup application using common bapis and the new sapui5 look.
Again I strongly recommend to get familiar with the NAD first, using the first two parts about
the designer:
Important: This tutorial was written for the RC1 of release 2.10! The RC2 is out now and there are some major changes. So I strongly recommend to upgrade to the RC2 if you are starting. For those having already finished the application and want to upgrade to RC2 I’ve added the changes to make to the relevant areas of this tutorial.
1. Create a abap class and implement the interface /NEPTUNE/IF_NAD_SERVER
2. Create an application. Name it i.e. ZRJT_BLOG_SAPUI5_01
Insert your application class on the application tab of the application.
Select SAPUI5 as general and sap.m as specific library
Select Bluecrystal as theme.
Change to the designer and add Layout/App to the objects tree. Name it ‘App’. Note: The objects have no styles. Everything comes from the framework. If you want, check the attributes of the object to get an overview.
Basically the SAPUI5 framework organizes the application flow almost similar to jQuery Mobile. There are no single pages called by requests. It’s just one page and the other pages are just part of the same DOM which are shown or hidden if the user navigates.
3. For our application we need 3 pages. A menu page, a overview page as list and a detail page.
Therefor add three page containers from /Layout/ as childs of the App object. Keep all three on the same level. Name them like shown in the picture:
Remember that i’m always using the object type as prefix. You can do it your way. But the page container objects have to be named unique. Otherwise you will mess up the navigation.
Add a Title to the field on the General Tab of every page container. This will be the header of the pages. Activate and preview. Your application should look like this:
4. Add a StandardTile object from /ValueHolders/ as child of the container pageMenu. Name it ‘tileMenuUserLookup’. As you may know from Fiori the tiles are used for navigating like ‘links’ or ‘buttons’.
Go to the General Tab of the Tile and add a title (ie. Show Users’).
Select the Attribute Tab of the tile and look for the field ‘icon’. Use the search help
on the right side of the filed. This page should be shown:
Select the name of the icon, copy and paste them into the field ‘icon’ of the tile. Also put
‘sap-icon://’ as prefix.
In my demo i have used the value ‘sap-icon://person-placeholder’ as icon for the tile.
You may also fill the field number with a value. This will be shown on the upper right side of the tile. You can also fill the field ‘info’ with some information. It will be shown at the bottom of the tile:
If you preview it you can see that the pointer is changing upon the tile and it changes if you click on it.
So let’s build some navigation to our pageOverview.
Go to the Attribute Tab of the tile and paste App.to(“pageOverview”); to the field ‘press’ under Events. Activate and check it out. Easy, isn’t it?
There is another interesting feature i want to show you. Press the button on the right side of the field ‘press’. In the upcoming window navigate to the folder ‘OtherUI5’. Select Navigation sap.m and press the button
You get some very useful javascript snippets for all kinds of navigation. Just copy and paste it and change the name of the page you want to navigate to. You can also add your own JavaScript there, select it and press ‘Enter’. The script will be used for the filed (in this case ‘press’) but shows up as ‘Ananymous Function’.
This means you can have all your own scripts inside the application and can use it in different places. Due to the up- and download function in that window it’s easy to create your own javascript snippets and import them into every new application.
Now let’s add a navigation from the pageOverview back to pageMenu.
Select the object pageOverview. Insert App.backToPage(“pageMenu”); to the field ‘navButtonTap’. For the field navButtonType select sap.m.ButtonType.Back from the dropdown. For the field showNavButton select true from the dropdown. Activate and Preview.
The overview page should show a arrow on the upper left corner and navigate back to the menu page if you click on it. That was easy, right?
5. Now we should get some data from our tables. Go to your application class and add a attribute to it:
Attribute Level Visibility Associated Type
T_USERLIST Instance Attribute Public HRBAS_BAPIUSNAME_TABLE
Go to your application class and create a private instance method ‘GET_USER_DATA’. Navigate into the method and paste the coding into it:
data lt_selection_range type table of bapiussrge.
data ls_selection_range type bapiussrge.
data lv_search_input type string value ‘*’.
*Prepare the selection range
move ‘USERNAME’ to ls_selection_range-parameter.
move ‘I’ to ls_selection_range-sign.
move lv_search_input to ls_selection_range-low.
move ‘CP’ to ls_selection_range-option.
append ls_selection_range to lt_selection_range.
call function ‘BAPI_USER_GETLIST’
exporting
max_rows = 100
with_username = ‘X’
tables
selection_range = lt_selection_range
userlist = me->t_userlist.
It’s similar to the code i have used for the last blog. To make it easy we will handle no errors. To test the method just change the visibility temporary to ‘public’.
6. Back to the designer. Add a List from the ‘List’ folder as child to the page container ‘pageOverview’ and name it ‘listUsers’.
Change to the general tab of that object.and fill the field ‘Title’ with ‘Username(Full)’.
Bind the field ‘Model Source’ to the attribute T_USERLIST of the application class:
Fill the field ‘AJAX ID’ with ‘GET_USERS’.
Important: If you use RC2, select the button beside the AJAX ID to select the model you want to receive data from:
Important: If you are working with the RC2 of release 2.10 you have to know, that the Ajax ID is no longer fired on initialisation! You now have to set the attribute setInitLoad of the list to online / cache or onlineOnEmptyCache. If you are using one of the last two options you also have to set ‘setEnabledCache’ to true.
Add an item of type StandardListItem from the List folder as child below the list object, name it ‘itemFullname’ and set
the type to sap.m.ListType.Navigation.
Go to the Attribute tab of that object.
Bind the field ‘description’ to the field USERNAME of the table.
Bind the field ‘title’ to the field FULLNAME of the table.
Insert ‘sap-icon://employee’ to the field icon.
Activate the application and implement the interface method HANDLE_ON_AJAX in your application class (just doubleclick on it).
Insert the following code to the method HANDLE_ON_AJAX:
case ajax_id.
when ‘GET_USERS’.
me->get_user_data( ).
endcase.
This means if the Ajax ID of the list is fired, the table in the application class will be filled using the method GET_USER_DATA.
Activate and preview your application.
After clicking on the tile the application should navigate to the overview page and sho a list similar to this one:
Cool, isn’t it? 😎
You are now already a experienced sapui5 mobile application developer 😉
7. Now we will build the detail page. Before we can start i need to explain how the NAD handles the binding of view fields to the attributes of the application class.
As you may already know we just bound the tables, structures and values from the application class to the fields of the view when using jQuery Mobile or Wijmo. On tables we used a loop object to create lists and so on.
SAPUI5 is using so called models. Models are structures or tables and have to be declared as attributes of the application class. (To be honest i don’t really like the term ‘model’ for that construct, but that’s another bag).
Models are used to send data between application class and view. In SAPUI5 the page container has to be bound to one (or more) models. This models have to be structures which contain all fields you want to show on a page.
To make it more confusing check our overview page: We did not bind the model to the page container, but to the list directly. This was working because we simply navigated to that page and our listUsers fired the Ajax ID ‘GET_USERS’ at initialization.
Important: If you are working with the RC2 of release 2.10 you have to know, that the Ajax ID is no longer fired on initialisation! You have to set the attribute setInitLoad to online / cache or onlineOnEmptyCache. If you are using one of the last two options you also have to set ‘setEnabledCache’ to true. This is a real cool feature! The application will automatically handle offline situations without any scripting on the device. The cache is limited to 2.5 Mb but that should be far enough in most cases.
In Neptune you can bind structures/tables to different components. All containers (Page, Vbox, Hbox, Panel mm) can be bound to a structure. Table/List can be bound to Internal Tables. You can also bind as many components as needed on each page.
To show our detail for a user the flow has to be different:
– we need to get the value for the userid of the selected user from the overview list.
– we need to trigger the sending of an Ajax ID to call the HANDLE_ON_AJAX interface method
and transfer the selected user.
– we need to get the detail data from the sap tables and fill the model
– we need to transport the data to the view
– we need to navigate to the view
Let’s start with creating the method and the model.
Create a structure and name it. In this case i have used ‘ZNAD_S_MOD_USER_DETAIL’ as name.
Add some components like shown below:
You can add more components later. I’ve kept it slim for this example.
Create two attributes in your application class like this:
Attribute Level Visibility Associated Type
S_MODEL_PAGEDETAIL Instance Attribute Public ZNAD_S_MOD_USER_DETAIL
V_SELECTED_USERNAME Instance Attribute Public XUBNAME
We will use V_SELECTED_USERNAME to get the userid of the selected user from our overview list. S_MODEL_PAGEDETAIL is the model for our page container.
Add a private instance method to your application class and name it ‘GET_USER_DETAIL’.
Implement it and copy this code to the method:
DATA lt_return TYPE bapiret2_t.
DATA lt_addtel TYPE bapiadtel_t.
DATA ls_addtel TYPE bapiadtel.
DATA lt_addsmtp TYPE bapiadsmtp_t.
DATA ls_addsmtp TYPE bapiadsmtp.
IF NOT me->v_selected_username IS INITIAL.
CALL FUNCTION ‘BAPI_USER_GET_DETAIL’
EXPORTING
username = me->v_selected_username
TABLES
return = lt_return
addtel = lt_addtel
addsmtp = lt_addsmtp.
IF NOT lt_addtel IS INITIAL.
READ TABLE lt_addtel INTO ls_addtel INDEX 1.
MOVE ls_addtel-telephone TO me->s_model_pagedetail-telephone.
ELSE.
*Just to have some data if there’s nothing maintained
MOVE ‘049007007’ TO me->s_model_pagedetail-telephone.
ENDIF.
MOVE me->v_selected_username TO me->s_model_pagedetail-user_id.
ENDIF.
Check the FM BAPI_USER_GET_DETAIL if you want to get more details later. Have in mind, that all fields have to be created as components for the page model.
Now navigate to the interface method ‘HANDLE_ON_AJAX’ and add the following code
inside the CASE:
WHEN ‘GET_DETAIL’.
me->v_selected_username = ajax_value.
me->get_user_detail( ).
ENDCASE.
This means: If the Ajax ID GET_DETAIL is send, move the send ajax value to the field v_selected_username and call the method get_user_detail.
8. Now we will build the view to show the details.
Change to the designer and navigate to the object itemFullname in our object tree.
We need to get the value ‘USERNAME’ (actually user id) when the user selects an entry in our overview list. Therefor we implement a Anonymous Function for the event ‘tab’.
Select the tab Attribut and click on the button for the field ‘tap’.
Insert the following script into the JavaScript window:
// List Get Selected Row
var context = oEvent.oSource.getBindingContext();
var value = context.getProperty(“USERNAME”);
//transport data to and from application class
reloadpageDetail(value);
I think it’s easy to unserstand what’s going on here, even if you are not familiar with JavaScript, right?
Select the page container pageDetail. Fill the following fields on the general tab:
Titel: User Detail
Model Source: Bind the structure S_MODEL_PAGEDETAIL from the application class.
Ajax ID: GET_DETAIL
Check the box at ‘Prevent reload at initialization’. Important: In RC2 this checkbox is no longer available.
Model Recieve: Select pageDetail from the dropdown
Model Send: Select pageDetail from the dropdown
Important: In RC2 the number of models is unlimited now. Use the button beside the AJAX ID to select the model you want to receive data from:
For RC1: To prevent the reload of this page is very important. Remember, that the SAPUI5 application is just one page. If we wouldn’t prevent the reload of the detail page it would happily send the Ajax ID, fill the data and immediately navigate there if the application starts.
As next we will build the navigation back to the overview page.
Select the tab Attrubute for the object pageDetail.
Set navButton Type to sap.m.ButtonType.Back and showNavButton to true.
Add a Anonymous Function to the event navButton Tap and insert the following code:
// Go to a previous page
App.to(“pageOverview”);
We need to navigate to the pageDetail. This will be done if the data from the application class are lready successfully send to the view.
Stay on the Attribute tab of pageDetail and add a Anonymous Function to the event ajaxSuccess.
Insert the following code:
App.to(“pageDetail”);
As last step we need to add some fields to show our data.
Add a list to the pageDetail. Add a StandardListItem as child of the list.
Go to the Attribute tab of the item and bind the field ‘info’ to the field TELEPHONE of S_MODEL_PAGE_DETAIL.
Insert sap-icon://outgoing-call to the field icon. Insert ‘Phone’ to the field title.
Add a itemfor every field you want to show on the pageDetail.
Activate and test your application.
You detail page should show something like this (We have already added some more models):
That’s all! I hope everything went well so far and you had some fun.
Here’s the link to the running application (might change now and then):
Imagine that I have never touched SAPUI5 before, but checked the elements in the demokit. One of the neptune developers introduced me in a 1.5 hours websession to the framework.
The most confusing thing for me was the application flow using the models. So i need some hours to figure it out myself later. It’s far away from using requests and submits.
But after i got it it’s really easy. And hey guys, it’s soooo damn fast and looking awesome! I will probably never touch any other framework again 😉
The SAPUI5 framework with NAD needs only some snippets of easy JavaScript. Check it yourself. Even for grey haired ABAPers (like me) it should be very easy to understand it.
Beside that:
– Absolutely no need of oData/NWGW.
– All data transport between client/server is made by JSON, automatically generated by Neptune.
Can you imagine the increase of speed in development processes? I’m looking for a competition with someone who’s using any other tool. If they are half way through configurating their oData, i’ve already sold my app. Any bets? 😆
So far I have found only one issue: SAPUI5 doesn’t seem to work properly with some Firefox releases, check Browser Support in SAPUI5. This will hopefully get fixed soon. With Chrome or IE everything was fine. I’m using Chrome due to it’s fine console for development anyway.
As far as I know the release candidate 1 including SAPUI5 is already available. Download it here: Neptune Software
Summary:
I have no doubt the Neptune Application Designer is on the way to be established as the best HTML5 designer for SAP.
There are so many cool frameworks and features included and it’s really easy to handle them. The neptune guys always manage to implement complex stuff in a way that makes it breathtaking easy to work with it. I’ve started to train some ABAP developers so far and everyone of them was able to create his first working application in about 2 hours using jQuery Mobile.
Now I can’t await to get my hands on the SAPUI5 desktop objects in the NAD and will post a tutorial about that as soon as possible.
Until then you might check out also the new feature the neptune guys have build into the PhoneGap Addon for
creating hybrid container apps. Check one box and get an automatically created page which allows the user to log into the SAP system before the app starts. Not a single line of coding, nothing to configure.
Or the included Font Awesome framework.
Have fun!
Note: If there are any problems please use the Neptune Helpdesk
Wow
Again Ralf what an impressive demonstration of how wonderful the NAD is !!
I think definetly that it has been created by and for grey haired dev guys !! ( like me of course)
I have tested link of demo on iphone 4 ( from my bed in holidays) with chrome and safari and there are some little problem with safari ( no back button was shown).
Maybe you will share why you dont like the word "model" 🙂
Can't we consider that we are building MVC application with NAD ?
Thanks for sharing all this with us Ralf and i am waiting (on the beach with a beer and my iphone) your next tutorial on NAD 😉
Cheers
Hi Reynald,
thanks. Check the link from SAP about browser compability. It's really a pity, because the jQuery Mobile framework for instance is running on almost every browser. No idea if SAP or the browser companies will will fix it.
About the model: for me MVC means, that the model is keeping the business logic. The controller (in case of the NAD architecture it's the application class) is responsible for transporting the data from the model to the view and holds the navigation logic. You should be able to run every view on the same model without changing the model.
I case of the SAPUI5 implementation in NAD you just have datasources without any implemented logic in the attributes of the application class, so for me it's a datasource. But i'm probably a bit stubborn on that. But you can build applications using the MVC pattern with NAD for sure.
Any application that mixes business logic and the parts of the view are a wrong approach nowadays. Just imagine you have a portal application using WebDynpro ABAP and want to use SAPUI5 now to have a unique technology for all ui's in your landscape. If the business logic would be implemented in the controller methods of the WebDynpro, you would have to pull everything out and build it again.
An example: We often want to show values in a table in different colors dependent from a threshold. That's also business logic for me. So the color of the cell should be send from the model. The controller has just to transform the value into a format the view needs to show the specific color. I can't see that logic in a table or structure. But in the end it really doesn't matter how you name something if you know, what you have to do with it.
It's the same if my colleagues say: This is a reference if they point to a reference variable. For me quirky guy it's still a reference variable and not the reference itself or even the object. That's why i never use 'o' in a label 😉
Have fun at the beach! You should keep your hands of the SAP systems and use your cam for some nice bikini girl pictures so you would have something to share with us 😆
Cheers
thanks Ralf. Of course i will take off my hands from SAP systems certainly and share some moment with bikinis just near of me 🙂
Hi Ralf,
Thanx for the blog, really nice to develop a mobile app using se80. Took me a while to get it working, because i had to figure out that i had to fill in the type for the itemFullname (set it to sap.m.ListType.Navigation). Now i can navigate from the overview page to the detail page. Would be nice if you add this info to the blog.
Got two questions:
1. is it possible to make the app working without the javascript code (i mean the code at the tap event from the itemFullname) ? For an abap'er like me it would take quite some time to figure this out myself (without a blog like this)
2. can you give an example to add a picture to the detail page. I've been trying this on the example of you're previous blog (part ii) but cannot get it working. We've got pictures stored in archivelink for our employees. And this would be really nice to impress my co-workers of the it department (most of them are pro microsoft)
Hi Erik,
thanks for pointing to the missing type of the list item.
Regarding your questions:
1. SAPUI5 is using JavaScript by default. The Neptune guys encapsulated almost all JavaScript. But now and then you need to define something yourself, like the target of the navigation. That's why they implemented the JavaScript Helper which is really great. But don't worry. I wrote this tutorial at a very early stage of the SAPUI5 implementation. As usual there will be detailed information on the Neptune website for every single item soon. They will also deliver a couple of SAPUI5 examples with the upcoming releases.
We are also training the developers of every customer ( usually 2 days). Beside that i've heard they will establish a forum and a knowledgebase on their website soon. And last but not least there will be classroom trainings like this one in October: http://neptune-software.com/news/
2. Basically you just need to use a StandardListItem from the sap.m library and bind the field 'icon' to a component of the structure ZNAD_S_MOD_USER_DETAIL. I'm not familiar with archivelink. If i find the time i'll try to create an example where you can use a picture from a sap table.
Kind regards
Hi Ralf,
Thanks for your answers. Regarding point 2, retrieving the image from archive link is something i can do myself (done it before). I can place the jpg file anywhere on the sap server. What i just cannot figure out is what value to put in the src attribute of an image object. It is not the absolue path on the sap server (tried this). The relative path is something i don't know, because i don't know what it is relative to. In the examples i see (for example) /neptune/public/application/neptune_flight/images/neptune_logo2013_allyellow_xsmall.png. How does this relate to the directory structure of the server? Or am i missing the point completely?
(I understand that i have to use the imagesource field and bind this to get the image dynamically)
Hi Erik,
the usual way is to store the images into the MIME Repository of the application. That's why the path shows: /neptune/public/application/neptune_flight/images/ It's the path inside the repository.
The objects of the MIME Repository are included in the transport. I'm not sure if it works with absolute paths. What would happen, if you transport the application? So please send a mail to support@neptune-software.com
Hi Erik,
use the FM ARCHIVOBJECT_GET_URI and set the parameter objecttype to 'PREL' to get a relative path for the object. Then it should work.
Regards
Ralf-J.
Hi Ralf,
Thanks. Got it working with a picture of an employee. Even inserted a page to enter a part of the name so it doesn't show all users but only those who match (a part of) the name. Very happy with it.
Regards, Erik
Hi Ralf,
Thanks for introducing SAPUI5 to me 🙂 ...
I beleive that I have installed Neptune 2.1 ...as I can see SAP UI5 libraries ...
At step 4 ...I could not update Icon attribute with Icon I want .. how to update that attribute ..?
Secondly in the same step when I preview , atleast I should see 'Show Users' Text in the screen ...but I could not see that...just showing blank screen . Is there anything I am missing in SAPUI5 ..
Please advise..
Kind Regards
Rama
Hi Rama,
regarding the icon: You can only use the icons from https://sapui5.netweaver.ondemand.com/test-resources/sap/ui/core/Icon.html
Use sap-icon://name_of_the_icon
If you are using a wrong name the application should show an error in your JavaScript console and doesn't show up.
HTH
Hi Ralf ,
I forgot to select SAPUI5 under library , but selected just sap.m only ....
Now its working fine
Kind Regards
Rama
Great to hear it's working now. I've reported it as a bug. You shouldn't be able to select a specific framework without setting the major selection first.
Kind regards
Ralf-J.
Hi Ralf,
Thanks ,
One more thing noticed y'day after RC2 upgrade , this was not working . But you already addressed it here in this blog ... thanks for that .
Great!!Keep going 🙂
KR
Rama
Hi Ralf,
Thanks for the refreshing blog. It was very helpfull to understand the concept of SAPui5 better.
Could you also provide me a topic how to use inputfields and put these to the AJAX_VALUE.
I've tried several things but I can't get it work right.
Thanks in advance.
Gr,
Dave
Hi Dave,
basically you should set a structure as model to the pagecontainer and bind your inputfield to that so it would receive and send. Njal Stabell shows this in his tutorial:
http://support.neptune-software.com/solution/categories/122856/folders/214213/articles/133528-backend-data-models-and-navigation
HTH
Kind regards
Ralf-J.