Quantcast
Channel: SAPUI5 Developer Center
Viewing all 789 articles
Browse latest View live

Interactive 3D Graphics With Three.js & WebGL

0
0

From OpenGL to WebGL

 

WebGL is as a part of HTML5 and based on OpenGL ES 2.0. It provides an API for 3D graphics, so JavaScript developers can program 3D-applications without any plugins or enhancements. Simply put, you can say it like this: WebGL extends the capabilities of modern UI-Development. Beside classical browser games you can create high-class, interactive content, which is normally known from desktop applications.

 

1. Live Demo

 

To give you a little impression of WebGL, i created a little demo for our beloved SCN. At the time of writing this blog post, only Chrome and Firefox can run this application: Launch Demo

 

This little showcase has the following features.

 

  • Complete first-person-controls, based on HTML5 Pointer-Lock-API
  • Collision detection, so the player can't walk through objects
  • Lens flare effects
  • Interactive objects
  • A complete UI based on jQuery and Twitter Bootstrap
  • Sky-Textures (CubeMap)
  • Floor texture with diffuse, bump and specular map
  • WebGL detection
  • A object-oriented, component-based design pattern

 

You can download the complete source-code at github.

 

2. WebGL is amazing! Where do i begin?

 

WebGL is a quite challenging API, so you have to conform to certain requirements.

 

  • You have to master JavaScript programming perfectly. Because WebGL applications are getting complex very fast, you will need good skills in code management and design patterns. You find a lot of ebooks and literature in the internet or at amazon, e.g.: The Definitive Guide: Activate Your Web Pages
  • Then i recommend to learn WebGL API, although you won't program directly with WebGL, but with Javascript 3D libraries like three.js. But for a basic comprehension of 3D graphics programming, it's good to know what's happening under the hood. For example, this is a very successful book for beginners: Professional WebGL Programming: Developing 3D Graphics for the Web
  • Like i mentioned before, you will normally work with a library, which encapsulates a lot of basic WebGL-coding. Three.js is a excellent option. It's powerful, complimentary and you will find many examples in the download-package, which explain step by step each appreciable technique of the framework. Have a look at the examples on the official homepage!
  • When you want to create or edit a texture, you should be familiar with GIMP (freeware) or Photoshop.
  • If you want to create 3D-models or animations by yourself, you will need a tool like the freeware Blender. Because 3D-modelling is something very special, you will need to invest a lot of time to handle this kind of software. The cool thing is: When you create models with Blender, you can easily export them in three.js-format. After that, you can import your model in your application. The necessary Blender-plugin is provided by the three.js team and can be found in the official download-package.

 

3. API-Support and future

 

WebGL is an very experimental API, so the browser support is not unrestricted. As you can see on this page, Internet Explorer will support WebGL initially with version 11. Currently Chrome and Firefox are the only browsers, which support this API satisfactorily. You should keep this information in mind, because the browser of your audience decides consequently, whether you can use WebGL or not.

 

I hope all this information motivates you to give WebGL and three.js a little chance.

 

Thanks for reading!


SAP Fiori Style Application Architecture Options

0
0

Most likely you have already come across the SAP Fiori applications and might therefore be wondering what architectural options there are to implement similar easy to use applications on top of your SAP backend systems leveraging SAPUI5 on top of SAP Gateway.

 

The potentially least complex option for SAP Fiori style applications that only require connection to one backend system, e.g. SAP ERP, is to implement all SAP Gateway and SAPUI5 components onto that backend system.

Fiori simplest architecture.jpg

Once you require connections to more than one backend system, e.g. to SAP SRM in addition to SAP ERP, an OData Hub becomes the more viable option. In this scenario it would make sense to leave the SAPUI5 frontend components on the OData Hub as long as you consume the solution locally in your corporate network and don’t require access through SAP EP.

Fiori hub architecture.jpg

If you prefer to access your SAP Fiori style applications via SAP EP, e.g. to simplify SSO, you should consider deploying the SAPUI5 components to EP and thereby form an UI Hub. However SAP does currently not support this configuration for their native SAP Fiori apps.

Fiori portal architecture.jpg

In case you would like to access further PO components like BPM or BRM it would make your solution more flexible and reusable if you accessed those components through the OData Hub as well rather than accessing them directly from SAPUI5, e.g. by combining them with SAP EP.

Fiori PO architecture.jpg

To open your SAP Fiori style applications to users outside your corporate network you could of course connect them via VPN or open up your internal network to the outside world, preferably through a DMZ, but it might be easier and architecturally more flexible to make use of the SAP Hana Cloud Platform. In this scenario you would deploy the SAPUI5 components onto the SAP Hana Cloud and use the SAP Mobile Platform, enterprise edition, cloud version in case of mobile users. Via the SAP HANA Cloud Connector you would securely connect to your OData Hub. Unfortunately SAP does currently not support this configuration for their native SAP Fiori apps.

Fiori cloud architecture.jpg

There are more architectural options, especially in detail, for your SAP Fiori style applications but the above selection should give you a good starting point to evaluate your respective strategy. Therefore I would like to mention only one more option and that is to move one or more of your core SAP backend systems to an on demand provider, e.g. SAP HANA Enterprise Cloud. In this case you would securely connect to your OData Hub via the SAP HANA Cloud Connector again.

Fiori on demand architecture.jpg

Parent child relationship for a Dropdown Box in UI Table

0
0

In this blog I will share the header item relationship  for Dropdown Box in a UI Table . Take an example like there are two Dropdown Boxes i.e One Header and other is Item Dropdown Box . When an header item is selected from Header part the corresponding items will be added in the Item Dropdown box.

 

It is easy in Normal case but a bit tricky if the Dropdown Boxes are in a UI Table , i.e When a header item is selected in any row of the UI Table then the corresponding Child Items will be added in the item Dropdown box of the same row. No other Dropdown boxes would be affected only corresponding rows will be affected.

 

I will explain  the above scenario with a simple example .

 

Scenario :    When a header item is selected in any row of the UI Table then the corresponding Child Items will be added in the item Dropdown box  of the same row only.

 

Below is an Array of Header-Items in a tabular format for simple understanding.

 

Header-Item Array :

array.PNG
Drop down boxes in UI Table

fig a.PNG

fig b.PNG

     Fig (b) : Header Items are filled in First column . I have maintained three header items as per the Array.

fig c.PNG

    Fig (c) : When  “Vegetables” is selected in the Header Part , corresponding child items are added in the same row .

fig d.PNG

fig e.PNG

     Fig (e) :  When “Fruits” is selected in the Header Part , corresponding child items are added in the same row.

fig f.PNG

     Fig ( f ) : Now  I changed the  “Fruits” to “Animals”  in the Header Part , corresponding child items are added in the same row .

 

Code Base  of  the example

 

Declaration of Array and Values


 var aData = [ ];       aData.push({"header": "Vegetables" , "item" : "Potato"});       aData.push({"header": "Vegetables" , "item" : "Brinjal"});       aData.push({"header": "Vegetables" , "item" : "Cabbage"});       aData.push({"header": "Vegetables" , "item" : "Tomato"});       aData.push({"header": "Fruits" ,     "item" : "Apple"});       aData.push({"header": "Fruits" ,     "item" : "Orange"});       aData.push({"header": "Animals" ,    "item" : "Lion"});       aData.push({"header": "Animals" ,    "item" : "Tiger"});       aData.push({"header": "Animals" ,    "item" : "Deer"});       aData.push({"header": "Animals" ,    "item" : "Zebra"});

 

Creation of UI Table

 

 var oTable = new sap.ui.table.Table({              title: "Header-Item example in Dropdown Box",              visibleRowCount: 3,              firstVisibleRow: 3,              width: "500px",              selectionMode: sap.ui.table.SelectionMode.Single                                                });                       

 

Adding of First column i.e. Header column into the table

 

       //Add first column to the UI Table       var oColumn1 = new sap.ui.table.Column({              label: new sap.ui.commons.Label({text: "Header"}),              template: new sap.ui.commons.DropdownBox("header_drop",                           {                     tooltip: "Header Part",                                                            items: [                             new sap.ui.core.ListItem({text: ""}),                             new sap.ui.core.ListItem({text: "Vegetables"}),                             new sap.ui.core.ListItem({text: "Fruits"}),                                  new sap.ui.core.ListItem({text: "Animals"})                                  ],                  change:function(event){                                           fill_child_items(event);                                          }                           })                                                  });
oTable.addColumn(oColumn1);

 

Adding of Second column i.e. Item column  into the table

 

//Add Second column to the UI Table      
var oColumn2 = new sap.ui.table.Column({              label: new sap.ui.commons.Label({text: "Items"}),             template: new sap.ui.commons.DropdownBox("item_drop")                       });       oTable.addColumn(oColumn2);

 

A function for Filling Child items

 

function fill_child_items(event){ 

// Current selected value in the Header Drop down box                     
var selected_hdr = event.getParameter("newValue") ; 
// Current row index
var current_rowindex = event.getParameter('id').substring(event.getParameter('id').length-1);
// ID of the item Dropdown .
var item_dropdown_id = "item_drop-col1-row"+current_rowindex;
// Removing all items from the child Drop down
sap.ui.getCore().byId(item_dropdown_id).removeAllItems();                                   
// Adding child items  to Item Dropdown      for (var i=0 ; i< aData.length ; i++)                    {                              if(selected_hdr == aData[i].header)                                         {                                         var oItem = new sap.ui.core.ListItem();                                         oItem.setText(aData[i].item);                                         sap.ui.getCore().byId(item_dropdown_id).addItem(oItem);                                         console.log(aData[i].item);                                         }                    }                                                          };

 

Note : For every UI element added in the UI table , there is always a unique ID generated by table itself for each row .

 

Example : I have a “Dropdown”  in the 2nd column , given its id as “item_drop”  in design time .

Now in run time the id is automatically generated with the combination of Colum index and row index .

So for first row the ID of the Dropdown will be “item_drop-col1-row0”.

“col1” is column index for Dropdown .

“row0” is the row index for Dropdown.

 

Similarly for second row the id will be “item_drop-col1-row1” .

 

Below image describes the ID generation in the Table :fig g.PNG

Working with Control Extensions in UI5 - Creating F4 control

0
0

One of the key feature of SAP UI5 is developing custom UI controls. This is one of the differentiating factor from WebDynpros. In this blog I will explain how to create a new control by extending the standard controls. I have taken the example of Value Help (F4) which is very much known in WD as EVS. SAP UI5 provides something called ValueHelpField which provides hook methods to write our own logic. I will explain how to extend this control to make it generic component to get EVS kind of functionality.

 

Concepts: SAP UI5 provides extend() method for all the controls and this can be used to define sub classes. Typically each control will have properties to define the behavior of the control and each control can aggregate other controls. And also controls can have associated controls as well define events. Each control has a method called renderer which defines the look and feel of the control. In this example I will be using the default render class defined for ValueHelpField which is 'sap.ui.commons.ValueHelpFieldRenderer'.

 

How it works: The required logic is provided in the attached JS file (com.incture.commons.js). The control name is defined as 'incture.commons.ext.ExtendedValueSelector'.  Copy the file locally and rename it to .js and copy to a folder in UI5 project. For example if the folder name is evscomp in the UI5 project, the folder structure should look like below:

 

1.png

Provide the JS reference in the html file script tags.




  <script src="evscomp/com.incture.commons.js" type="text/javascript">





  </script>

 

The control provides many features like automatic data validation when user inputs data manually and if data is wrong then the control will be rendered as error. And also it provides data validation state to know the status of input value.

 

We all set to use the custom control in the application. Follow the below steps to use the control.

 

1) Define the JSON Model which provides data set for EVS.

 

    
//Create json data. We can use REST URL instead of this dummy data.                                 var      aData =                   [ {                       codeColId : "1000",                       descpColId : "Plant 1000"                  }, {                       codeColId : "2000",                       descpColId : "Plant 2000"                  }, {                       codeColId : "3000",                       descpColId : "Plant 3000"                  }, {                       codeColId : "4000",                       descpColId : "Plant 4000"                  }, {                       codeColId : "5000",                       descpColId : "Plant 5000"                  },{                       codeColId : "6000",                       descpColId : "Plant 6000"                  },];                        //Create JSON model with above test data               var oModel = new sap.ui.model.json.JSONModel();                oModel.setData({modelData : aData});               //If the data set is provided as REST service in JSON format then use the below syntax             //oModel = new sap.ui.model.json.JSONModel();               //oModel.loadData("json url");

 

 

2)  Now  create the instance of the custom control and set all the required properties. The below mentioned properties are defined for the new control. Please check the file incture.commons.ext.ExtendedValueSelector for property details.

 

                var myEVSControl = new incture.commons.ext.ExtendedValueSelector("oPlantEVSFieldId",                {                           evsSourceFieldId           : "oPlantEVSFieldId",                           evsTitle                              : "Plant EVS",                             codeLable                      : "Plant",                             descriptionLable            : "Plant Desc",                             codeColModelField            : "codeColId",                             descColModelField            : "descpColId",                             dataPath                    : "/modelData",                             valueHelpRequest : function(evt)                         {                                                   this.openEVS(this,oModel);//oModel is the model defined at the above step                          },                          change : function(evt)                          {                               this.validateInputs(evt,this,oModel);                                              }                });

 

From the above properties,

evsSourceFieldId is the id of the control.

evsTitle is the EVS dialogue title.

codeLable is the first column name in the EVS popup.

descriptionLable is the second column name in the EVS popup which usually displays the description.

codeColModelField is the bind property from JSON model. From the above dummy JSON data the first field name.

descColModelField is the bind property from JSON model. From the above dummy JSON data the second field name.

dataPath: is the path to values in the REST service.

 

Note:In case if we have defined the REST service which provides the data in JSON format then the above three properties should be from the REST service.

 

3) Add the control to layout or any container along with Label control (in this example label with text 'Plant' is defined). And the control looks like below:

2.png

As we have used the renderer of ValueHelpField the look and feel of the custom control is same ValueHelpField.

 

4) Enter focus to the text field area and press F4 button or click on the Search Help Icon, which displays the data as below:

3.png

5) Select a row and click on Ok button which puts the value back to text field area. The control provides default validations like clicking on Ok button without selecting a row. And also provides default sorting, filtering on two columns.

4.png

6) Now try entering some value which is not part of the data set. The control provides default validation and highlights the field as error.

5.png

7) Once corrected , the field turns to green indicating valid value.

6.png

8) The control provides an API method to know the field validation state. We can check the status by calling the method through the control instance variable created above - myEVSControl.getValidationState();. This method returns true/false. If returned true means the data in the text field is valid data from the given model. If false, the data is not from the data set.

 

That's it. The control can be instantiated as many times as we need in any application with different data sets. This version only supports JSON Model but easily it can be extended with OData model as well.

 

P.S: This initiative is to provide reusable components in UI5 which can be used across the UI5 developments. Looking forward to see more developments in UI5 area.

SAP Fiori Style Application PoC Architecture

0
0

While I described production ready SAP Fiori Style Application Architecture Options earlier, this blog is about a light footprint option for SAP Fiori style applications using SAPUI5 on top of SAP Gateway that is suitable for non-productive scenarios e.g. for PoCs.

 

Fiori poc architecture.jpg

 

As you can see from the diagram, this option does not require a local SAP Gateway installation but uses Gateway as a Service (GWaaS) instead, which is available  via the SAP HANA Cloud Platform. Since GWaaS is still in beta state, this option is only suitable for non-productive scenarios in the moment. Also you would have to model, develop and register your SAP Gateway services directly on the backends but would not be limited in their number. However you would need a SAP HANA Cloud Connector to connect your backend systems to the SAP HANA Cloud. I also described how to Securely expose SAP NetWeaver Application Server ABAP Services through Gateway as a Service via the SAP HANA Cloud Connector for those interested in the details.

How to use SAP UI5 in HANA Studio rev. 60

0
0

In order to install SAP UI5 in HANA studio 1.60, you need to install it first.

 

To do this, go to Help -> Install New Software

 

1.png

 

In the new screen, select the "Available Software Sites".

 

2.png

 

Add this two entries and press Ok:

  1. http://download.eclipse.org/releases/juno
  2. https://tools.hana.ondemand.com/juno

 

In the Work with, select "SAP Development Tools for Eclipse Juno".

 

3.png

 

Select UI Development Toolkit for HTML5 -> UI development toolkit for HTML5 (Developer Edition)

 

4.png

After that, the installation should be like just another software installation.

 

 

To run the "Hola, mundo" example:

 

Right click over the Project Explorer view and select New -> Project. In the New Project wizard, select SAPUI5 Application Development. 

 

6.png

 

Complete the wizard.

 

When everything has completed. And just for now, modify the index.html file, just like in the image.

 

7.png

 

To view the changes, we need to Preview it. Right click on the index.html file, select Run As -> Web App Preview.

 

8.png

 

You will have a preview and a URL. You can paste that URL in a browser and view it there.

 

9.png

Deploying SAP UI5 Applications from Eclipse

0
0

This document is a walkthrough for deploying sap UI5 Application straight from Eclipse. There are some advantages for developing sap UI5 application from Eclipse instead of NWDS. NWDS is not yet available mac os which makes it difficult for me to get the things done whereas I can use Eclipse in mac. So it makes complete sense for me to use Eclipse for SAP UI5 related development which otherwise not so easy.

 

Prerequisite -

  • You have eclipse installed in your system.
  • You already have created SAP UI5 web application module.

 

Level - Beginner

 

Here is a step by step guide for deploying UI5 application from Eclipse -

 

  • Go to eclipse and choose to install a new software from Help -> Install New Software

 

Screen Shot 2013-09-06 at 11.15.46 PM.png

 

  • Go to Eclipse Market Place and either copy the update site from right or drag the install widget from left side of the page -

 

Screen Shot 2013-09-06 at 11.21.54 PM.png

 

  • If you have copied the update site please go to install software and click on the add site provide the update site url there. Or If you have dragged the install widget into workspace you will see the following option follow the instruction and install the adapter.

 

Screen Shot 2013-09-06 at 11.27.20 PM.png

 

  • Once above steps are done you are good to add the NW application server right click on any developed application and select run on server -

 

Screen Shot 2013-09-06 at 11.31.11 PM.png

 

  • From the Popup select manually define a new server and select SAP category and select SAP Netweaver 7.2. Don't worry about server version it works for 7.3 and 7.31 too , and if you don't like it still well you can rename the server to 7.3 thats what I did .

 

Screen Shot 2013-09-06 at 11.35.06 PM.png

 

  • Click next and define the server name and instance number, Ping server and click finish you are done -

 

Screen Shot 2013-09-06 at 11.35.22 PM.png

 

  • Once done you can see the server in the application run on server popup next time and you can deploy the

application

 

Screen Shot 2013-09-06 at 11.41.20 PM.png

 

Thats all hope it helps, The constructive feedback is always welcome feel free to comment.

 

~*Thanks*~

Types of Controls in SAP UI5

0
0

This blog tells you about various types of controls available in SAP UI5.

 

  1. Complex Controls
  2. Dialog Controls
  3. Layout Controls
  4. Simple Controls
  5. UX3 Controls
  6. Value holders

 

Complex controls


It contains controls that generally allow embedding other controls, are highly flexible regarding content display, and allow to mix various design aspects to gain rich user interfaces.


  • Accordion
  • Application Header
  • Carousel
  • ColorPicker
  • Data table
  • Date Range Slider
  • Inbox
  • Menu
  • MenuBar
  • Menu Button
  • Message Bar
  • Note Taker
  • Paginator
  • Progress Indicator
  • Road map
  • Row reoeater
  • Segmented Button
  • Split Button
  • Table
  • Toolbar
  • Tree
  • TreeTable
  • VIZCharts

 

Dialog Control

 

The Dialog control usually would be used with a standard approach where the MessageBox is kind of pre-configured since it already provides typical message types. There are two various flavors of dialog controls.


  • Dialog
  • MessageBox

 

Layout Control

 

The feature set that is available with the Layout controls varies from basically designing a screen area or a page by using a divider, to providing complex layouts such as MatrixLayout or AbsoluteLayout, etc.

 

  • Absolute Layout
  • Border Layout
  • Form
  • Grid Layout
  • Horizontal divider
  • Horizontal layout
  • Matrix layout
  • Panel
  • Responsive flow layout
  • Splitter
  • Tabstrip
  • Vertical layout

 

Others Controls

 

You find information on the RichTooltip control which is available for many controls and by this category-independent.

 

  • Callout
  • Richtooptip

 

Simple Controls

 

Controls like Label, Button, Link, and TextView, etx, are some of the  basic controls since they are required and used for nearly any application design.

 

  • Button
  • FormattedText view
  • HTML
  • Image
  • Imagemap
  • Label
  • Link
  • Scrollbar
  • Textview
  • Togglebutton

 

UX3Controls

 

  • Collection Inspector
  • Dataset
  • Exactbrowser
  • Facefilter
  • Navigationbar
  • Notification bar
  • Overlaycontainer
  • Popuppositioning
  • Quickview
  • Shell
  • ThinkInspector
  • Toolpopup

 

Value Holders

 

It contains the controls that offer value lists such as ComboBox, ListBox, or DropdownBox as well as controls where the user can make interactive choices on data selection like CheckBox or RadioButtonGroup, for example.

 

  • Autocomplete
  • Checkbox
  • Combobox
  • Datepicker
  • Daterangescroller
  • Dropdownbox
  • Fileuploader
  • Inplaceedit
  • Listbox
  • Passwordfield
  • Radiobutton
  • Radiobutton group
  • Rangeslider
  • Rating indicator
  • Search Field
  • Slider
  • TextArea
  • Tristatecheckbox
  • Valuehelpfield

Working with Dialog Controls in SAP UI5

0
0

This blog tells you about types of dialog controls and how to use in SAP UI5

The Dialog control is used to display some information temporarily in a size-limited window in front of the regular application screen, without affecting/removing or modifying the currently displayed content in the main/parent window. Dialog control includes thoughts known from other technologies where traditionally we use to call the windows that appears have names such as dialog box, popup window, alert box, or message box.
It is modal that means that some user action is required before returning to the parent window is possible. To achieve this, you can create an instance of the dialog control using its constructor Dialog() (i.e., new sap.ui.commons.Dialog()). Next, you set the properties for the title and the content, make settings for the size and define other property values.
The MessageBox utility class implements some of the functionality based on the Dialog control. MessageBox defines a template that can be easily configured with the method parameters. Each method of the MessageBox class addresses a different use case: alert(), confirm(), and show().
Syntax for alert() :-
sap.ui.commons.MessageBox.alert("Your Message",'fnCallback',"title");     //fnCallback & title are optional ; but fnCallback is used to handle the event after the user responds
Example:-
sap.ui.commons.MessageBox.alert("You are refused to display the message",'',"Notification");
Output:-
alert.jpg
Syntax for confirm() :-
sap.ui.commons.MessageBox.confirm("Your message",fnCallback, "title");  //fnCallback & title are optional ; but fnCallback is used to handle the event after the user responds
Example:-
new sap.ui.commons.Button({text:"Show Message", press : dispAlert}).placeAt("content1");  // Displays a button & when is press the button, this will call the function dispAlert()
function dispAlert()        {
           sap.ui.commons.MessageBox.confirm("Are you want to display message?",rCallAlertBack, "Confirmation");
       returnfalse;
        }
function rCallAlertBack(rValue)       {
if(rValue)    //If User presses 'Ok'
            {
            sap.ui.commons.MessageBox.alert("Welcome to SAPUI5.\n You're now viewing a Simple alert message.",'',"Congrats!");
        returnfalse;
            }
else  // If the user presses 'Cancel'
           {
            sap.ui.commons.MessageBox.alert("You are refussed to display the message",'',"Notification");
            }
    }
Output:-
button.jpg
Once the user presses the button "Show Message" ; below Confirmation window will be popup
confirm.jpg
When the user presses "Ok" ; rCallAlertBack() will execute the corresponding lines of code and displays as shown below
confirm1.jpg
Syntax for show() :-
sap.ui.commons.MessageBox.show(sMessage,oIcon,sTitle,vActions,fnCallback,oDefaultAction)
where,
sMessage :Message to be displayed    
oIcon        :sap.ui.commons.MessageBox.Icon.WARNING or ERROR or INFORMATION OR CRITICAL OR SUCCESS OR QUESTION
sTitle        :title of the message box
vActions  : sap.ui.commons.MessageBox.Action.YES or sap.ui.commons.MessageBox.Action.NO.(You can also use OK or CANCEL instead of YES or NO)
fnCallback: tohandle the event after the user responds
Example:-
Here is your complete code, Copy & paste in notepad -> save as "*.html (* - anyname) and execute/run in your browser.

<!DOCTYPEHTML>

<html>

<head>

<title>Welcome | SAPUI5 Demo ::Dialog controls</title>

     <scriptsrc="resources/sap-ui-core.js"id="sap-ui-bootstrap"

           data-sap-ui-libs="sap.ui.commons"

           data-sap-ui-theme="sap_goldreflection">

           // Available Themes: sap_goldreflection, sap_platinum and By Default: High Contrast Black

     </script>

     <!-- add sap.ui.table,sap.ui.ux3 and/or other libraries to 'data-sap-ui-libs' if required -->

     <script>

     function dispAlert()   { //Display simple Alert Message

           sap.ui.commons.MessageBox.confirm("Are you want to display message?",rCallAlertBack, "Confirmation");

       returnfalse;

       }


// to call the above function, we create a simple button

     new sap.ui.commons.Button({text:"Show Message", press : dispAlert}).placeAt("content1");

  

// to get back the user selection from the above function

                   

     function rCallAlertBack(rValue)            {

       if(rValue)    //If User presses 'Ok'

                {

             sap.ui.commons.MessageBox.alert("Welcome to SAPUI5.\n You're now viewing a Simple alert message.",'',"Congrats!");

         returnfalse;

                                      }

       else  // If the user presses 'Cancel'

                {

             sap.ui.commons.MessageBox.alert("You are refussed to display the message",'',"Notification");

                }

         }


    jQuery.sap.require("sap.ui.commons.MessageBox");  // this is required since there is no direct access to the box's icons like MessageBox.Icon.WARNING

            

     function fnCallbackMessageBox1(sResult1) {           

               if(sResult1=='OK')           {

                sap.ui.commons.MessageBox.show("You are not authorized to delete this content.\n Please check your access",

                                                                                sap.ui.commons.MessageBox.Icon.WARNING,

                                                                            "Warning",

                                                                                [sap.ui.commons.MessageBox.Action.OK,sap.ui.commons.MessageBox.Action.CANCEL],

                                                                              '', sap.ui.commons.MessageBox.Action.OK);                     

                }

               else                {

                sap.ui.commons.MessageBox.alert("You are refused to display the message",'',"Notification");

                }

           returntrue;

            }


// a callback that will be called when the message box is closed again

            

     function fnCallbackMessageBox(sResult) {

              if(sResult=='OK')                    {

                    sap.ui.commons.MessageBox.show("You are not authorized to delete this content.\nCheck Access and try again",

                                                                                sap.ui.commons.MessageBox.Icon.INFORMATION,

                                                                            "Notification", [sap.ui.commons.MessageBox.Action.OK,sap.ui.commons.MessageBox.Action.CANCEL],

                                                                                 fnCallbackMessageBox1,sap.ui.commons.MessageBox.Action.OK);           

                    }

              else                        {

                    sap.ui.commons.MessageBox.show("Data deleted successfully!\n", sap.ui.commons.MessageBox.Icon.SUCCESS,"Sucess",

                                                                               [sap.ui.commons.MessageBox.Action.OK], '', [sap.ui.commons.MessageBox.Action.OK]);

                    }

          returntrue;

           }

    

   function openMessageBox() {

   /* sap.ui.commons.MessageBox.Icon.WARNING or ERROR or INFORMATION OR CRITICAL OR SUCCESS OR QUESTION

       For the buttons to be displayed, you can use values such as sap.ui.commons.MessageBox.Action.YES or sap.ui.commons.MessageBox.Action.NO.  */


     // open a fully configured message box

                   sap.ui.commons.MessageBox.show("You are not authorized to delete this content.\nCheck Access and try again",

                                                                                          sap.ui.commons.MessageBox.Icon.ERROR,"Error",

                                                                               [sap.ui.commons.MessageBox.Action.OK,sap.ui.commons.MessageBox.Action.RETRY],

                                                                               fnCallbackMessageBox,

                                                                               [sap.ui.commons.MessageBox.Action.OK,sap.ui.commons.MessageBox.Action.RETRY]);

              }

// to call the above function, we create a simple button

              new sap.ui.commons.Button({text:"Delete Content", press : openMessageBox}).placeAt("Content2");

</script>

</head>

<bodyclass="sapUiBody">

<divid="content1"></div>

<br/>

<divid="Content2"></div>

  <br/>

</body>

</html>

 

Sample Outputs:-
Once you press "Delete Content" button,
btn1.jpg
All the below message box are coded to display.
Error Dialog box:-
error.jpg
Success Dialog box:-
sucs.jpg
Notification Dialog box:-
noty.jpg
Warning Dialog box:-
Warn.jpg

Internet Explorer: A Developer's Opinion

0
0

Internet Explorer: A Story for Reflection

 

1. True Love

 

A lot of web developers should know the following scenario:

anti-ie.jpg

 

Especially in the past, when Internet Explorer 6, 7 or 8 were current releases, all these weird peculiarities of Microsoft's browser drove many developers to insanity. You had to implement workarounds and different kind of fallbacks, so your application was ready for Internet Explorer. Fortunately, frameworks like jQuery and various CSS/HTML-Templates defused this situation, because they handled nearly all platform characteristics. Despite everything, it was a time, when Internet Explorer was getting pretty discredited. Look at this:

 





See more on Know Your Meme.

 

2. Microsoft answer

 

Honestly, I have to say that Microsoft has done a much better job with the current releases of Internet Explorer. IE9 and IE10 support a lot of important features of CSS3/HTML5 and offer an improved HTML-rendering-engine.

 

That's all very well, but what happens, when you compare IE10 with Chrome or Firefox?

 

3. Some Empirical Values

 

In my company, we are currently using Windows 7 with IE9 as standard browser. Besides, Mozilla Firefox ESR is installed on each workstation as a fallback platform (so if there is an incident with IE or a security issue). Because we are primarily developing web applications, the browser is crucial factor for good user experience. Therefore, several development-teams started together a little study.

 

Some customers should work with a combination of Google Chrome and IE 10 for two month and report the user experience on each platform. The result was very interesting: Nearly nine of ten users said, working with Chrome is faster and more user-friendly than IE10.

 

Now there are some thoughts to establish Chrome as standard browser. The problem is, that approximately 5% of our applications would not run on Chrome, because they use specific functions of older Internet Explorers (chiefly .NET applications) . Furthermore we have some legacy ITS-Applications, which create error-messages, when you call them with something else than IE.

 

So the goal is: Refactoring! Next year, we are going to redevelop all ITS-applications with a newer technology stack (SAPUI5/Gateway) and totally platform independent. The same holds true for BI-Solutions, where we will use BO Design Studio prospective. A nice side-effect of this project is, that we would be able to use Chrome as a primary browser for all SAP-Solutions.

 

4. My Message for you

 

  1. Refactoring! Refactoring! Refactoring!
  2. Force good user experience. A smart browser choice is an important part of it.
  3. Always use latest browser versions. Especially when you want to work with new stuff like HTML5.

 

Thanks for reading!

HowTo run SAPUI5 on Portal - Portal Runtime Integration (Quirks & Co.)

0
0

Dear Portal-Fans,

 

time is passing by and at long last SAPUI5 itself and the SAPUI5 iView have been shipped out with SP09 and we should be able to code SAPUI5 application within the Portal now, getting rid of WDJava and taking the next level towards state-of-the-art applications.

Now hacks as described hereHowTo run SAPUI5 on Portal 7.3 together with NWDI and NWDS shouldn't be needed anymore. Unfortunately my enthusiastic thoughts have been undercut by reality... It's just not working as supposed. Indeed the new SAPUI5 iView delivered by SAP can be used to consume external SAPUI5 applications, but I could not manage to make SAPUI5 applications runnable which are sited within the Portal itself.

 

What I as a Portal Developer would like to expect is that I should be able to code a SAPUI5 application and create easily an iView out of it!

Just as well as known by usual portal applications (select application from "Portal Applications", "Copy / Paste as iView" towards the desired PCD Location)

 

To make it worse, I just was not able to create a working SAPUI5 application within the Portal Runtime by using AbstractPortalComponents.

The application is just not working as supposed... dialogs are not shown.. and it behaves weird if it renders anyway ;-(

 

To make it clear:

I want to use the Portal Runtime and I want to take advantage of it (EPCM, DSM, DomainRelaxing etc.).

 

I do not want to code my applications as a usual servlet and I do not want to just integrate it via an URL iView. I do not want to abuse the prtrw-connection or interfere via the "request.getServletResponse(true)" trick (see link above). All this would cause in ignoring the features of the Portal Runtime, too (EPCM etc.).

 

Instead I want to integrate SAPUI5 iViews within Pages together with other iViews and I want to render the whole page in embedded mode. E.g. so that the SAPUI5 dialogs could crossfade the whole page...

 

Since this expectation could not be fulfilled within SP09 (or I am just to silly to get the right point...) and I want to start with SAPUI5 NOW, I searched for a solution by my own.

 

The good news are:

I found one and since I read several blogs concerning the same issue, I want to share how I solved my issue! Maybe you can benefit from it:

 

 

Initial position and Analysis

I just created an easy SAPUI5 application showing a button. When you click this button a SAPUI5 dialog will appear. The application is an AbstractPortalComponent just adding the SAPUI5-resources, the SAPUI5 config and bootstrap and includes a little js-file containing the SAPUI5 code itself.

 

Remember that the PortalConnection is responsible for adding HEAD, TITLE and BODY tags and will add all portalspecific stuff (EPCM etc.). All things, that you are writing back into the response within your doContent-Method will be put within the body of the whole HTML response.

 

Here is the HTML response when calling it via /irj/go/portal/prtroot/<ApplicationAlias>.<ComponentName> (I set EPCF Level to zero to minimize the output for my tests)

 

<html><head><link rel="stylesheet" href="/com.sap.portal.design.portaldesigndata/themes/portal/theme_ford_development/prtl_std/prtl_std_ie6.css?v=7.30.9.0.1" /><link rel="stylesheet" href="/com.sap.portal.design.portaldesigndata/themes/portal/theme_xxx_development/glbl/glbl_ie6.css?v=7.30.9.0.1" /><script type="text/javascript">
/*HTML Business for Java, 6.0*/
ur_system = {doc : window.document , mimepath :"/com.sap.portal.design.urdesigndata/themes/portal/theme_xxx_development/common/", stylepath : "/com.sap.portal.design.urdesigndata/themes/portal/theme_xxx_development/ur/", is508 : false, domainrelaxing : "MINIMAL"};
var popup_emptydoc = "/htmlb/jslib/emptyhover.html";</script><title>QuirksTest</title><meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"></head><body class="prtlBody urFontBaseFam urScrl"> <script type="text/javascript">window["sap-ui-config"] = {theme : "sap_goldreflection",   libs : "sap.ui.commons",debug : false,trace : false};</script><script src="/sapui5/resources/sap-ui-core.js" type="text/javascript" id="sap-ui-bootstrap"></script><script SRC="/xxx.com~glob_btr~portal~admin~tools/scripts/quirkstest/start.js?2d255bbed31a92e3436e69410628ef2c" ></script><div id="QuirksTestUIRoot"></div></body></html>

 

When calling the component and clicking on the button....nothing happens...so why?

First I thought of an CSS issue but I was wrong. And finally I found the guilty one : Quirksmode!

notworking.jpg

When you change the document mode by hand back to standards (F12-->DocumentMode) suddenly the application is running as supposed.

 

Searching  a way out of hell

As I recognized that it all has to to with Quirks, I really messed-up!
SAPUI5 is not working within Quirks....hmm the whole Portal (AFP) is running in Quirks-mode...!

"Walldorf, we have a problem!"

 

So how to solve this issue? Taking the whole Portal out of Quirks is no option. (Launch the Portal and change to standard mode and you'll see, what I mean ;-))

Writing an own custom framework without Quirks is also not the desired solution for many customers. They want to keep their Ajax Framework Page.

 

I knew from the block mentioned above, that integrating SAPUI5 via an URL iView is working. This will result in an additional iframe which itself is not running in Quirksmode.

 

To let SAPUI5 work well within Portal Runtime I need two things:

1. <!DOCTYPE html> to be the first element of the HTML response and

2. <meta http-equiv="X-UA-Compatible" content="IE=edge"> to be the first meta tag within the head tag

 

Both together will ensure the html code is recognized as HTML5 and in addition the browser won't enter Quirks mode.

 

But how to achieve this for a Portal Component?

Writing and registering a custom Portal Connection is no option, since this would interfere the whole Portal.

Therefore I picked up the idea of the EnhancedResponse mentioned in How To Apply Custom Branding Using the AJAX Framework L-Shape APIs by Sven Kannengiesser. Take a look at this document how the EnhancedResponse is working...this is really cool stuff!

 

To sum it up:

 

The EnhancedResponse gives you the complete HTMLResponse of the request and lets you altering it according your wishes. And the clue is, that if your Portal Component is part of a Page it gives you the whole HTMLResponse of this page (if you run your iViews in embedded mode).

Now we are able to add the doctype as well as the meta http-equiv when we need it.

 

The solution

 

Take a look at the following code snippet. This will prevent the Page/iView from rendering in Quirksmode:

 

public void doContent(IPortalComponentRequest request, IPortalComponentResponse response)    {        EnhancedResponse enhancedResponse  = new EnhancedResponse(request, true, true);            enhancedResponse.setTitle("QuirksTest");

//       //enhancedResponse.setDocTypeToHtml5();
//        enhancedResponse.setHttpEquivMetaAtFirstPosition("X-UA-Compatible", "IE=edge");
//        enhancedResponse.include(HtmlFactory.createSAPUI5Config("sap_goldreflection", "sap.ui.commons", false, false));
//        enhancedResponse.include(HtmlFactory.createSAPUI5Bootstrap(false));        enhancedResponse.initSAPUI5("sap_goldreflection", "sap.ui.commons", false, false, false);        response.include(request,request.getResource(IResource.SCRIPT, "scripts/quirkstest/start.js"));              response.write("<div id=\"QuirksTestUIRoot\"></div>");    }

 

I wrote some convenience methods to setup the core SAPUI5 application elements.

The commented lines explain what the initSAPUI5()-method really does:

 

1. Setting the Doctype to HTML5

2. Adding the http-equiv tag at the first position (I enhanced the EnhancedResponseClass to make this work)

3. Adding the initial SAPUI5 config script part

4. Adding the SAPUI5 bootstrap

 

Finally I only need to include the JavaScript for the application itself and add the root-div where to place the SAPUI5 controls to.

 

I uploaded a SCA containing the EnhancedResponse code you need at github. It can be imported into NWDS:

https://github.com/jedrogi/EResponse4PortalAndSAPUI5.git

 

The resulting HTML Response now looks like this:

<!DOCTYPE html><html><head><meta http-equiv="X-UA-Compatible" content="IE=edge"><link rel="stylesheet" href="/com.sap.portal.design.portaldesigndata/themes/portal/theme_xxx_development/prtl_std/prtl_std_ie6.css?v=7.30.9.0.1" /><script type="text/javascript">
/*HTML Business for Java, 6.0*/
ur_system = {doc : window.document , mimepath :"/com.sap.portal.design.urdesigndata/themes/portal/theme_xxx_development/common/", stylepath : "/com.sap.portal.design.urdesigndata/themes/portal/theme_xxx_development/ur/", is508 : false, domainrelaxing : "MINIMAL"};
var popup_emptydoc = "/htmlb/jslib/emptyhover.html";</script><title>QuirksTest</title><meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"><script type="text/javascript">window["sap-ui-config"] = {theme : "sap_goldreflection",   libs : "sap.ui.commons",debug : false,trace : false};</script><script src="/sapui5/resources/sap-ui-core.js" type="text/javascript" id="sap-ui-bootstrap"></script><script SRC="/xxx.com~glob_btr~portal~admin~tools/scripts/quirkstest/start.js?e7cf8856f829a508842dc34107046ac0" ></script></head><body class="prtlBody urFontBaseFam urScrl"><div id="QuirksTestUIRoot"></div></body></html>

 

Take a look at lines 1 and 2. They are the important ones. Now calling the component and clicking on the button again gives us the desired result:

working.jpg

 

 

YEAH! SAPUI5 ROCKS!

 

I played around with this approach and was able to integrate several combinations of iViews integrated within the same page. The solution seems to work

and enables me to keep state-of-the-art within the Portal as well ;-)

 

working2.jpg

 

Open Issues

 

Unfortunately the described approach only works as long as you remain within the content area. Integrating the SAPUI5 application within the Framework Page would crash again. SAPUI5, Quirks and AFP rendering compete against each other again...

Yet I do not have a solution for it!

 

So I  hope this information will help you to make your SAPUI5 application running within the Portal Runtime. SAPUI5 is great and should play a great role in future! Also for the NetWeaver Portal!

 

Regards,

 

Jens

How to read data from a Gateway service using AJAX call and JSON Model

0
0

Hello Everyone,

 

In this blog i will tell you how to read data from a Gateway Service using AJAX call.

 

VIEW:-

 

//At first we will define the data array. I will tell you how we are going to use this data array.

 

Data =  [{

           Serial_Num : "",

           Item_Number : ""

           Comp_Number : ""

           Comp_Desc : "",

           Comp_Qty : "",

           UOM : "",

           Item_Category : "",

           Item_Text : "",

           Sort_String : "",

           Storage_Loc : "",

           Ph_Assign : "",

           Alt_Item_Grp : "",

           Priority : "",

           Mfct_Code : "",

           UsageProb : "",

           Alt_BOM : ""

}];

 

 

//Then we will define the Table

 

oTable = new sap.ui.table.Table("oTable", {

                                     title : "BOM Items",

                                         visibleRowCount : 10,

                                         selectionMode: sap.ui.table.SelectionMode.Single,

                                         navigationMode: sap.ui.table.NavigationMode.Scrollbar,

                                         width : "auto"

});

 

 

//Then we will add columns to our table

 

oTable.addColumn(new sap.ui.table.Column("ColserialNumber", {

                          label : "Sl.No.",

                          width : "50px",

                          template : new sap.ui.commons.TextView("serialNumber",{

                                    enabled : false

                          }).bindProperty("text","Serial_Num"),

                    resizable : false

                }));

 

In a similar way i have added 10 more columns to my table based on my requirement.

 

 

Now let us see how i have used the data array in my table columns.

 

As you can see from the above piece of code that i have used .bindProperty(), and inside this bindProperty i am giving the properties "text" and "Serial_Num".

 

The "text" is the property of the type of ui element we are using. Here i have used TextView so i have given property as "text". If you want to use any ValueHolder UI element then you have to give property as "value" in place of "text".

 

The "Serial_Num" is the key i have used in my data array.

 

 

Now,

We will set the model to the table so that we can read data from Gatewat service.

 

 

Controller : -

 

// Defining the model

  var oModel = new sap.ui.model.json.JSONModel();    //Defining a JSON Model

                              sap.ui.getCore().setModel(oModel );

                              oModel .setData({modelData : Data});                      //Setting the data array defined by me to the model

  oTable.setModel(oModel );                                     // I have defined the instance of table(oTable) as global

  oTable.bindRows("/modelData");                             //Performing bindRows("/modelData"), so that data gets bind to the corresponding row.

 

 

//After this making an ajax call to bind the data coming from service with our custom defined data array which is again bound to the table.

 

$.ajax({

                                  type: 'GET',

                                  url : "your_service_url",

                                  dataType: 'json',

 

                                  success: function(data,textStatus,jqXHR) {

                                                  console.log(data);                       

     },

     error : function(jqXHR,textStatus,errorThrown) {

 

     }

 

Here, console.log() is a printing statement. I am trying to print the response which i am getting from from the service in the console which looks something like this

 

console.png

 

Now, i will show you how i will map the data coming from service with my data array.

 

$.ajax({

                                  type: 'GET',

                                  url : "your_service_url",

                                  dataType: 'json',

 

                                  success: function(data,textStatus,jqXHR) {

                                                  console.log(data);                       

 

                                        for(var i = 0 ; i < data.d.results.length ; i++)

                                                                                          {

                                                  Data[i].Comp_Desc= data.d.results[i].Comp_Desc;

                                                  Data[i].Comp_Qty= data.d.results[i].Comp_Qty;

                                                  Data[i].Comp_Number = data.d.results[i].Comp_Number ;

                                             }   

                                        oTable.bindRows("/modelData");

     },

     error : function(jqXHR,textStatus,errorThrown) {

 

     }

 

Now let us see what i am doing in the success of the Ajax call.

 

Here i am running a loop on the length of the data, which i am getting from service.

 

Then manually setting each of the properties which was defined in the data array to the data coming from backend,

eg:-  Data[i].Comp_Desc= data.d.results[i].Comp_Desc;

 

You must be thinking what is this data.d.results,

 

console2.png

You can see in the screenshot above that inside the Object node(which is nothing but the data node), we have child node 'd', and this child node again has another child node 'results', which contains the actual data.

So in order to fetch the data we are traversing through this tree using data.d.results.

 

Now again there can be multiple number of data coming from backend which will bind to the rows of our table. So we are running a loop on data.d.results.length so that different sets of data are mapped to corresponding rows.

 

We are done now.

 

Let's see the result.

 

You will get something like this,

console3.png

 

 

Points to remember : -

 

1. Define the data array based on the response you are getting from the service, try to give the same name for better understanding.

2. Make sure that in each bindProperty you are doing, correct property is binded, else you will get unexpected results.

3. Whenever we will fire a read service then automatically this bindProperty() will map,for example "Serial_Num" key to the column to which it is binded.

4. Make sure the data array is set to the model and the model is set to the table.

5. Do not forget to do bindRows, in this case oTable.bindRows("/modelData");

6. Before mapping the data first take a look how response is coming from service, use console.log(data) for this.

 

Hope this blog will help.

 

There may be different ways of reading data from Gateway service.

 

But this suits me well.

 

Any feedback is welcomed.

 

Thanks.

SAPUI5 Pagination of Table on Scroll End

0
0

In my current project we had an requirement where we needed pagination to be implemented on scroll end of table but unfortunately there wasn't any scroll end API for SAPUI5 table. So we had to implement a workaround solution in jQuery to support scroll end functionality.

 

Here goes the solution

 

//Add an event delegate for oTable 
oTable.addEventDelegate({
 onAfterRendering:function() { //after rendering get the reference of the dom element  //Currently I have ripped the reference from the SAPUI5 table and binded an jquery scroll event to dom element    $('.sapUiScrollBar > div:eq(0)').bind("scroll", function () {    var self = $(this);    if (self[0].scrollHeight - self.scrollTop() == self.height()) { //Calculation to check if scroll end position is reached     var oData = oModel.getData();    oData.modelData.push({lastName: "Dente", name: "Al", checked: true, linkText: "www.sap.com", href: "http://www.sap.com", src: "images/person1.gif", gender: "male", rating: 4},
 {lastName: "Friese", name: "Andy", checked: true, linkText: "www.sap.com", href: "http://www.sap.com", src: "images/person2.gif", gender: "male", rating: 2},
 {lastName: "Mann", name: "Anita", checked: false, linkText: "www.sap.com", href: "http://www.sap.com", src: "images/person1.gif", gender: "female", rating: 3},
 {lastName: "Schutt", name: "Doris", checked: true, linkText: "www.sap.com", href: "http://www.sap.com", src: "images/person1.gif", gender: "female", rating: 4},
 {lastName: "Open", name: "Doris", checked: true, linkText: "www.sap.com", href: "http://www.sap.com", src: "images/person1.gif", gender: "female", rating: 2});    oModel.setData(oData);    oTable.rerender(); //Rerender the table once scroll end is reached    }  });
 }
}); 

 

 

I hope this workaround helps out someone who are currently looking around for solution until SAPUI5 library introduces an API.

 

Snippix Link for Internal Employees: http://veui5infra.dhcp.wdf.sap.corp:8080/snippix/#85438

 

Download Example From Attachment

Create and Apply Custom Theme to SAPUI5 Application

0
0

Introduction –


In this blog, we will see how we can create custom theme using Theme Designer tool and then how we can apply it to SAPUI5 application. You can also refer below SAP help documentation. There are few steps which are not clear while reading SAP Help documentation and hence I thought to share detailed steps in this blog.

 

References -


 

Steps -


Start theme designer using transaction /UI5/THEME_DESIGNER in backed SAP system. It will open web application with below URL https://<hostname>:<port>/sap/bc/theming/theme-designer?sap-client=<client>


Open this URL in chrome browser or Firefox or IE9. It will show below screen to select existing SAP provided themes as starting point. Select sap_goldreflection theme as template theme and click on Edit button.

ui5_theme1.jpg

Now select UI5 Control Previews and add various controls.  As per SAP help documentation, I will select Shell UI element.

ui5_theme2.jpg


You can see the original and preview for added UI element along with the Quick, Expert and CSS tab on right hand side.

ui5_theme3.jpg

As displayed below, I changed the color of various properties under Quick tab. Also I will add company logo image.

ui5_theme4.jpg

After changing color properties and adding company logo, preview of the application will look as below.

ui5_theme5.jpg

 

To save theme as draft, we need to select option Theme --> Save Draft as displayed below.

ui5_theme6.jpg

 

We can publish theme with option as Theme --> Publish

ui5_theme7.jpg

It will show below screen. Provide the required details and click on Publish.

ui5_theme8.jpg

Now custom theme is ready and we can play with different UI controls and the effect of new theme on UI elements.


 

Let’s add UI elements as Accordion, ApplicationHeader, TabStrip, Shell etc.

ui5_theme9.jpg

 

ApplicationHeader – Original

ui5_theme10.jpg

ApplicationHeader – Preview

ui5_theme11.jpg

 

TabStrip – Original

ui5_theme12.jpg

TabStrip – Preview

ui5_theme13.jpg

 

Shell – Original

ui5_theme14.jpg

Shell – Preview

ui5_theme15.jpg

 

We can also add any SAPUI5 applications which are deployed to SAP application server to see the effect of custom theme. As displayed below, provide the link (Application URL) and name of the application and click button Add.

ui5_theme16.jpg

The preview will show the application in custom theme.

ui5_theme17.jpg

 

Let’s see how custom theme can be applied to standalone SAPUI5 application. To do that, we need to download the custom theme from backed SAP system.

Download theme using transaction /UI5/THEME_TOOL.

ui5_theme18.jpg

Once it is downloaded, zip file will be created with below kind of sub-folder structure.

ui5_theme19.jpg

We need to upload the content of UI5 sub folder.

ui5_theme20.jpg

We need to create folder resources and there upload sub-folders sap, ui and uiext.

ui5_theme21.jpg

Apart from this change, Change the theme name from sap_goldreflection to custom theme cm_sap_goldreflection which is assigned to data-sap-ui-theme.

 

 

<scriptid='sap-ui-bootstrap'type='text/javascript'           

            src='resources/sap-ui-core.js'

data-sap-ui-theme='cm_sap_goldreflection'

            data-sap-ui-libs='sap.ui.commons,sap.ui.table'></script>

 

<script>

 

Below is the screen of the application with standard theme sap_goldreflection.

ui5_theme22.jpg

Below is the screen of the same application after applying custom theme cm_sap_goldreflection.

ui5_theme23.jpg

 

Note: We can also apply custom theme to SAPUI5 standalone application using URL parameter as explained below.

 

There is other way to apply theme with URL parameter. For deployed application, we need to add theme parameter sap-ui-theme=<custom_theme_id>@t<theme-root>


For e.g. Shell demokit application URL will become as below,


https://<host>:<port>/sap/public/bc/ui5_ui5/demokit/test-resources/sap/ui/ux3/Shell.html?sap-ui-theme=cm_sap_goldreflection@https://<host>:<port>/sap/public/bc/themes/~client-<client>

ui5_theme24.jpg

Below is the screen of custom SAPUI5 application which is deployed to backend SAP Application server.

ui5_theme25.jpg

 

Closing Remarks –


With Theme designer tool, we can easily create/edit custom theme and change the look and feel of SAPUI5 application as per our company branding theme.

Theme designer tool can be used to create custom theme for SAPUI5 (Desktop and Mobile Applications), Webdynpro ABAP and NWBC.


Your comments/suggestions and experience on this topic are most welcome!

 

Mobile Dev Course W3U3 Rewrite - ProductList, ProductDetail & SupplierDetail

0
0

I rewrote the mobile dev course sample app from W3U3. This post explains what I changed in the ProductList, ProductDetail and SupplierDetail views / controllers. See the links at the bottom of the opening post to get to explanations for the other areas.

 

ProductList

 

If you remember back to the Login controller (described in the previous post in this series) we arrive at the ProductList view after successfully logging in, creating the OData model for the business available at the OData service, and performing a move from the Login page to this ProductList page with oApp.to("ProductList"), the navigation mechanism that is available in the App control, inherited from NavContainer.

 

ProductList.view.js

 

Here's what the ProductList view looks like.

 

sap.ui.jsview("com.opensap.ProductList", {    getControllerName: function() {        return "com.opensap.ProductList";    },    createContent: function(oController) {        return new sap.m.Page("ProductPage", {            title: "Products",            content: [                new sap.m.List({                    headerText: "Product Overview",                    items: {                        path: "/ProductCollection",                        template: new sap.m.StandardListItem({                            title: "{Name}",                            description: "{Description}",                            type: sap.m.ListType.Navigation,                            press: [oController.handleProductListItemPress, oController]                        })                    }                })            ]        });    }
});

 

Like the previous views, this isn't actually much different from the original version. I've left out stuff that wasn't needed, and in particular the icon property of each StandardListItem was pointing at the wrong model property name, resulting in no icon being shown in the list. I've removed the icon* properties as well as a couple of list properties (inset and type).

 

What I have done, though, mostly for fun, is to write the createContent function as a single statement. This in contrast to the multiple statements in the original, but perhaps more interestingly, the whole thing looks more declarative than imperative. This will come into play when we eventually look at declarative views in XML, which are actually my prefererence, and arguably the neatest and least amount of typing ... which might surprise you. Anyway, more on that another time.

 

ProductList.controller.js

The ProductList controller is very simple; all it has to do is handle the press of the StandardListItem (see the press event specification in the view above).

 

sap.ui.controller("com.opensap.ProductList", {    handleProductListItemPress: function(oEvent) {        this.getView().getParent().to("ProductDetail", {            context: oEvent.getSource().getBindingContext()        });    }

});

 

Again, I've left out the empty boilerplate code from the original, and am just doing what's required, nothing more: getting the binding context of the source of the event (the particular StandardListItem that was pressed), and passing that in the navigation to the ProductDetail page.

 

Note that I've been sort of interchanging the word page and view here and earlier. This is in relation to the App control, which has a 'pages' aggregation from the NavContainer control. As the documentation states, you don't have to put Page controls into this pages aggregation, you can put other controls that have a fullscreen semantic, and one of those possible controls is a View.

 

 

ProductDetail

 

So we've navigated from the ProductList to the ProductDetail by selecting an item in the List control, and having that item's binding context (related to the OData model) passed to us. Here's what the view looks like.

 

sap.ui.jsview("com.opensap.ProductDetail", {    getControllerName: function() {        return "com.opensap.ProductDetail";    },    onBeforeShow: function(oEvent) {        if (oEvent.data.context) {            this.setBindingContext(oEvent.data.context);        }    },

 

So in the ProductDetail view, where we want to simply show more detail about that particular Product entity, we first make sure that the passed context is bound (to the view).


 

  createContent: function(oController) {        return new sap.m.Page({            title: "{Name}",            showNavButton: true,            navButtonPress: [oController.handleNavButtonPress, oController],            content: [                new sap.m.List({                    items: [                        new sap.m.DisplayListItem({                            label: "Name",                            value: "{Name}"                        }),                        new sap.m.DisplayListItem({                            label: "Description",                            value: "{Description}"                        }),                        new sap.m.DisplayListItem({                            label: "Price",                            value: "{Price} {CurrencyCode}"                        }),                        new sap.m.StandardListItem({                            title: "Supplier",                            description: "{SupplierName}",                            type: sap.m.ListType.Navigation,                            press: [oController.handleSupplierPress, oController]                        })                    ]                }),                new sap.m.VBox({                    alignItems: sap.m.FlexAlignItems.Center,                    items: [                        new sap.m.Image({                            src: "{app>/ES1Root}{ProductPicUrl}",                            decorative: true,                            densityAware: false                        })                    ]                })            ]        });    }

});

 

Once that's done, all we have to do is fill out the createContent function, which again is very similar to the original. Note that here I'm using two model properties together for the value of the "Price" item to show a currency value and code.

 

In the original version, there was some custom data attached to the Supplier item - specifically the SupplierId property from the Product. This was used, in the controller, to manually (and somewhat "bluntly") construct an OData Entity URL for subsequent (manual) retrieval. Of couse, you might have guessed by now what I'm going to say. Not necessary at all. More on this shortly. But it's worth pointing out that the attaching of the custom data is quite a useful and widely available facility in general. It's widely available because it's part of the Element class, from which, ultimately, all controls inherit. So you can attach custom data in name/value pairs to any control you wish, more or less.

 

Finally, let's have a quick look at that VBox control containing the product image. I took a lead from the original app and decided to prefix the relative URL (which is what is contained in the ProductPicUrl property) with the generic (non-SMP-proxied) 'sapes1' URL base. And to achieve this prefixing I just concatenated a couple of model properties - one from the named "app" model (the ES1Root) and the other being the actual image relative URL.


Ok, let's have a look at the rewritten controller. 

 

ProductDetail.controller.js

 

sap.ui.controller("com.opensap.ProductDetail", {    handleNavButtonPress: function(oEvent) {        this.getView().getParent().back();    },    handleSupplierPress: function(oEvent) {        this.getView().getParent().to("SupplierDetail", {            context: oEvent.getSource().getBindingContext()        });    }
});

 

As well as the back navigation, we have the handling of the press of the Supplier item in the ProductDetail view. This should take us to the SupplierDetail view to show us more information about the supplier.

 

So before we think about how we make this work, let's pause for a second and consider the business data that we're consuming through the OData service.

 

OData Model and Service

 

We have, in the OData service originating at https://sapes1.sapdevcenter.com/sap/opu/odata/sap/ZGWSAMPLE_SRV/, a number of EntitySets, or 'collections', including the BusinessPartnerCollection and the ProductCollection - both of which have entities that we're interested in for our app. We start out with the ProductCollection, display a list, pick a specific product for more detail, and then go to the supplier for that product. If you look at the OData metadata for this service, you'll see that in the definition of the Product entity, there's a navigation property that will take us directly from the product entity to the related business partner entity. How useful is that? Yes, very! So let's use it.

 

navprop.jpg

Before we look at how we use it, let's review how the original app was doing things here to go from the selected product detail to the supplier. In the supplierTap function of the original ProductDetail controller, the OData.read function was called explicitly (ouch), on a manually constructed OData URL (ouch), which abruptly jumped straight to the BusinessPartnerCollection, ignoring this navigation feature (double-ouch). The supplier's ID (which had been squirrelled away in the custom data as mentioned earlier) was specified directly, as a key predicate, and a JSON representation was requested:

OData.read("https://sapes1.devcenter.com/sap/opu/odata/sap/ZGWSAMPLE_SRV/BusinessPartnerCollection('" + supplierId + "')?$format=json", ...)

 

Yes, you can guess the next bit :-) The JSON data was passed directly to the next view, bypassing any semblance of OData model usage. Ouch. I guess this also bypasses the SMP URL rewriting security and should have really been the SMP-based URL. And ouch.

 

So how did we do it here? Well, just by passing the context of the selected product, as usual. Just like we did when we went from the ProductList view to the ProductDetail view. And then following on from that in the SupplierDetail view with a reference to the relative 'Supplier' entity.


 

SupplierDetail

 

SupplierDetail.view.js

 

Ok, so here's the view.

 

sap.ui.jsview("com.opensap.SupplierDetail", {    getControllerName: function() {        return "com.opensap.SupplierDetail";    },    onBeforeShow: function(oEvent) {        if (oEvent.data.context) {            this.setBindingContext(oEvent.data.context);        }    },   createContent: function(oController) {        var oPage = new sap.m.Page({            title: "{CompanyName}",            showNavButton: true,            navButtonPress: [oController.handleNavButtonPress, oController],            content: [                new sap.m.List({                    items: [                        new sap.m.DisplayListItem({                            label: "Company Name",                            value: "{CompanyName}"                        }),                        new sap.m.DisplayListItem({                            label: "Web Address",                            value: "{WebAddress}"                        }),                        new sap.m.DisplayListItem({                            label: "Phone Number",                            value: "{PhoneNumber}"                        })                    ]                })            ]        });        oPage.bindElement("Supplier");        return oPage;    }

});

 

This view looks pretty normal and doesn't differ much from the original. We have the onBeforeShow and the createContent. But the key line is this:

 

oPage.bindElement("Supplier")

 

At the point that this is invoked, there's already the binding context that refers to the specific product previously chosen, say, like this:

 

https://sapes1.sapdevcenter.com/sap/opu/odata/sap/ZGWSAMPLE_SRV/ProductCollection('HT-1007')

 

(I'm using the 'sapes1' link rather than the SMP-rewritten one here so you can navigate them from here and have a look manually if you want.)

 

Following the navigation property mentioned earlier, to the supplier (the entity in the BusinessPartnerCollection) is simply a matter, OData-wise, of extending the path to navigate to the supplier, like this:

 

https://sapes1.sapdevcenter.com/sap/opu/odata/sap/ZGWSAMPLE_SRV/ProductCollection('HT-1007')/Supplier

 

So in OData terms, we're navigating. And in path terms, we're going to a relative "Supplier", which is exactly what we're doing with the oPage.bindElement("Supplier"). The bindElement mechanism, when called on an entity in an OData model, triggers an automatic OData "read" operation, i.e. an HTTP GET request, and updates the model.  Bingo!

 

Looking at the Network tab of Chrome Developer Tools, this is what we see happens:

calls.jpg

 

The first call (ProductCollection?$skip...) was for the initial binding to "/ProductCollection" in the ProductList view. Then a product HT-1007 was selected, the App navigated to the ProductDetail view, and then the supplier item was pressed. And when the bindElement in the SupplierDetail view was called, this triggered the last call in the screenshot - to "Supplier", relative to ProductCollection('HT-1007').

 

All automatic and comfortable!

 

 

SupplierDetail.controller.js

 

sap.ui.controller("com.opensap.SupplierDetail", {    handleNavButtonPress: function(oEvent) {        this.getView().getParent().back();    }

})

 

Let's finish off with a quick look at the corresponding controller for this view. It doesn't have much work to do - just navigate back when the nav button is pressed. And it's very similar to the original.

 

So there we have it. Embrace SAPUI5 and its myriad features (automatic module loading, well thought out controls, OData models, and more) and have fun building apps.

 

That's draws this series to an end. Thanks for reading. The link to the Github repo where the rewritten app can be found is in the original post in this series, and also here: https://github.com/qmacro/w3u3_redonebasic

 

Share & enjoy!



HTML5 Web Messaging

0
0

My Iframe Dilemma

 

Last year, I had a very interesting issue in one of my projects: An external application should be embedded in a Content-Management-System via iframe. Sounds like nothing special, right? Well actually yes, but both applications should communicate, although they were hosted in different domains. Now everybody knows, that Web Browser, for security and privacy reasons, prevent documents in different domains from affecting each other. Because there was no time in this project to migrate one application to the other domain and the CMS had no Portal-Event-Mechanism, I needed an other quick and reliable solution.

 

Cross-Document Messaging

 

Cross-document messaging is a HTML5-API for sending messages between two documents safely. These documents don't have to run within the same domain, which is the actual big advantage of this technique. Besides, the API is very easy to use: With postMessage() you can send messages to other window-objects, where you can receive them via message-event. Look at the following listing:

 

1. Base-Website

 

// get iframe
var iframe = document.getElementById('externalApp');

// get window object
var iframeWindow = iframe.contentWindow || iframe.contentDocument;

// send a message to window
iframeWindow.postMessage('Hello iframe', 'http://popup.de');

 

2. Embedded Iframe

 

// EventHandler for message processing
function receiveMessage(event){     // check origin of message, because you     // process ALL message of any origin     if(event.origin == 'http://mysite.de'){          // log message in browser console          console.log(event.data);     }

}
// Register EventHandler 
// For security reasons: Don't code this, if you don't expect messages from other sides
window.addEventListener('message', receiveMessage, false);

 

As you can see, it's very simple to change messages between two documents.

 

My Guidance

 

Although HTML5 Web messaging provides a very smart API, you should use it only in exceptional situations. It's always better to keep your applications in one single domain to prevent same origin policy issue. Avoiding SOP allows you to communicate directly between multiple windows or iframes in the first place. But there is even more room for improvement! I think the best way for arranging multiple web-apps or widgets is using a portal, which normally provides a clean and powerful event-mechanism.

 

Before you start doing great things with Web Messaging, please check out this comprehensive documentation of Mozilla Developer Network to get all important details for development.

 

Thanks for reading!

Remove Default value(NO DATA) from SAPUI5 Chart(Line,Pie,Bar) and put some spinner before geting data from XSODATA service

0
0

Hi,

 

Write a java script function in your sapui5 application and put the below code for getting line chart.

 

function lineChartTest(){

 

                        var stock=sap.ui.getCore().byId("stock").getValue();

                        var exchange=sap.ui.getCore().byId("exchange").getValue();

 

                        var oModelChartt = new sap.ui.model.json.JSONModel();   

                        sap.ui.getCore().setModel(oModelChartt);

 

                        jQuery.ajax({

 

                                url: ' Put your XSODATA URL Here'

 

                                dataType: "json",

 

                               beforeSend: function() {

                                    $('#loader').show();        //This method will call before your request go to server.

                                 },

 

                                 complete: function(){     //This method would call after completion of  your request.

                                    $('#loader').hide();     //Create a div and assign a id to that div

                                 },

 

                                success: function(data, textStatus, jqXHR) { // callback called when data is received

 

                                    if (data.length == 0) {

                                        window.alert(textStatus+jqXHR);

 

                                    } else {

                                        oModelChartt.setData(data); // fill the received data into the JSONModel

                                    }

                                },

 

                                error: function(jqXHR, textStatus, errorThrown) {

 

                                    $('#errorMsg').show();

 

 

                                }

 

                            });

 

                            var dataset = new sap.viz.ui5.data.FlattenedDataset(

                                    {

 

                                        dimensions : [ {

 

                                            axis : 1,

                                            name : 'Year',

                                            value : "{YEAR_INT}"

 

                                        },

                                        {

 

                                            axis : 1,

                                            name : 'Week',

                                            value : "{WEEK_INT}"

 

                                        } ],

 

                                        measures : [ {

                                            name : 'PriceHigh',

                                            value : '{PRICEHIGH}'

                                        } ],

 

                                        data : {

                                            path : "/d/results",

 

                                        }

                                    });

                            var oTextView = new sap.ui.commons.TextView({      /* This Code will be using for remove Default value.You can replace                                                                                                                                                    'NO Data'  value  with your custom message. */

                                text : 'Please wait, loading data',

                                wrapping : false,

                                semanticColor: sap.ui.commons.TextViewColor.Negative,

                                textAlign:sap.ui.core.TextAlign.Center

                                });

 

                            var chart = new sap.viz.ui5.Line(

                                    {

 

                                        width : "800px",

                                        height : "400px",

                                         plotArea : {

                                                'colorPalette' : d3.scale.category20().range()

                                                },

 

                                        title : {

 

                                            visible :false,

                                            text : 'Stock Data'

                                        },

                                        dataset : dataset,

                                       noData :  oTextView   // just assign your custom message to  noData property

                                    });

                                chart.setModel(oModelChartt);

                                chart.placeAt("linechart","only");  //only property will help you to append chart with refreshed value

 

}

Check JSON data length and Error property in Ajax call(SAPUI5).

0
0

Hi,

 

Please find the below code that will help you to display a custom message to user if you are not finding any data from XSODATA service.

 

jQuery.ajax({

 

                url : "your URL"

 

                dataType : "json",

              

                success : function(data, textStatus, jqXHR) { // callback  called when data is received

                                                         

                   if (data.d.results.length == 0) { // if data length is 0 then it assumnes that No matching data found and append the message

                                               

                        $('#errorMsg').show();

 

                    } else {

                        // fill the received data into the JSONModel

                    }

                },

 

                error : function(jqXHR, textStatus, errorThrown) {

 

                    $('#error').show();     //This will help you to throw a message to the user if URL is not correct like (404,401 etc)

 

                }

 

            });

 

 

 

<html>

    <body>

         <div id='errorMsg' class="display">

                <p>No Data Found</p>

         </div>

        <div id='error' class="display">

                <p>404 No Found</p>

         </div>

    </body>

</html>

Generate QR Code in SAPUI5 Application using Google Chart API

0
0

In this blog, we will see how we can generate QR code using Google Chart API.

QR_CM.png

As per Wikipedia,

QR code (abbreviated from Quick Response Code) is the trademark for a type of matrix barcode (or two-dimensional barcode) first designed for the automotive industry in Japan. A barcode is an optically machine-readable label that is attached to an item and that records information related to that item. The information encoded by a QR code may be made up of four standardized types ("modes") of data (numeric, alphanumeric, byte / binary, Kanji) or, through supported extensions, virtually any type of data.

 

The QR Code system has become popular outside the automotive industry due to its fast readability and greater storage capacity compared to standard UPC barcodes. Applications include product tracking, item identification, time tracking, document management, general marketing, and much more.

 

Google Chart API provides nice way to generate QR code. You can find good details on Google's QR code API here

 

Taking reference from this website, I developed simple SAPUI5 application to generate QR code of Contact details in the MeCard format.

 

Also I am generating BusinessCard with QR code as an image on it.

 

Let's see the SAPUI5 application screen and output.

sapui5_qr1.jpg

As displayed above, I am providing contact details information and then generating MeCard type QR code and also using the same image on business card UI element.

 

Now, to decode QR code, I am using zxing online QR code decoder. Here either we can upload the QR code image file OR specify the image URL. you just need to right click on the image generated (as displayed in above screen) and provide the URL path.

sapui5_qr2.jpg

As displayed below, you will be able to see the decoded result of your QR code.

sapui5_qr3.jpg

 

You can access the code at GitHub and also can access live demo at JSBin

 

I hope you enjoyed reading this blog on QR code generation. Please feel free to put your comments/suggestions. And I hope you will be happy to generate QR code with this simple SAPUI5 application

SAPTechEd2013 USB Explorer

0
0

Hi,

 

It's currently a lunch break and I'm enjoying my first TechEd.

I was just looking at the USB of materials they provided and thought it was great, but it was hard to navigate.

 

So over lunch I though would be fun to build a very simple SAPUI5 example to help:

 

It's just a slight variant of the great examples in the SDK library:

https://sapui5.hana.ondemand.com/sdk/#test-resources/sap/ui/table/demokit/Table.html

 

I've uploaded my new HTML file, using SAPUI5, onto Google drive & attached

https://drive.google.com/file/d/0Bxydpie8Km_fSXQtZkVmVnRkZmM/edit?usp=sharing


Feel free to download and copy to your USB directory :

 

 

Then open with Google Chrome (or other browsers) [Note it needs and internet connection to run the SAPUI5 javascripts] 

 

Cheers

Aron



Viewing all 789 articles
Browse latest View live




Latest Images