Skip to Content
Author's profile photo Rui Nogueira

Using Neo and SAPUI5 – Part 2 – Hi SAP UI5, may I introduce you to Neo?

In my first blog of this series we’ve prepared the development environment to be able to start developing with Neo and SAP UI5. In this blog post we’ll create our first SAP UI5 app and will deploy it on Neo. We’ll not create a “Hello world” app, but try to be a bit more sophisticated. This app will be the ground for the next blog posts where we’ll add persistence to our app and secure it properly.

Ok. Let’s go.

The Tweets Persistence App

One of the most important goals I have with this blog series is also to address some issues you might face during your day-to-day work with SAP UI5 and Neo. For that the app needs to fulfill certain requirements. The app needs to

  • look good 🙂
  • read and write data into the persistence layer of Neo
  • be able to handle asynchronous events
  • be secured in a way that only certain users can access it
  • use both JPQL and native SQL queries

Therefore we’ll build an app that will persist tweets messages for specific search terms. The user will have two tables, where the first contains the a list of search terms and the second table the corresponding tweets for it.

So first of all we’ll create the UI in SAP UI 5.

Setting up the project

Let’s use the project that you’ve created in the first part of this blog series. Rigth-click on the project name, click on “Refactor”, “Rename” and give it another name. We’ll use the name “tweetsApp”.

Screen Shot 2012-05-03 at 16.27.49.png

After that we delete some files that we don’t need for our project. Let’s switch to the Java perspective (Eclipse menu “Window”, “Open Perspective”, “Java”) and delete the following files:

  • WebContent/index.jsp
  • WebContent/resources (all files and the resources directory itself)
  • WebContent/test-resources (all files and the resources directory itself)

Screen Shot 2012-05-04 at 08.25.25.png

Now double-click the index.html file under the WebContent folder, delete all the text in it and substitute it with the following code and save the index.html file.

<!DOCTYPE HTML>

<html>

<head>

     <meta http-equiv=“X-UA-Compatible” content=“IE=edge” />

     <title>Tweets Persistence App</title>

     <script

       src=“./resources/sap-ui-core.js”

       type=“text/javascript”

       id=“sap-ui-bootstrap”

       data-sap-ui-libs=“sap.ui.ux3, sap.ui.commons, sap.ui.table”

       data-sap-ui-theme=“sap_goldreflection”>

     </script>

     <script type=“text/javascript”>

            var aContent = {};

            // Create a SAP UI5 shell element

            var oShell = new sap.ui.ux3.Shell(“tweetAppShell”, {   

              appIcon : http://www.sap.com/global/images/SAPLogo.gif,

              appTitle : “Tweets Persistence App”,

          });

        // And now add so called WorksetItems to the shell

        // Each WorksetItem consists in our case of a NavigationItem

        // Notice that each Navigation Item is accessible via a unique key!

            var WI = sap.ui.ux3.NavigationItem;

        oShell.addWorksetItem(new WI({key : “wi_home”,   text : “All Tweets”}));

        oShell.addWorksetItem(new WI({key : “wi_tweets”, text : “Tweets per hashtag”}));

        // Just take the shell and place it in the html area called shellArea

        oShell.placeAt(“shellArea”);

       </script>

</head>

<body class=“sapUiBody” >

     <!– And here is the div element shellArea where  the shell element will be posted to–>

     <div id=“shellArea”></div>

</body>

</html>

Let’s deploy it and see what happens.

Screen Shot 2012-05-04 at 09.27.24.png

Open your browser and enter the address http://localhost:8080/tweetsApp/index.html (or another port than 8080).

You should now see something like this

Screen Shot 2012-05-04 at 09.45.06.png

The SAP UI5 library generate a lot of things for you without having to write a lot of code. For example you can click on the two navigation tabs and you’ll get a nice transition animation. Additionally SAP’s “gold reflection” theme has been applied to our app. There are other themes you can try out, but I like the gold reflection theme a lot so I’ll stay with it for now.

The app still looks  very empty because we haven’t any elements assigned to the navigation items. We’ll change that now.

Adding UI Elements

Our app will show in the “All Tweets” tab a list of all tweets that have been persisted in our database.

The tab “Tweets Per Hashtag” will show a list of hashtags we want to monitor and another list with the tweets for a selected hashtag.

To make it as easy as possible, we’ll use the DataTable element of SAP UI5.

Tools like the one I’m using here tend to grow a lot once you find them useful. You add a feature here, a nice goodie there and suddenly you have a code monster in front of you that is hard to maintain. Therefore we’ll take care from the very beginning to keep our code as maintainable and readable as possible.

Firstly we’ll create a separate JavaScript file to handle the creation of tables in our app. For that we’ll create a new folder in our WebContent folder called “tools” and a file called “buildTable.js”.

Screen Shot 2012-05-04 at 09.54.35.png

The directory should look now like this:

Screen Shot 2012-05-04 at 09.59.54.png

To be able to access this JavaScript code in our app we’ll have to add the reference to it at the beginning of our index.html file.

<script type=”text/javascript” src=”tools/buildTable.js”></script>

We’ll first take care of the smalest element of the DataTable: a column. We want to have column elements that just show text, another one that shows text with a link in it and another column where we can show a picture. Let’s add the following code to our buidlTable.js file:

var buildLinkedColumn = function (title,value,link, width){

    var field;

    if (link){

        field = new sap.ui.commons.Link();

        field.bindProperty(“text”,value);

        field.bindProperty(“href”,link);

        field.setTarget(“_blank”);

    } else {

        var fieldValue = “{” + value + “}”;

        field = new sap.ui.commons.TextField({value:fieldValue});

    }

    return     new sap.ui.table.Column().

    setLabel(new sap.ui.commons.Label({text: title})).

    setTemplate(field).

    setWidth(width).

    setSortProperty(value).

    setFilterProperty(value);

}

var buildPlainColumn = function (title,value,width){

    var fieldValue = “{” + value + “}”;

    return new sap.ui.table.Column({

        label: new sap.ui.commons.Label({text: title}),

        template: new sap.ui.commons.TextArea({value:fieldValue}),

        sortProperty: value,

        filterProperty: value,

        width: width});

}

var buildColumnWithPic = function (title,piclink,width){

    oImage = new sap.ui.commons.Image().bindProperty(“src”, piclink);   

    oImage.setWidth(width);

    oImage.setHeight(width);

    return new sap.ui.table.Column({

        label: new sap.ui.commons.Label({text: title}),

        template: oImage,

        width: “60px”});

}

So we have now three variables called buildPlainColumn, buildColumnWithPic and buildLinkedColumn. Each of these variables will return an object of the type sap.ui.table.Column that is calculated in a function. The parameters provided to these functions will be used to bind the result of a JSON object to the table data. I’ll explain this later in this blog.

Now let’s add the creation of the DataTable itself to the code. We’ll have three tables in our app. One showing a list of all tweets that have been persisted in our app, another one with a list of all hashtags and another one showing a list of tweet for a selected hashtag. We’ll create another variable called buildTable that you give the table name as parameter. After that our buildTable.js file looks like this:

var buildTable = function(tableName){

  // Only run through the code if a table name has been provided as parameter

  if (tableName) {

      // table with a list of all tweets

      if (tableName === “allTweets” || tableName === “tweetsForHashtag”) {

          var oTable = new sap.ui.table.DataTable(“table” + tableName, {

            title : “Tweets”,

            width : “100%”,

            visibleRowCount : 5,

            expandedVisibleRowCount : 10,

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

            editable : false

        });

        oTable.setRowHeight(“50px”);

        oTable.addColumn(buildColumnWithPic(“Picture”,”icon”,”48px”));

        oTable.addColumn(buildLinkedColumn(“Author”,”author”,”linkauthor”,”180px”));

        oTable.addColumn(buildLinkedColumn(“Tweet”,”tweet”,”linktweet”));

        if (tableName === “allTweets”) {

                 oTable.bindRows(“allTweets”);   

        }

        if (tableName === “tweetsForHashtag”) {

                oTable.bindRows(“tweetsForHashtag”);   

        }

        return oTable;   

     }

    if (tableName === “allHashtags”) {

        var oTable = new sap.ui.table.DataTable(“table” + tableName, {

            title : “All Hashtags”,

            width : “150px”,

            visibleRowCount : 5,

            expandedVisibleRowCount : 10,

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

            editable : false

        });

    oTable.addColumn(buildPlainColumn(“Hashtag”,”hashtag”,”90px”));

    oTable.bindRows(“allHashtags”);   

    return oTable;   

   }

   return null;

  }

  else {

    return null;

  }

};

var buildLinkedColumn = function (title,value,link, width){

    var field;

    if (link){

        field = new sap.ui.commons.Link();

        field.bindProperty(“text”,value);

        field.bindProperty(“href”,link);

        field.setTarget(“_blank”);

    } else {

        var fieldValue = “{” + value + “}”;

        field = new sap.ui.commons.TextField({value:fieldValue});

    }

    return     new sap.ui.table.Column().

    setLabel(new sap.ui.commons.Label({text: title})).

    setTemplate(field).

    setWidth(width).

    setSortProperty(value).

    setFilterProperty(value);

}

var buildPlainColumn = function (title,value,width){

    var fieldValue = “{” + value + “}”;

    return new sap.ui.table.Column({

        label: new sap.ui.commons.Label({text: title}),

        template: new sap.ui.commons.TextArea({value:fieldValue}),

        sortProperty: value,

        filterProperty: value,

        width: width});

}

var buildColumnWithPic = function (title,piclink,width){

    oImage = new sap.ui.commons.Image().bindProperty(“src”, piclink);   

    oImage.setWidth(width);

    oImage.setHeight(width);

    return new sap.ui.table.Column({

        label: new sap.ui.commons.Label({text: title}),

        template: oImage,

        width: “60px”});

}

As the table for all tweets and the table of tweets for a specific hashtag provide the same columns, we only need on if-statement for both cases.

The code will first test which table name has been provided as a parameter. Depending on the parameter it will build a DataTable element that is returned from the calling instance.

We are ready with the preparations of our UI elements.

It’s time to include the logic into our index.html file to make the UI elements show up in our app.

Show The UI Elements In Our App

There is not much we’ll have to do. We need to be able to set the content for each of the tabs separately and need to ensure that the content for the first tab is pre-filled. So we’ll have to add a little bit more code into our index.html file. This is how the index.html file looks like after adding that additional functionality. I’ve marked the added code in bold:

<!DOCTYPE HTML>

<html>

    <head>

         <meta http-equiv=”X-UA-Compatible” content=”IE=edge” />

         <title>Tweets Persistence App</title>

         <!–

         Load the SAP UI5 library into the memory and set some meta information for it

         like the libs you want to use and the theme you want to apply

         –>

         <script

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

           type=”text/javascript”

           id=”sap-ui-bootstrap”

           data-sap-ui-libs=”sap.ui.ux3, sap.ui.commons, sap.ui.table”

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

         </script>

        <script type=”text/javascript” src=”tools/buildTable.js”></script>

         <script type=”text/javascript”>

            // Create a SAP UI5 shell element

            var oShell = new sap.ui.ux3.Shell(“tweetAppShell”, {  

                  appIcon  : “http://www.sap.com/global/images/SAPLogo.gif“,

                  appTitle : “Tweets Persistence App”,

            });

            // And now add so called WorksetItems to the shell

            // Each WorksetItem consists in our case of a NavigationItem

            // Notice that each Navigation Item is accessible via a unique key!

            var WI = sap.ui.ux3.NavigationItem;

            oShell.addWorksetItem(new WI({key : “wi_home”,   text : “All Tweets”}));

            oShell.addWorksetItem(new WI({key : “wi_tweets”, text : “Tweets Per Hashtag”}));

            // Initialize the content variable

            var aContent = {};           

            // Initialize the content for the first visible tab

            oShell.setContent(getContent(“wi_home”));

            // Whenever a tab is selected in the sheet, set the content accordingly

            oShell.attachWorksetItemSelected(function(oEvent) {

                // get the key of the selected navigation item (built-in into the WorksetItem)

                var itemKey = oEvent.getParameter(“key”);

                oShell.setContent(getContent(itemKey));       

            });

            // Just take the shell and place it in the html area called shellArea

            oShell.placeAt(“shellArea”);

            // content generation and buffering

            function getContent(id) {

                    if (id == “wi_home”) {

                        if (!aContent[id]){

                            aContent[id] = [buildTable(“allTweets”)];

                        }

                    }

                    if (id == “wi_tweets”) {

                        if (!aContent[id]){

                            aContent[id] = [buildTable(“allHashtags”), buildTable(“tweetsForHashtag”)];

                        }

                    }

                return aContent[id];

            }

         </script>

    </head>

    <body class=”sapUiBody” >

         <!– And here is the div element shellArea where the shell element will be posted to–>

         <div id=”shellArea”></div>

    </body>

</html>

The first line that is bold loads the buildTable.js file into the memory so that we can use the code of it.

<script type=”text/javascript” src=”tools/buildTable.js”></script>

The next one initializes a variable that will contain the content we want to assign to each of the tab

// Initialize the content variable

var aContent = {};     

To pre-load the content for the first tab we need this:

// Initialize the content for the first visible tab

oShell.setContent(getContent(“wi_home”));

That code line calls a function called getContent that you give the unique key of the navigation tab. Depending on the id the getContent function will then return the corresponding content:

// content generation and buffering

function getContent(id) {

                    if (id == “wi_home”) {

                        if (!aContent[id]){

                            aContent[id] = [buildTable(“allTweets”)];

                        }

                    }

                    if (id == “wi_tweets”) {

                        if (!aContent[id]){

                            aContent[id] = [buildTable(“allHashtags”), buildTable(“tweetsForHashtag”)];

                        }

                    }

      return aContent[id];

}

The content is assigned only once to the tab. That’s what the if statement takes care of that starts with if (!aContent[id]). Only if the content for a specific id (in our case the key of the navigation element) is not available, yet, it will be built. If you don’t do that you’d re-create the same content again. This would lead into errors as the SAP UI5 library would notice that e.g. a table with the unique id tableallTweets is already available.

Filling the content variable has become pretty easy as we can re-use the function buildTable we’ve defined in buidlTable.js. We just say buildTable(“xxx”) and the table for xxx is created. The content of that table needs to be defined in one of the if statements of the function in the buildTable variable. That’s all.

Finally we need another method to ensure that the content is really switched whenever the user selects an entry of the navigation bar. That’s what this code here is for:

// Whenever a tab is selected in the sheet, set the content accordingly

oShell.attachWorksetItemSelected(function(oEvent) {

   // get the key of the selected navigation item (built-in into the WorksetItem)

   var itemKey = oEvent.getParameter(“key”);

   oShell.setContent(getContent(itemKey));       

});

If not already done save not the index.html and the buildTable.js file and republish your changes to your local Neo instance. Et voila:

Screen Shot 2012-05-04 at 11.23.24.pngScreen Shot 2012-05-04 at 11.23.36.png

Pre-Fill Tables With Dummy-Data

We don’t have any persistence, yet, in our app, but let’s put  some dummy data into our tables.

We’ll add another function to our code that ensure the right data is available for each of our tabs. In this blog series I’ll use JSON as data format, but you can easily change the code to make it also run with oData.

After adding the new function getTheRightModelData and adding some dummy data into the function our index.html file looks like this:

<!DOCTYPE HTML>

<html>

    <head>

         <meta http-equiv=”X-UA-Compatible” content=”IE=edge” />

         <title>Tweets Persistence App</title>

         <!–

         Load the SAP UI5 library into the memory and set some meta information for it

<!DOCTYPE HTML>

<html>

    <head>

         <meta http-equiv=”X-UA-Compatible” content=”IE=edge” />

         <title>Tweets Persistence App</title>

   

         <!–

         Load the SAP UI5 library into the memory and set some meta information for it

         like the libs you want to use and the theme you want to apply

         –>

         <script

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

           type=”text/javascript”

           id=”sap-ui-bootstrap”

           data-sap-ui-libs=”sap.ui.ux3, sap.ui.commons, sap.ui.table”

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

         </script>

       

        <script type=”text/javascript” src=”tools/buildTable.js”></script>

        

         <script type=”text/javascript”>

            // Create a SAP UI5 shell element

            var oShell = new sap.ui.ux3.Shell(“tweetAppShell”, {  

                  appIcon  : “http://www.sap.com/global/images/SAPLogo.gif“,

                  appTitle : “Tweets Persistence App”,

            });

   

            // And now add so called WorksetItems to the shell

            // Each WorksetItem consists in our case of a NavigationItem

            // Notice that each Navigation Item is accessible via a unique key!

            var WI = sap.ui.ux3.NavigationItem;

            oShell.addWorksetItem(new WI({key : “wi_home”,   text : “All Tweets”}));

            oShell.addWorksetItem(new WI({key : “wi_tweets”, text : “Tweets Per Hashtag”}));

            // Initialize the content variable

            var aContent = {};           

           

            // Initialize the content for the first visible tab

            oShell.setContent(getContent(“wi_home”));

            getTheRightModelData(“wi_home”);   

            // Whenever a tab is selected in the sheet, set the content accordingly

            oShell.attachWorksetItemSelected(function(oEvent) {

                var itemKey = oEvent.getParameter(“key”);

                oShell.setContent(getContent(itemKey));       

                getTheRightModelData(itemKey);       

            });

            // Just take the shell and place it in the html area called shellArea

            oShell.placeAt(“shellArea”);

           

            // content generation and buffering

            function getContent(id) {

                    if (id == “wi_home”) {

                        if (!aContent[id]){

                            aContent[id] = [buildTable(“allTweets”)];

                        }

                    }

                    if (id == “wi_tweets”) {

                        if (!aContent[id]){

                            aContent[id] = [buildTable(“allHashtags”), buildTable(“tweetsForHashtag”)];

                        }

                    }

                return aContent[id];

            }

           

            function getTheRightModelData(itemKey){

                if (itemKey == “wi_home”){

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

                   oModel.setData({

                       “allTweets”:

                       [

                             {“icon”: “http://scn.sap.com/people/rui.nogueira/avatar/46.png?a=1392“, “author”:”ruinogueira”, “linkauthor”:”https://twitter.com/#!/ruinogueira“, “tweet”: “Just started my blog series around #SAPUI5 and #Neo http://t.co/DIwHXsu8 #innojam”, “linktweet”:”http://twitter.com/#!/ruinogueira/status/192606455688474624“},

                             {“icon”: “https://twimg0-a.akamaihd.net/profile_images/1281299036/portrait_reasonably_small.jpg“, “author”:”steinermatt”, “linkauthor”:”https://twitter.com/#!/steinermatt“, “tweet”: “@rhirsch @simondsap oh ‘they’ know for sure and we are working on it – won’t be long 😉 – btw, lets go for #sapnwneo as hashtag”, “linktweet”:”https://twitter.com/#!/ruinogueira/status/194863564442443776“},

                             {“icon”: “http://scn.sap.com/people/rui.nogueira/avatar/46.png?a=1392“, “author”:”ruinogueira”, “linkauthor”:”https://twitter.com/#!/ruinogueira“, “tweet”: “Working on my second blog post around #sapnwneo and #sapui5. Hope to get it done by end of this week.”, “linktweet”:”https://twitter.com/#!/ruinogueira/status/194863564442443776“},

                       ]

                   });

                  

                    if (itemKey == “wi_tweets”){

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

                       oModel.setData({

                           “allHashtags” :

                           [

                                {“hashtag”:”innojam”},

                               {“hashtag”:”sapnwneo”},

                               {“hashtag”:”sapui5″}

                           ],

                           “tweetsForHashtag” :

                           [

                               {“icon”: “http://scn.sap.com/people/rui.nogueira/avatar/46.png?a=1392“, “author”:”ruinogueira”, “linkauthor”:”https://twitter.com/#!/ruinogueira“, “tweet”: “Just started my blog series around #SAPUI5 and #Neo http://t.co/DIwHXsu8 #innojam”, “linktweet”:”http://twitter.com/#!/ruinogueira/status/192606455688474624“},

                               {“icon”: “http://scn.sap.com/people/rui.nogueira/avatar/46.png?a=1392“, “author”:”ruinogueira”, “linkauthor”:”https://twitter.com/#!/ruinogueira“, “tweet”: “Working on my second blog post around #sapnwneo and #sapui5. Hope to get it done by end of this week.”, “linktweet”:”https://twitter.com/#!/ruinogueira/status/194863564442443776“},

                           ]

                       });

                  

                  

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

                }

               

           }

           

         </script>

   

    </head>

   

    <body class=”sapUiBody” >

         <!– And here is the div element shellArea where the shell element will be posted to–>

         <div id=”shellArea”></div>

    </body>

</html>

In the function getTheRightModelData you can see how the JSON data fields connect to the fields we’ve used in our buildTable.js file.E.g. with oTable.bindRows(“allTweets”) in the buildTable function you tell the DataTable that it gets its datasets from the JSON variable “allTweets” we’ve defined in the getTheRightModelData function. The actual columns of our tables connect to the field names in the corresponding JSON object.

Pretty straight forward.

At the end we just need to ensure that whenever we select another tab we get the corresponding data. That’s what we need the other two lines for I’ve added to the code for attachWorksetItemSelected

            // Whenever a tab is selected in the sheet, set the content accordingly

            oShell.attachWorksetItemSelected(function(oEvent) {

                var itemKey = oEvent.getParameter(“key”);

                oShell.setContent(getContent(itemKey));       

                getTheRightModelData(itemKey);       

            });

and  after setting the content for the first visible tab:

            // Initialize the content for the first visible tab

            oShell.setContent(getContent(“wi_home”));

            getTheRightModelData(“wi_home”);    

Enjoying The First Results

Let’s republish our code again to the local Neo instance and we finally see some data in our app

Screen Shot 2012-05-04 at 12.52.51.png

Screen Shot 2012-05-04 at 12.53.43.png

The End Of Blog Number 2

Of course there is still a lot to do in order to get a really functional app. We haven’t talked about persistence, yet, and the table to show the related datasets for a hashtag is not working, too.

But you’ve learned how easy it is to create a nice looking prototype for an SAP UI5 app. You’ve also learned how to map a DataTable object to JSON data read-in by the SAP UI5 dataModel and also how you can use different UI elements withing such tables.

With the code for the buildTable.js file and index.html file in this blog you can easily try out this blog yourself. Have fun.

To be continued

In my next blog series I’ll show you how to use the persistence layer of Neo and how to access the data from within our app. We’ll not only read data, but also write data back to the persistence layer.

I hope you’ve enjoyed this blog and where able to follow it with some “aha” moments. For me those moments are the most important ones because they motivate to try out more and to suddenly have another idea on how to leverage other technologies and other know-how, too.

In case you find out something is wrong or would do things different, just post as a comment to this blog.

This is useful for the community and highly appreciated by me.

You can also ping me directly via my Twitter user ruinogueira.

Oh! One more thing: don’t forget to rate this blog (and all the others coming in the next weeks and months) so that I can see if you find it helpful or not.

Best,

Rui

Assigned Tags

      22 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Frank Koehntopp
      Frank Koehntopp

      Wait a minute - Netweaver NEO, HTML5, and all without having to code Java?

      That ROCKS!

      Author's profile photo Rui Nogueira
      Rui Nogueira
      Blog Post Author

      Thanks Frank. So you'll probable skip my next blog. It'll be using Java to use the persistence API from Neo.

      Author's profile photo Matthias Steiner
      Matthias Steiner

      Nice blog Rui - keep it coming! 🙂

      Author's profile photo Rui Nogueira
      Rui Nogueira
      Blog Post Author

      Just started writing the next blog post  about persisting data in Neo. Will show some more things at the SAP Inside Track 2012 in Hamburg next Saturday.

      Author's profile photo Former Member
      Former Member

      Hello Rui,

      I just tried out your tutorial. Great features, nicely written, I enjoyed it a lot 🙂

      However, you got a syntax error in your final code for the index.html file. The brackets after   if (itemKey == "wi_home"){   and   if (itemKey == "wi_tweets"){   are never closed properly. When you copy & paste that code, all you see is a blank page. Took me some time to find the mistake there 😉

      Anyways, after I fixed that, It works perfectly. Can't wait for the next post!

      Author's profile photo Rui Nogueira
      Rui Nogueira
      Blog Post Author

      Hi Lukas, thanks a lot for your feedback. Now I know that at least one person really tried it out 🙂

      I've just copied the code in index.html from my Eclipse project into this blog again.

      So I hope this is fixed now.

      Sorry for the trouble!

      Best,

      Rui

      Author's profile photo Nico Groh
      Nico Groh

      Hi Rui,

      I had still a problem with the getTheRightModelData Method. Here comes my working version.

      Thanks & Regards

      Nico

      function getTheRightModelData(itemKey){
                    var oModel  = new sap.ui.model.json.JSONModel();
                    if (itemKey == "wi_home"){              
                     oModel.setData({
                               "allTweets":

                               [

                                     {"icon": "http://scn.sap.com/people/rui.nogueira/avatar/46.png?a=1392", "author":"ruinogueira", "linkauthor":"https://twitter.com/#!/ruinogueira", "tweet": "Just started my blog series around #SAPUI5 and #Neo http://t.co/DIwHXsu8 #innojam", "linktweet":"http://twitter.com/#!/ruinogueira/status/192606455688474624"},

                                     {"icon": "https://twimg0-a.akamaihd.net/profile_images/1281299036/portrait_reasonably_small.jpg", "author":"steinermatt", "linkauthor":"https://twitter.com/#!/steinermatt", "tweet": "@rhirsch @simondsap oh 'they' know for sure and we are working on it - won't be long  - btw, lets go for #sapnwneo as hashtag", "linktweet":"https://twitter.com/#!/ruinogueira/status/194863564442443776"},

                                     {"icon": "http://scn.sap.com/people/rui.nogueira/avatar/46.png?a=1392", "author":"ruinogueira", "linkauthor":"https://twitter.com/#!/ruinogueira", "tweet": "Working on my second blog post around #sapnwneo and #sapui5. Hope to get it done by end of this week.", "linktweet":"https://twitter.com/#!/ruinogueira/status/194863564442443776"},

                               ]

                           });
                    
                    }
                    if (itemKey == "wi_tweets"){
                    
                     oModel.setData({

                               "allHashtags" :

                               [

                                    {"hashtag":"innojam"},

                                   {"hashtag":"sapnwneo"},

                                   {"hashtag":"sapui5"}

                               ],

                               "tweetsForHashtag" :

                               [

                                   {"icon": "http://scn.sap.com/people/rui.nogueira/avatar/46.png?a=1392", "author":"ruinogueira", "linkauthor":"https://twitter.com/#!/ruinogueira", "tweet": "Just started my blog series around #SAPUI5 and #Neo http://t.co/DIwHXsu8 #innojam", "linktweet":"http://twitter.com/#!/ruinogueira/status/192606455688474624"},

                                   {"icon": "http://scn.sap.com/people/rui.nogueira/avatar/46.png?a=1392", "author":"ruinogueira", "linkauthor":"https://twitter.com/#!/ruinogueira", "tweet": "Working on my second blog post around #sapnwneo and #sapui5. Hope to get it done by end of this week.", "linktweet":"https://twitter.com/#!/ruinogueira/status/194863564442443776"},

                               ]

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

      Author's profile photo Former Member
      Former Member

      Great Blog Rui as always,

      I tried to deploy it on the Cloud....

      I am gettting some missing Character Errors in the index.html file !!

      Though, able to fix it after few trials.

      Would be Great, if you can  revisit it once.

      Regards,

      Ravi

      Author's profile photo Former Member
      Former Member

      Just for Every One Else :

      You should try this File, if things doesnt work in first go.

      <!DOCTYPE HTML>

      <html>

      <head>

      <meta http-equiv="X-UA-Compatible" content="IE=edge" />

      <title>Tweets Persistence App</title>

      <!--

               Load the SAP UI5 library into the memory and set some meta information for it

      <!DOCTYPE HTML>

      <html>

          <head>

               <meta http-equiv="X-UA-Compatible" content="IE=edge" />

               <title>Tweets Persistence App</title>

        

               <!--

               Load the SAP UI5 library into the memory and set some meta information for it

               like the libs you want to use and the theme you want to apply

               -->

      <script src="./resources/sap-ui-core.js" type="text/javascript"

                id="sap-ui-bootstrap"

                data-sap-ui-libs="sap.ui.ux3, sap.ui.commons, sap.ui.table"

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

               </script>

      <script type="text/javascript" src="tools/buildTable.js"></script>

      <script type="text/javascript">

                  // Create a SAP UI5 shell element

                  var oShell = new sap.ui.ux3.Shell("tweetAppShell", { 

                        appIcon  : "http://www.sap.com/global/images/SAPLogo.gif",

                        appTitle : "Tweets Persistence App",

                  });

        

                  // And now add so called WorksetItems to the shell

                  // Each WorksetItem consists in our case of a NavigationItem

                  // Notice that each Navigation Item is accessible via a unique key!

                  var WI = sap.ui.ux3.NavigationItem;

                  oShell.addWorksetItem(new WI({key : "wi_home",   text : "All Tweets"}));

                  oShell.addWorksetItem(new WI({key : "wi_tweets", text : "Tweets Per Hashtag"}));

                  // Initialize the content variable

                  var aContent = {};          

                

                  // Initialize the content for the first visible tab

                  oShell.setContent(getContent("wi_home"));

                  getTheRightModelData("wi_home");  

                  // Whenever a tab is selected in the sheet, set the content accordingly

                  oShell.attachWorksetItemSelected(function(oEvent) {

                      var itemKey = oEvent.getParameter("key");

                      oShell.setContent(getContent(itemKey));      

                      getTheRightModelData(itemKey);      

                  });

                  // Just take the shell and place it in the html area called shellArea

                  oShell.placeAt("shellArea");

                

                  // content generation and buffering

                  function getContent(id) {

                          if (id == "wi_home") {

                              if (!aContent[id]){

                                  aContent[id] = [buildTable("allTweets")];

                              }

                          }

                          if (id == "wi_tweets") {

                              if (!aContent[id]){

                                  aContent[id] = [buildTable("allHashtags"), buildTable("tweetsForHashtag")];

                              }

                          }

                      return aContent[id];

                  }

                

                  function getTheRightModelData(itemKey){

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

                      if (itemKey == "wi_home"){              

                       oModel.setData({

                                 "allTweets":

                                 [

                                       {"icon": "http://scn.sap.com/people/rui.nogueira/avatar/46.png?a=1392", "author":"ruinogueira", "linkauthor":"https://twitter.com/#!/ruinogueira", "tweet": "Just started my blog series around #SAPUI5 and #Neo http://t.co/DIwHXsu8 #innojam", "linktweet":"http://twitter.com/#!/ruinogueira/status/192606455688474624"},

                                       {"icon": "https://twimg0-a.akamaihd.net/profile_images/1281299036/portrait_reasonably_small.jpg", "author":"steinermatt", "linkauthor":"https://twitter.com/#!/steinermatt", "tweet": "@rhirsch @simondsap oh 'they' know for sure and we are working on it - won't be long  - btw, lets go for #sapnwneo as hashtag", "linktweet":"https://twitter.com/#!/ruinogueira/status/194863564442443776"},

                                       {"icon": "http://scn.sap.com/people/rui.nogueira/avatar/46.png?a=1392", "author":"ruinogueira", "linkauthor":"https://twitter.com/#!/ruinogueira", "tweet": "Working on my second blog post around #sapnwneo and #sapui5. Hope to get it done by end of this week.", "linktweet":"https://twitter.com/#!/ruinogueira/status/194863564442443776"},

                                 ]

                             });

                      

                      }

                      if (itemKey == "wi_tweets"){

                      

                       oModel.setData({

                                 "allHashtags" :

                                 [

                                      {"hashtag":"innojam"},

                                     {"hashtag":"sapnwneo"},

                                     {"hashtag":"sapui5"}

                                 ],

                                 "tweetsForHashtag" :

                                 [

                                     {"icon": "http://scn.sap.com/people/rui.nogueira/avatar/46.png?a=1392", "author":"ruinogueira", "linkauthor":"https://twitter.com/#!/ruinogueira", "tweet": "Just started my blog series around #SAPUI5 and #Neo http://t.co/DIwHXsu8 #innojam", "linktweet":"http://twitter.com/#!/ruinogueira/status/192606455688474624"},

                                     {"icon": "http://scn.sap.com/people/rui.nogueira/avatar/46.png?a=1392", "author":"ruinogueira", "linkauthor":"https://twitter.com/#!/ruinogueira", "tweet": "Working on my second blog post around #sapnwneo and #sapui5. Hope to get it done by end of this week.", "linktweet":"https://twitter.com/#!/ruinogueira/status/194863564442443776"},

                                 ]

                             });

                      

                      }

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

                   }

               </script>

      </head>

      <body class="sapUiBody">

                <!-- And here is the div element shellArea where the shell element will be posted to-->

                <div id="shellArea"></div>

      </body>

      </html>

      Author's profile photo Robert Russell
      Robert Russell

      Hi Rui,

      Thank you for the blog, great way for me to get into SAPUI5 & NEO, hope you find time to post the follow up blog(s).

      Let me know if I have missed the blogs you mention.

      In my next blog series I'll show you how to use the persistence layer of Neo and how to access the data from within our app. We'll not only read data, but also write data back to the persistence layer.

      Cheers

      Robert

      Author's profile photo Carlos Weffer
      Carlos Weffer

      Hi Rui

      Great Blog. Looking forward to the one about using persistence layer.

      The Local instance has an Apache Derby DB and Cloud options are MaxDB (prod) and HANA (beta). I wonder if it does make sense to use a HANA DB on AWS for the local development. I reckon it will make easier to deploy the app later on the cloud.

      No excited about not being able to use external database administration tools to manage the application data on the cloud. Is there a way to overcome this?

      Thanks to Lukas and Ravi for picking up the missing brackets, made my life easier.

      Cheers,

      Carlos

      Author's profile photo Former Member
      Former Member

      Hello Rui,

      I just tried out your tutorial. Great features.

      However, I had a problem about No data displayed in the table. 😕

      Thanks & Regards

      Quentin

      Author's profile photo Robin Van Het Hof
      Robin Van Het Hof

      Great blog, thanks for sharing!

      I'm also anxiously 😛 awaiting your next blog about persistancy.

      I have come up with a working solution -- post JSON model from SAPUI5 form to servlet, have servlet convert JSON data to JDBC insert/update statement (I will transition to JPA shortly) and vica versa for data retrieval for display in form -- but I feel my approach can hugely benefit from some trimming/finetuning/optimization tips from the guru 😉

      Author's profile photo Richard Hirsch
      Richard Hirsch

      @Robin - Jongo is another option - A REST Interface for JDBC

      D.

      Author's profile photo Robin Van Het Hof
      Robin Van Het Hof

      That looks pretty cool! I didn't know about Jongo, but it looks pretty slick! I will definitely have a look at it!

      Author's profile photo Rui Nogueira
      Rui Nogueira
      Blog Post Author

      Hi Robin, that's exactly the way that I do it.

      Best,

      Rui

      Author's profile photo Robin Van Het Hof
      Robin Van Het Hof

      Good to know I'm on the same level as the guru then! 😛 Guess I'm not that anxiously waiting for your persistency blog anymore 😛

      Author's profile photo Former Member
      Former Member

      Hi Rui,

      I'm new to SAP UI 5, i wanted to ask you a question.

      I need to develop an application that needs to be deployed to NEO. The client side needs to be built using SAPUI5, and I also need to read data from HANA.

      Where should I write the server-side logic? should i use Servlets?

      Thanks and best regards!

      Julian

      Author's profile photo Rui Nogueira
      Rui Nogueira
      Blog Post Author

      Hi Julian, there are certainly other ways on how to do that, but as you're asking me I'd go for servlets.

      Rui

      Author's profile photo Midhun VP
      Midhun VP

      Nice blog Rui.

      Author's profile photo Former Member
      Former Member

      You may also want to check out the blog post Optimizing your SAP NetWeaver Cloud application with Gzip compression by Krum Bakalsky. This makes the initial loading of an SAP UI5 application times faster!

      Author's profile photo Andreas Wiedemann
      Andreas Wiedemann

      Hi Rui, great blog series so far!! Is there any chance to see part 3 any time soon?