You Don’t Know Openui5: app as component
“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.ui.core.ComponentContainer and sap.ui.core.Component. Also we want to know how to add automatic .js source code validating with eslint. As core source code for the project and quick start you may use project from my second 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 second 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/app-and-pages
First of all, project structure will be changed a little bit
├── .babelrc
├── .eslintrc (new)
├── .editorconfig
├── .gitignore
├── LICENSE.md
├── README.md
├── gulpfile.js => (Changed)
├── package.json => (Changed)
├── proxies.js
├── src
├── app
├── pages
| ├── CustomerDetail.page.js
| ├── Customer.page.js
| ├── Login.page.js
├── Component.js (New)
├── manifest.json (New)
├── app.config.js =>
├── app.startup.js => (Changed)
└── index.html
Add new developer dependencies via yarn
yarn add -D gulp-eslint babel-eslint
You packages.json will be automatically updated with new dependencies. Never update dependencies in package.json manually.
Just a brief explanation of used dependencies:
- gulp-eslint validating of you .js source code via gulp task
- babel-eslint parser for eslint tool
In .eslintrc
{
"parser": "babel-eslint",
"extends": "eslint:recommended",
"rules": {
"strict": 0,
"no-alert": 0,
"no-bitwise": 0,
"camelcase": 1,
"curly": 1,
"eqeqeq": 0,
"no-eq-null": 0,
"guard-for-in": 1,
"no-empty": 1
},
"globals": {
"$": true,
"_": true,
"jQuery": true,
"sap": true,
"app": true
},
"env": {
"browser": true,
"node": true
}
}
Full list of configuration options can be found here. In configuration you may found that we can enable ES6 syntax fo linter via “ecmascriptVersion”: 6, but it will not work, because we have custom babel preset for openui5. That’s why we are using parser “babel-eslint”.
Update gulpfile.js
const gulp = require('gulp');
// Require gulp-eslint plugin
const eslint = require('gulp-eslint');
...
// Turn of log for gulp-mem plugin
gulpMem.enableLog = false;
// 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())
// Validate our .js source code with linter
.pipe(eslint())
.pipe(eslint.format())
.pipe(b)
.pipe(replace('src.', ''))
.pipe(replace('src/', ''))
.pipe(sourcemaps.write('.'))
};
...
Update src/app.startup.js
/*eslint-disable no-unused-vars*/
let app;
/*eslint-enable no-unused-vars*/
// Now we can use arrow functions in our code (feature of ES6)
sap.ui.getCore().attachInit(() => {
sap.ui.require([
"sap/ui/core/ComponentContainer",
"app/Component"
], (ComponentContainer, MainComponent) => {
// Our main Component of application
let mainComponent = new MainComponent("main-component", {
id: "main-component",
name: "app"
});
// It is also possible to use factory function
// let mainComponent = sap.ui.component({
// id: "main-component",
// name: "app"
// })
// Or load component asynchronous
// sap.ui.component({
// id: "main-component",
// name: "app",
// async: true
// }).then((mainComponent) => {
// let componentContainer = new ComponentContainer("main-component-container", {
// component: mainComponent,
// height: "100%",
// width: "100%",
// });
//
// componentContainer.placeAt("content");
// });
// Our main Container for Component
let componentContainer = new ComponentContainer("main-component-container", {
component: mainComponent,
height: "100%",
width: "100%",
});
componentContainer.placeAt("content");
});
});
In src/appComponent.js
import UIComponent from "sap/ui/core/UIComponent";
import App from "sap/m/App";
import Login from "app/pages/Login.page";
import Customers from "app/pages/Customers.page";
import CustomerDetail from "app/pages/CustomerDetail.page";
// Create object and export as module to use in future
// Also here we are using class/extends (feature of ES6)
export default class Component extends UIComponent {
metadata = {
manifest: "json"
}
createContent() {
app = new App("app", {
initialPage: "login"
});
return app
.addPage(Login)
.addPage(Customers)
.addPage(CustomerDetail);
}
}
In our next articles we will found other cool features of component approach from openui5.
In src/manifest.json
{
"_version": "1.8.0",
"sap.app": {
"id": "you-do-not-know-openui5",
"type": "application",
"title": "you-do-not-know-openui5",
"description": "Project for articles from https://blogs.sap.com/author/skholod/",
"applicationVersion": {
"version": "0.0.1"
}
},
"sap.ui": {
"technology": "UI5",
"deviceTypes": {
"desktop": true,
"tablet": true,
"phone": true
},
"supportedThemes": [
"sap_belize"
]
},
"sap.ui5": {
"dependencies": {
"minUI5Version": "1.44",
"libs": {
"sap.ui.core": {},
"sap.m": {}
}
}
}
}
It is minimum configuration for application component. Other configuration options you can found here.
Looks like everything is ready! Now we can issue gulp default task in command line.
gulp
Content of src folder will be validated via Eslint (.js), 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
In browser we see the following
Now we need to be sure that linter of .js source code is working.
Update src/app/Component.js
...
createContent() {
// Declare variable here
let unusedVariable;
app = new App("app", {
initialPage: "login"
});
return app
.addPage(Login)
.addPage(Customers)
.addPage(CustomerDetail);
}
..
Because of changes in .js file (watchers in gulpfile.js), gulp task build will be issued automatically
In command line we see the following
And let see how classes/extends of ES6 source code compiled to ES5 openui5 sources.
Open DevTools in Chromium browser and click Sources tab.
Our original source code
And our compiled code to ES5
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:
- Use Component as application means that Component is a main entry point for the whole ui of our application. But we still using pages inside Component. I recommend you to use Component and configure it like application for production use.
and enhance our development environment:
- Add validating of js code via Eslint.
Something to read
- Walkthrough: Step 9: Component Configuration
- Walkthrough: Step 10: Descriptor for Applications
- Descriptor for Applications, Components, and Libraries