Application Development Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 
GrahamRobbo
Active Contributor

I have been building web user interfaces with SAP technology for many years now. I have been through the challenges of middleware solutions provide by SAP and partners. Danced with the many generations of the ITS, negotiated with the various components of the Mobile Engine so they will play nice together, and bounced off the multiple personalities of Web Dynpro.

But for me I have always found server-side scripting the best way to build web user experiences. In the SAP world this is most commonly seen as the Business Server Pages (BSP) framework but server-side scripting is the same technique used with ASP, JSP, Python, PHP, Ruby, node.js, etc. In this paradigm the HTTP request from the browser client is processed on the server which returns a payload that typically contains HTML and client-side ECMAScript which is then rendered by the browser. Pretty sophisticated user experiences can be built this way but for me server-side scripting brings up images of hourglasses as the user waits for the server to process and respond to the current request.

This paradigm is now changing - albeit in somewhat subtle ways. The best description I have seen of this is the "single page web". Very broadly this means there is a single HTTP request/response cycle that returns pretty much all the HTML and client-side script that the browser needs to provide the user experience. Then further resources are retrieved and loaded as required asynchronously - which is to say in the background without having to block the user experience. i.e. No hourglasses.

In the SAP world NetWeaver Gateway has an important role to play here. It is the framework that provides simple REST-based API services that expose backend functionality and return a data payload - typically using the OData protocol. NW Gateway provides a very clear separation between user experience and backend so that you can use any tools or technologies you like to create the front-end UI that interacts with the backend API's.

In the past few months I have been approached by several of my long-term customers seeking to rebuild the user interfaces I created for them earlier this century. They were happy with the functionality of the applications but wanted them "renewed" so they looked better on Apple iOS devices. One example is a warehouse management application I originally built for PPC devices. The customer is replacing these devices with scanner-equipped iPods because they are significantly cheaper than the ruggedised terminals they had been using. As part of this replacement they want the screens to better match the native iOS experience.

I considered using the SAP UI5 framework as the basis for the new UX. After all it is SAP's favoured solution for this type of scenario and the customers were keen to use it. However I went in another direction and I would like to explain why.

Back to first principles. Here is a piece of sample HTML that demonstrates some of the standard user interface elements available to the web developer - many of which I used in my original applications. There are text fields, buttons, checkboxes, radio buttons, etc.

<!DOCTYPE html>
<html>
          <head>
                      <meta name="viewport" content="width=device-width, initial-scale=1">
          </head>
          <body>
                    <h1>HTML Example</h1>
                    <p>Sample text and <a href="#" >links</a></p>
                    <ul>
                            <li>List Header</li>
                            <li>Read-only list item</li>
                            <li><a href="#">Linked list item</a></li>
                    </ul>
              <fieldset>
                              <input type="radio" name="radio-choice-b" id="radio-choice-1-b" value="choice-1" checked="checked" />
                              <label for="radio-choice-1-b">Radio Button 1</label>
                              <input type="radio" name="radio-choice-b" id="radio-choice-2-b" value="choice-2" />
                              <label for="radio-choice-2-b">Radio Button 2</label>
                              <input type="radio" name="radio-choice-b" id="radio-choice-3-b" value="choice-3" />
                             <label for="radio-choice-3-b">Radio Button 3</label>
              </fieldset>
              <fieldset>
                              <input type="checkbox" name="checkbox-b" id="checkbox-b" checked="checked" />
                              <label for="checkbox-b">Checkbox 1</label>
                              <input type="checkbox" name="checkbox-b" id="checkbox-c" />
                              <label for="checkbox-c">Checkbox 2</label>
                              <input type="checkbox" name="checkbox-b" id="checkbox-d" />
                              <label for="checkbox-d">Checkbox 3</label>
              </fieldset>
                    <fieldset>
                              <input type="radio" name="radio-view-b" id="radio-view-a-b" value="list" checked="checked"/>
                              <label for="radio-view-a-b">On</label>
                              <input type="radio" name="radio-view-b" id="radio-view-b-b" value="grid"  />
                              <label for="radio-view-b-b">Off</label>
                    </fieldset>
                    <select name="select-choice" id="select-choice-b">
                              <option value="standard">Option 1</option>
                              <option value="rush">Option 2</option>
                              <option value="express">Option 3</option>
                              <option value="overnight">Option 4</option>
                    </select>
                    <p><input type="text" value="Text Input" /></p>
                    <p><input type="range" name="slider" value="50" min="0" max="100" /></p>
                    <button>Button</button>
          </body>
</html>

When I open this page in the iPhone browser it looks like this.

My example wont all fit on an iPhone screen so I will mainly use the iPad for my screen shots

This works and it sort of looks okay - we could certainly pretty it up a bit if we wanted - but it would take quite a bit of effort to make it look anything resembling a native iOS application. Fortunately other people have already done the heavy lifting for us. There are plenty of examples freely available but I am going to use JQuery Mobile.

The JQuery Mobile framework makes use of HTML5 data- attributes for markup based initialization and configuration of widgets. For example the attribute data-role="header" defines the page header area. You do not have to use these attributes but it certainly makes this process easier. So I take our HTML example from above, add some div tags and plenty of data- attributes then load the JQuery Mobile framework from the CDN as described on the Jquery Mobile download page/.

I also added some HTML for a Home button and a Navigation button to the header area and had them render as icons.

My HTML now looks like this - a little more verbose (and for some reason poorly formatted) but in essence the same as before. If I remove the loading of the JQuery Mobile framework the page renders exactly the same as my original example.

<!DOCTYPE html>
<html>
<head>
   <meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.3.1/jquery.mobile-1.3.1.min.css" />
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://code.jquery.com/mobile/1.3.1/jquery.mobile-1.3.1.min.js"></script>
</head>
<body>
<div class="preview ui-shadow swatch">
<div class="ui-header ui-bar-b" data-swatch="b" data-theme="b" data-form="ui-bar-b" data-role="header" role="banner">
  <a class="ui-btn-left ui-btn ui-btn-icon-notext ui-btn-corner-all ui-shadow ui-btn-up-b" data-iconpos="notext" data-theme="b" data-role="button" data-icon="home" title=" Home ">
   <span class="ui-btn-inner ui-btn-corner-all">
    <span class="ui-btn-text"> Home </span>
    <span data-form="ui-icon" class="ui-icon ui-icon-home ui-icon-shadow"></span>
   </span>
  </a>
  <h1 class="ui-title" tabindex="0" role="heading" aria-level="1">JQueryMobile Sample</h1>
  <a class="ui-btn-right ui-btn ui-btn-icon-notext ui-btn-corner-all ui-shadow ui-btn-up-b" data-iconpos="notext" data-theme="b" data-role="button" data-icon="grid" title=" Navigation ">
   <span class="ui-btn-inner ui-btn-corner-all">
    <span class="ui-btn-text"> Navigation </span>
    <span data-form="ui-icon" class="ui-icon ui-icon-grid ui-icon-shadow"></span>
   </span>
  </a>
</div>

<div class="ui-content ui-body-b" data-theme="b" data-form="ui-body-b" data-role="content" role="main">

  <p>Sample text and <a class="ui-link" data-form="ui-body-b" href="#" data-theme="b">links</a>.</p>
  <ul data-role="listview" data-inset="true">
            <li data-role="list-divider" data-swatch="b" data-theme="b" data-form="ui-bar-b">List Header</li>
            <li data-form="ui-btn-up-b" data-swatch="b" data-theme="b">Read-only list item</li>
            <li data-form="ui-btn-up-b"><a href="#">Linked list item</a></li>
  </ul>
       
  <div data-role="fieldcontain">
      <fieldset data-role="controlgroup">
    <input type="radio" name="radio-choice-b" id="radio-choice-1-b" value="choice-1" checked="checked" />
          <label for="radio-choice-1-b" data-form="ui-btn-up-b">Radio Button 1</label>
    <input type="radio" name="radio-choice-b" id="radio-choice-2-b" value="choice-2" />
          <label for="radio-choice-2-b" data-form="ui-btn-up-b">Radio Button 2</label>
    <input type="radio" name="radio-choice-b" id="radio-choice-3-b" value="choice-3" />
          <label for="radio-choice-3-b" data-form="ui-btn-up-b">Radio Button 3</label>
      </fieldset>
      <fieldset data-role="controlgroup">
    <input type="checkbox" name="checkbox-b" id="checkbox-b" checked="checked" />
    <label for="checkbox-b" data-form="ui-btn-up-b">Checkbox 1</label>
    <input type="checkbox" name="checkbox-b" id="checkbox-c" />
    <label for="checkbox-c" data-form="ui-btn-up-b">Checkbox 2</label>
    <input type="checkbox" name="checkbox-b" id="checkbox-d" />
    <label for="checkbox-d" data-form="ui-btn-up-b">Checkbox 3</label>
      </fieldset>
  </div>
  <div data-role="fieldcontain">
   <fieldset data-role="controlgroup" data-type="horizontal">
    <input type="radio" name="radio-view-b" id="radio-view-a-b" value="list" checked="checked"/>
    <label for="radio-view-a-b" data-form="ui-btn-up-b">On</label>
    <input type="radio" name="radio-view-b" id="radio-view-b-b" value="grid"  />
    <label for="radio-view-b-b" data-form="ui-btn-up-b">Off</label>
   </fieldset>
  </div>
 
  <div data-role="fieldcontain">
   <select name="select-choice" id="select-choice-b" data-native-menu="false" data-theme="b" data-form="ui-btn-up-b">
    <option value="standard">Option 1</option>
    <option value="rush">Option 2</option>
    <option value="express">Option 3</option>
    <option value="overnight">Option 4</option>
   </select>
  </div>
 
  <input type="text" value="Text Input" class="input" data-form="ui-body-b" />
 
  <div data-role="fieldcontain">
   <input type="range" name="slider" value="50" min="0" max="100" data-form="ui-body-b" data-theme="b" data-highlight="true" />
  </div>
 
  <button data-icon="star" data-theme="b" data-form="ui-btn-up-b">Button</button>
</div>
</div>
</body>
</html>

A quick refresh of the browser and it looks like this.

Quite a difference - and all I did was add a few data- attributes and load the JQuery Mobile framework. We can modify the theme extensively if we choose to. It looks pretty good on a iPhone as well.

If I build a screen using SAP UI5 that contains the same user interface elements it could look like this.

Again we can modify the theme extensively to suit our needs - I just used the default for this example. Please don't get caught up comparing the appearance of my two very simple examples.

The real difference here is the code for building the SAP UI5 screen. Here it is.

<!DOCTYPE HTML>
<html>
<head>
  <meta charset="UTF-8">
  <title>SAPUI5 Mobile Sample</title>
  <style type="text/css">
  </style>
  <script src="../../../resources/sap-ui-core.js"
   id="sap-ui-bootstrap"
   data-sap-ui-libs="sap.m"
   data-sap-ui-theme="sap_mvi">
  </script>
  <script>
  jQuery.sap.require('sap.m.Input');
  var oApp = new sap.m.App("myApp", {initialPage:"page1"}),
   // page
   oPage1 = new sap.m.Page("page1", {
    customHeader: new sap.m.Bar({
     contentLeft: [new sap.m.Button({icon: sap.ui.core.IconPool.getIconURI("retail-store")})],
     contentMiddle: [new sap.m.Label({text: "SAP UI5 Example"})],
     contentRight: [new sap.m.Button({icon: sap.ui.core.IconPool.getIconURI("notes")})]
    }),
    content: [
     new sap.m.HBox({
      items:[
       new sap.m.Text({text: "Sample text and "}),
       new sap.m.Link({text : "links", press : function() {app.to("page2");}}),
      ]
     }),
     new sap.m.List({
       headerText : "List Header",
       items: [
        new sap.m.DisplayListItem({label: "Read-only list item"}),
        new sap.m.StandardListItem({title : "Linked list item",type : "Navigation"})
       ]
     }),
     new sap.m.VBox({
      items:[
       new sap.m.RadioButton({
        text: "Radio Button 1",
        selected: true,
        groupName:"group1"
       }),
       new sap.m.RadioButton({
        text: "Radio Button 2",
        groupName:"group1"
       }),
       new sap.m.RadioButton({
        text: "Radio Button 3",
        groupName:"group1"
       }),
      ]
     }),
     new sap.m.VBox({
      items:[
       new sap.m.CheckBox({selected:true, visible:true, enabled: true, text: "Checkbox 1"}),
       new sap.m.CheckBox({selected:false, visible:true, enabled: true, text: "Checkbox 2"}),
       new sap.m.CheckBox({selected:false, visible:true, enabled: true, text: "Checkbox 3"}),
      ]
     }),
     new sap.m.VBox({
      items:[
       new sap.m.Switch(),
       new sap.m.Select({
        title: "Select header",
        items: [
         new sap.ui.core.Item({key: "1", text: "Option 1"}),
         new sap.ui.core.Item({key: "2", text: "Option 2"}),
         new sap.ui.core.Item({key: "3", text: "Option 3"}),
         new sap.ui.core.Item({key: "4", text: "Option 4"}),
        ],
        selectedKey: "1"
       }),
       new sap.m.Input({placeholder : "Text Input"}),
       new sap.m.Slider({value: 50}),
       new sap.m.Button({
        type: sap.m.ButtonType.Default,
        text: "Button",
        icon: sap.ui.core.IconPool.getIconURI("add-favorite")
       }),
      ]
     })
    ]
   });
  oApp.addPage(oPage1);
  oApp.placeAt("body");
  </script>
</head>
<body id="body" class="sapUiBody"></body>
</html>

Again it is not a lot of code if you measure it in lines - but notice that it is all JavaScript.

The JQuery Mobile example really draws on the "progressive enhancement" strategy of web design. Essentially this means it seeks to start at a lowest common denominator level of browser capability and build up from there. So we started with pretty simple HTML elements that can be rendered by most browsers and then the JQuery Mobile framework enhances these elements in a layered fashion based upon the capabilities of the specific browser. The elements will render as feature-rich as the browser makes possible.

In some respects SAP UI5 does the same thing - it is after all built upon JQuery, JQueryUI and JQuery Mobile. But it is more focused on contemporary browsers and therefore can't be expected to work on all of them. Our JQuery Mobile example would still render the HTML elements on even the most rudimentary web browser whereas the SAP UI5 elements at least require a browser that supports JavaScript.

Getting back to my customers, who want me to renew their user interfaces, I have found it made much more sense to use frameworks like JQuery Mobile to "enhance" the existing screens than to rewrite them. The main advantages are that I can deliver the new screens in a much quicker timeframe and that these screens would continue to work on the old PPC devices using a single code line.

On the other hand if I was building a completely new set of screens from scratch, and confident that all devices would use contemporary browsers, then SAP UI5 becomes a much more attractive option.

Finally a caveat. This blog is not even close to an in-depth look at JQuery Mobile or SAP UI5. Nor is it a comparison of the capabilities of each framework. In none of my examples did I even touch upon the fairly important aspects of user event handling, page or view navigation, calling the backend, etc. Please don't treat it as such.

Thanks

Graham Robbo

17 Comments