Skip to Content

“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:

Additional:

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:

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

Previous articles

  1. You Don’t Know Openui5: bootstrapping
  2. You Don’t Know Openui5: app and pages
To report this post you need to login first.

Be the first to leave a comment

You must be Logged on to comment or reply to a post.

Leave a Reply