Mobilize ALV Reports – Part 2 Create JQueryMobile Web Application with Datatables plugin
In my previous blog post we created a restful service that returns with ALV metada and data. Now we will develop a jquerymobile web client that calls this service and represents data in jquery datatables plugin.
Part 1 – Create RESTful service
Part 3 – Visualize ALV Data with Highcharts for iPad
Creating JqueryMobile Web Application
Pre-requisites:
- It is assumed that you are already familiar with HTML and the basic javascript usage
- Check over jquery ajax: http://api.jquery.com/jQuery.ajax
- Check over jquerymobile fundamentals & documentation: http://jquerymobile.com/demos/1.1.1/docs/about/intro.html
- Check over datatables usage: http://datatables.net
Steps:
- Create jquerymobile web page
- Call restful service to get alv data
- Parse alv metadata to create columns of datatables
- Initialize datatables plugin with alv data
index.html
<!DOCTYPE html>
<html>
<!–<html manifest=”app.appcache”>–>
<head>
<title></title>
<meta http-equiv=”Content-Type” content=”text/html; charset=UTF-8″>
<meta name=”apple-mobile-web-app-capable” content=”yes”/>
<meta name=”viewport” content=”width=device-width, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no” />
<link rel=”shortcut icon” href=”images/mysapreport.jpg” />
<link rel=”stylesheet” href=”css/jqm/jquery.mobile-1.1.1.min.css” />
<!– DataTables CSS –>
<link rel=”stylesheet” type=”text/css” href=”css/datatables/jquery.dataTables.css”/>
<link rel=”stylesheet” type=”text/css” href=”css/datatables/ColVisAlt.css”/>
<script src=”js/jqm/jquery-1.7.2.min.js”></script>
<script src=”js/jqm/jquery.mobile-1.1.1.min.js”></script>
<!– DataTables –>
<script type=”text/javascript” src=”js/datatables/jquery.dataTables.min.js”></script>
<script type=”text/javascript” src=”js/datatables/ColVis.min.js”></script>
<script type=”text/javascript” src=”js/datatables/TableTools.min.js”></script>
<script type=”text/javascript” src=”js/settings.js”></script>
<script type=”text/javascript” src=”js/table.js”></script>
<script>
$.support.cors = true;
jQuery.support.cors = true;
</script>
</head>
<body>
<div data-role=”page” id=”alv” data-theme=”e”>
<div data-role=”header” data-position=”fixed”>
<h1>ALV</h1>
<a href=”#settings” data-role=”button” data-icon=”gear” data-theme=”b”>Settings</a>
</div>
<div data-role=”content” >
<div data-role=”fieldcontain”>
<label for=”transaction”>Transaction:</label>
<input type=”text” name=”transaction” id=”transaction” value=”” />
</div>
<div data-role=”fieldcontain”>
<label for=”variant”>Variant:</label>
<input type=”text” name=”variant” id=”variant” value=”” />
</div>
<a href=”javascript:getALV()” data-role=”button” data-icon=”grid” data-theme=”b”>Call Report</a>
<br>
</div>
</div>
<div data-role=”dialog” id=”settings”>
<div data-role=”content” >
<label for=”connectUrl”>Connect to:</label>
<input type=”url” name=”connectUrl” id=”connectUrl” value=”” data-mini=”true” />
<label for=”username”>Username:</label>
<input type=”text” name=”username” id=”username” value=”” data-mini=”true” />
<label for=”password”>Password:</label>
<input type=”password” name=”password” id=”password” value=”” data-mini=”true” />
<br>
<a href=”javascript:exitSettings()” data-role=”button” data-icon=”delete”>Exit</a>
<a href=”javascript:saveSettings()” data-role=”button” data-icon=”check” data-theme=”b”>Save</a>
</div>
</div>
<div data-role=”page” id=”showDatatable” data-theme=”e” data-add-back-btn=”true” data-dom-cache=”true”>
<div data-role=”header” data-position=”fixed”>
<h1 id=”datatableHeader”>ALV</h1>
<div class=”ui-btn-right”>
<a href=”#chartRules” data-role=”button” data-icon=”star” data-theme=”e” data-back=”true”>Chart</a>
</div>
</div>
<div data-role=”content”>
<div id=”dynamicDatatableDIV” >
<!–<table id=”dynamicDatatable” class=”tbl_basket_style”></table>–>
</div>
</div>
</div>
</body>
</html>
Call Restful Service:
function getALV(){
alvData = [];
alvMetadata = [];
$.ajax({
type: “GET”,
url: ‘http://‘ + $(“#username”).val() + ‘:’ + $(“#password”).val() + ‘@’ + $(“#connectUrl”).val() + ‘?tcode=’ + $(“#transaction”).val() + ‘&variant=’ + $(“#variant”).val(),
data: “”,
dataType: “jsonp”,
contentType: “application/javascript”,
username:$(“#username”).val(),
password:$(“#password”).val(),
jsonpCallback:”jsonp_success”,
crossDomain: true,
cache: false,
timeout: 10000,
xhrFields: {
withCredentials: true
},
beforeSend: function(xhr, settings){
$.mobile.showPageLoadingMsg();
},
complete: function(xhr, textStatus) {
$.mobile.hidePageLoadingMsg();
if (alvMetadata){
createDynamicTable(getColumnData(alvMetadata),alvData);
$.mobile.changePage(‘#showDatatable’);
$(‘#datatableHeader’).text(reportDescription);
}
},
success: function(sys){
},
error: function( result ){
if (result.statusText !== “success”){
alert(‘Error!! Unable to call ALV Report. Please check your settings & SAP connection’);
$.mobile.changePage(‘#settings’);
}
}
}); // Ajax posting
}
function JSONP_SUCCESS(result){
reportDescription = result.description;
alvMetadata = result.alvMetadata;
alvData = result.alvData;
//sort ALV metadata according to col_pos
alvMetadata.sort(function(a,b) {
return (parseInt(a.col_pos) > parseInt(b.col_pos)) ? 1 : ((parseInt(b.col_pos) > parseInt(a.col_pos)) ? -1 : 0);
} );
}
Datatables Columns Creation
function getColumnData(alvMetadata){
var column = new Array();
var type;
var just;
var sclass;
var visible;
var visCount = 0;
for(i=0;i<alvMetadata.length;i++){
type = alvMetadata[i].inttype;
just = alvMetadata[i].just;
visible = alvMetadata[i].no_out;
switch (type){
case ‘D’:
type = “date”;
break;
case ‘N’:
type = “string”;
break;
case ‘P’:
type = “numeric”;
break;
case ‘I’:
type = “numeric”;
break;
case ‘F’:
type = “numeric”;
break;
default:
type = “string”;
break;
}
switch (just){
case ‘L’:
sclass = “left-align”;
break;
case ‘R’:
sclass = “right-align”;
break;
case ‘C’:
sclass = “center-align”;
break;
default:
sclass = “left-align”;
break;
}
if (visible == ‘X’ || visCount > 5)
visible = false;
else{
visible = true;
visCount++;
}
column.push({
“mDataProp”:alvMetadata[i].fieldname.toLowerCase(),
“sName”: alvMetadata[i].fieldname,
“sTitle”: alvMetadata[i].seltext,
“sType”: type,
“sClass”: sclass,
“bVisible”: visible
});
}
return column;
}
Initialize Datatables
function createDynamicTable(aColumnData,aDataSet){
$(‘#dynamicDatatableDIV’).html( ‘<table id=”dynamicDatatable” class=”tbl_basket_style”></table>’ );
var alvTable = $(‘#dynamicDatatable’).dataTable( {
“sDom”: ‘rfCtip’,
“bStateSave”: true,//length, filtering, pagination and sorting not change when refresh(cooki)
“sPaginationType”: “full_numbers”,
“iDisplayLength”: 65536,
“oColVis”: {
“bRestore”: true
},
“bUseRendered”: false,
“aaData”: aDataSet,
“aoColumns”: aColumnData
} );
}
Test
After publishing service on your own system, you can call it only by editing settings in MySapReport . Web client saves your settings on localstorage except password. Password is saved on sessionstorage. So don’t need to edit connection url and username in each visit of client application but password is asked for each session.
You can run demo with empty settings.
If you want, you can publish client as BSP pages on sap ITS. For step by step instructions read John Moy’s blog .
You can find all sources codes on https://github.com/basarozgur/MySapReport
Screen Shots:
Transaction code entry
Settings
Report Data
Datatables Show / Hide Columns
Hi,
Nice work Basar.
Cheers,
Syam.
Amazing! Wow! Just been learning and using BSP + jQueryMobile for a payroll app (John Moy inspired) and launchpad BUT I still have a tremendous amount of background to learn.
Did I see correctly that you used Python?
Hi Steve,
Only jquery and compatible plugins are used. Html+Css+Javascript enough for client side.
If you check whole blog series, you will find all sources that you need. please feel free to ask questions at any point..
It was over in your Github account where I saw the , main.py.
I do have a question about using the cache manifest with BSP. Specifically about linking to the jquery, jqueryui and jquerymobile links. How do I use/code that in a BSP? Currently I am linking stylesheet to http://code.jquery...css and the scripts to http://code.jquery....min.js and mobile.js. From what I have read, I can copy these to the MIME and use them from there. But haven't found example code on how to use mime at a public level.
Since our project is primarily focused on mobile html5, having the jquery coding in cache would simply and speed it up.
Could you point me somewhere? Or indicate what I missed?
Thanks!
Hi,
There is a main.py file because i use google app engine to host my application and app engine only let you host java, phyton or go projects.
I prefer to use CDN hosting for jquery files. You can find more info on http://jquerymobile.com/download/.
Also there is a clear explanation on John Moy 's blog about using libraries in MIME