“More code, less talk”

Thanks

Inspired by You Don’t Know JS (book series)

What are we doing here today?

We want to know how to develop an openui5 application using sap.m.App and sap.m.Page. Also, we want to know how to develop openui5 app with lates ES6 (Ecmascript 2015) features, like import/export, classe, arrow functions and much more. As core source code for the project and quick start you may use project from my first article.

Introduction

A goal of my blog is do not teach you how to use openui5 library from SAP in right way. The openui5 was designed to solve one issue with several possible ways. So you are able to choose.

The goal is sharing my personal experience of using the library and some other web development stuff, which helps you to speed up your development using openui5.

All code samples are developed on MacOS environment. On other environments (Linux or Windows) process should be nearly the same.

Pre-requirements

Minimal:

  • MacOS, Linux or Windows operating system prepared
  • Chromium browser installed
  • Node.js javascript runtime installed
  • Yarn dependency manager installed
  • Gulp4 javascript task runner installed globally

Additional:

  • Git client (command-line or GUI) installed
  • Preferred IDE installed (for ex. Visual Studio Code or WebStorm)

Let’s go

First of all I recommend you to create project as described in my first article (preferable). Or just clone project from repository (for lazy developers)

git clone https://github.com/sergiykh/you-do-not-know-openui5.git cd you-do-not-know-openui5 git checkout tags/bootstrapping

First of all, project structure will be changed a little bit

├── .babelrc => (New) ├── .editorconfig ├── .gitignore ├── LICENSE.md ├── README.md ├── gulpfile.js => (Changed) ├── package.json => (Changed) ├── proxies.js ├── src ├── app => (New) ├── pages => (New) ├── CustomerDetail.page.js => (New) ├── Customer.page.js => (New) ├── Login.page.js => (New) ├── app.config.js => (Changed) ├── app.startup.js => (Changed) └── index.html 

Extend structure by adding folders

mkdir -p src/app/pages

Add new developer dependencies via yarn

yarn add -D @types/openui5 babel-core babel-preset-ui5 gulp-babel merge-stream gulp-sourcemaps gulp-replace

You packages.json will be automatically updated with new dependencies. Never update dependencies in  package.json manually.

Just a brief explanation of used dependencies:

  • @types/openui5 usually it is types for TypeScript, but we will use it in our for code auto-completion now (Visual Studio Code or Intellij IDEA/WebStorm)
  • babel-core compiles JavaScript code from ES6 to ES5
  • gulp-babel for supporting Babel compiler via gulp tasks
  • babel-preset-ui5 for compile openui5 application with Babel (UNOFFICIAL)
  • merge-stream for merging gulp streams
  • gulp-sourcemaps to generate/write sourcemaps for compiled  files
  • gulp-replace to replace strings in files via gulp tasks

In .babelrc

{ "presets": [ "ui5" ] } 

Update gulpfile.js

const gulp = require('gulp'); const browserSync = require('browser-sync'); // require babel gulp plugin, merge stream plugin and sourcemaps gulp plugin const babel = require('gulp-babel'); const merge = require('merge-stream'); const sourcemaps = require('gulp-sourcemaps'); const replace = require('gulp-replace'); ... // stream for all files except .js const copy = () => { return gulp.src([ 'src/**/*', '!src/**/*js' ]); }; // stream for all .js files const copyJs = () => { let b = babel() .on("error", (e) => { console.log(e.stack); b.end(); }); return gulp.src([ 'src/**/*js' ]) .pipe(sourcemaps.init()) .pipe(b) .pipe(replace('src.', '')) .pipe(replace('src/', '')) .pipe(sourcemaps.write('.')) }; // merge two streams and copy content of src folder to root path in-memory gulp.task('app:build', () => { return merge(copy(), copyJs()) .pipe(gulpMem.dest('/')); }); ...

Update src/app.config.js

... theme: "sap_belize", resourceRoots: { "app": "app" }, preload: "sync", ...

Update src/app.startup.js

let app; // Now we can use arrow functions in our code (feature of ES6) sap.ui.getCore().attachInit(() => { sap.ui.require([ "app/pages/Login.page", "app/pages/Customers.page", "app/pages/CustomerDetail.page" ], (Login, Customers, CustomerDetail) => { app = new sap.m.App({ initialPage: "login" }); app.addPage(Login); app.addPage(Customers); app.addPage(CustomerDetail); app.placeAt("content"); }); });

In src/app/pages/Login.page.js

// Now we can use import/export modules (feature of ES6) // Import openui5 modules import Page from "sap/m/Page"; import Input from "sap/m/Input"; import Label from "sap/m/Label"; import Button from "sap/m/Button"; // Create object and export as module to use in future export default new Page("login", { title: "Login", showNavButton: false, content: [ new Label({ text: "Username" }), new Input({ placeholder: "type here" }), new Label({ text: "Password" }), new Input({ placeholder: "type here" }), new Button({ text : "Login", press : () => { app.to("customers"); } }) ] }) 

In src/app/pages/Customers.page.js

// Now we can use import/export modules (feature of ES6) // Import openui5 modules import Page from "sap/m/Page"; import TileContainer from "sap/m/TileContainer"; import StandardTile from "sap/m/StandardTile"; const customer = "Customer"; // Create object and export as module to use in future export default new Page("customers", { title: "Customers", showNavButton: true, navButtonPress : function () { app.back(); }, content: [ new TileContainer({ tiles: [ new StandardTile({ icon: "sap-icon://customer", // Now we can use string templates (feature if ES6) title : `${customer} 1`, info : "Active", press: () => { app.to("customerDetail") } }), new StandardTile({ icon: "sap-icon://customer", title : `${customer} 2`, info : "Not Active", press: () => { app.to("customerDetail") } }) ] }) ] }) 

In src/app/pages/CustomerDetail.page.js

// Now we can use import/export modules (feature of ES6) // Import openui5 modules import Page from "sap/m/Page"; import MessageToast from "sap/m/MessageToast"; import Input from "sap/m/Input"; import Label from "sap/m/Label"; import Button from "sap/m/Button"; // Create object and export as module to use in future export default new Page("customerDetail", { title: "Customer Detail", showNavButton: true, navButtonPress : function () { app.back(); }, content: [ new Label({ text: "Username" }), new Input({ value: "Awesome Username" }), new Label({ text: "Email" }), new Input({ value: "[email protected]" }), new Button({ text : "Print Details", press : () => { MessageToast.show("Customer's Detail Printed"); } }) ] }) 

Looks like everything is ready! Now we can issue gulp default task in command line.

gulp

Content of src folder will be compiled (.js) via Babel, copied to root path in-memory, watchers will be started, browser-sync server will be started and our app will be opened in Chromium browser.

In command line we see the following

Jan 06 2018 12 20 08 8053828

In browser we see the following

Now we need to be sure that we can debug openui5 written with cool ES6 features.

Open DevTools in Chromium browser and click Sources tab.

Our original source code

And our compiled code to ES5

Later we will try another feature of ES6 like extends, classes, rest arguments, spread operator, etc.

So, it is the end for today. Source code for our project can be found here. Feel free to experiment with source code, because it is only one way to become a developer. And Happy Coding!

Next topic of “You Don’t Know Openui5” series will be soon.

Summary

So, we enhance our simple openui5 application:

  • Add pages and navigation. I usually use sap.m.App and sap.m.Page to quick start with openui5 example code.

and enhance our development environment:

  • Add ES6 support using Babel and openui5 babel preset.
  • Add sourcemaps for debugging ES6 code in browser.

Something to read

  • Get Started: Setup and Tutorials. Hello World!

Previous articles

  1. You Don’t Know Openui5: bootstrapping