Skip to Content
Technical Articles

SAPUI5 Web Components with Ionic and CAPM

PS:Live demo of the app at the end

Background

As you must be aware SAPUI5 has recently launched Web components and i was thinking of trying it. We have great examples of web component being used in Angular,React and Vue. I was thinking of why don’t we try it with Ionic framework which is built on top of Angular and observe its behavior. So this blog post talks about my trials of using web components within Ionic a hybrid app framework.

What we are planning to do

I am planning to build a mash up of different stuff:)

  1. SAP Cloud Application Programming model for setting up our backend API
  2. Ionic framework for hybrid mobile app
  3. SAPUI5 Web Components specifically cards and timelines inside Ionic framework
  4. A custom charting library inside the UI5 web component control

So let’s begin!

Setting up the Backend API using Cloud Application Programming Model

We will be creating two entities one is Sales order and another is ToDos which will be exposing the corresponding data. We will follow the great SAP Developer tutorial to set it up. The entities will look like below.

namespace my.capm;
entity SalesOrders {
  key id : Integer;
  customer : String;
  netAmount  : Integer;
  status:String;
  creationDate:Date
}
entity ToDos{
  key id  : Integer;
  title:String;
  subtitle:String;
  place:String;
}

Corresponding services

using my.capm as my from '../db/data-model';
service DataService {
entity SalesOrders @readonly as projection on my.SalesOrders;
entity ToDos @readonly as projection on my.ToDos;
}

Sample Data

id;title;subtitle;place
1;Call ABAP Team;16-Jul-2019 13:30;OnCall
2;Meet Sales Team;17-Jul-2019 13:00 - 15:00;Panchkula
3;OpenSAP Final Exam; 20-Jul-2019 14:00;Online
4;Meet CEO; 21-Jul-2019 10:00;InPerson
5;Meet CFO; 23-Jul-2019 11:00;InPerson
6;Resgin from the company; 24-Jul-2019 14:00;Online

id;customer;netAmount;status;creationDate
1;Bombay Textiles;500;Open;"2019-07-22"
2;GOI;1500;Open;"2019-07-23"
3;GOI;1300;Open;"2019-07-24"
4;GOI;1200;Open;"2019-07-25"
5;GOI;1750;Open;"2019-07-27"

Deploy to Local SQLite database 

cds deploy --to sqlite:db/my-data.db

Our service is ready all we need to do publish it over the internet for the demo purpose i am using ngrok

Now our backend is set lets move to frontend! 

Setting up ionic project

Setting up ionic project is very simple all you need to do is follow the below mentioned steps, I am assuming you have Node.js already installed.

npm install -g ionic

Creating a sample app with tabs as template

ionic start myApp tabs

Simply go inside the folder and run it locally.

Ionic serve

So we have the basic ionic frontend ready, In next step we will add the UI5 Web components and integrate with our backend API.

Using the UI5 Web Component within Ionic

We are planning to use only two tabs one will show my to do task list and another for my sales orders, so modifying the tabs.page.html file.

<ion-tabs>
  <ion-tab-bar slot="bottom">
    <ion-tab-button tab="tab1">
      <ion-icon name="flash"></ion-icon>
      <ion-label>My ToDo's</ion-label>
    </ion-tab-button>

    <ion-tab-button tab="tab2">
      <ion-icon name="apps"></ion-icon>
      <ion-label>My Orders</ion-label>
    </ion-tab-button>
  </ion-tab-bar>
</ion-tabs>

Lets first add the timeline to tab1, in order to use any webcomponent we need to also declare custom elements schemas 

import { NgModule,CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import '@ui5/webcomponents/dist/Timeline';

Add it as a dependency in the module under schemas

schemas: [ CUSTOM_ELEMENTS_SCHEMA ]

Then next task was first call the backend. In ionic we use HttpModule with HttpClient, read this blog for more details if needed. So we have the data for my to do’s fetched from backend API now.

import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Component({
  selector: 'app-tab1',
  templateUrl: 'tab1.page.html',
  styleUrls: ['tab1.page.scss']
})
export class Tab1Page {
  private myToDos: any =[];
  constructor(private http: HttpClient) {
  this.http.get('https://7d76332c.ngrok.io/data/ToDos').subscribe((response) => {
    this.myToDos = response;
  });
}
}

Next step was to use the timeline component of SAPUI5 which works flawlessly with Ionic.

  <ui5-timeline >
    <ui5-timeline-item *ngFor="let myToDo of myToDos.value"  
    titleText="{{myToDo.title}}" 
    subtitleText="{{myToDo.subtitle}}" icon="sap-icon://calendar">
      <div>{{myToDo.place}}</div>
    </ui5-timeline-item>
  </ui5-timeline>

Moving on to the sales order tab, we have to do similar things, declare our SAPUI5 web component which we want to use in this case Card and Table both.

import '@ui5/webcomponents/dist/Card';
import '@ui5/webcomponents/dist/Table';

Then next we make the data fetching call

this.http.get('https://7d76332c.ngrok.io/data/SalesOrders').subscribe((response) => {   
 this.salesOrders = response; 
});

All we need to now is add our UI5 component control to the frontend as can be seen below.

<ion-header>
  <ion-toolbar>
    <ion-title>
      My Orders
    </ion-title>
  </ion-toolbar>
</ion-header>

<ion-content class="ion-padding">
  <style>
    .status-error {color: #b00;}
    .status-warning {color: #e9730c;}
    .status-success {color: #107e3e;}
    </style>
    <ui5-card heading="My Sales Orders"  class="medium">
      <ui5-table class="demo-table content-padding">
        <!-- Columns -->
        <ui5-table-column slot="columns">
                <ui5-label>Sales Order</ui5-label>
        </ui5-table-column>
    
        <ui5-table-column slot="columns">
                <ui5-label>Customer</ui5-label>
        </ui5-table-column>
    
        <ui5-table-column slot="columns">
                <ui5-label>Net Amount</ui5-label>
        </ui5-table-column>
    
        <ui5-table-column slot="columns" min-width="450" popin-text="Date" demand-popin>
                <ui5-label>Date</ui5-label>
        </ui5-table-column>
    
        <!-- Rows -->
        <ui5-table-row *ngFor="let saleOrder of salesOrders.value">
          <ui5-table-cell>
            <ui5-label>{{saleOrder.id}}</ui5-label>
          </ui5-table-cell>
          <ui5-table-cell>
            <ui5-label>{{saleOrder.customer}}</ui5-label>
          </ui5-table-cell>
          <ui5-table-cell>
              <ui5-label>{{saleOrder.netAmount}}</ui5-label>
          </ui5-table-cell>
          <ui5-table-cell>
            <span>{{saleOrder.creationDate}}</span>
          </ui5-table-cell>
        </ui5-table-row>
        
      </ui5-table>
    </ui5-card>
</ion-content>

Bingo we have our frontend integrated and ready as can be seen below

Next level – Using another library component inside UI5 component

I was kind of happy with the progress so far but wanted to go beyond. Neither SAPUI5 web component has Charts nor Ionic, so what if we embed charts in the SAPUI5 web components how will it behave i wanted to check that. In this example we have used Chart.js library control line charts.

All you need to do this first install charts using below command

npm install chart.js --save

Then i added the canvas id specifically inside SAPUI5 Web components

<ion-header>
  <ion-toolbar>
    <ion-title>
      My Orders
    </ion-title>
  </ion-toolbar>
</ion-header>

<ion-content class="ion-padding">
  <style>
    .status-error {color: #b00;}
    .status-warning {color: #e9730c;}
    .status-success {color: #107e3e;}
    </style>
    <ui5-card heading="My Sales Orders"  class="medium">
      
      <div class="ion-padding">
       <ion-card>
          <ion-card-header>
            History
          </ion-card-header>
          <ion-card-content>
            <canvas #lineCanvas></canvas>
          </ion-card-content>
        </ion-card>
      </div>
     <!-- Table is here -->
    </ui5-card>
</ion-content>

All i need to do this pass the fetched data to chart control

      this.lineChart = new Chart(this.lineCanvas.nativeElement, {
        type: "line",
        data: {
          labels: this.salesOrders.value.map(saleOrder =>  saleOrder.creationDate),
          datasets: [
            {
              label: "Sales order value over time",
              fill: false,
              lineTension: 0.1,
              backgroundColor: "rgba(75,192,192,0.4)",
              borderColor: "rgba(75,192,192,1)",
              borderCapStyle: "butt",
              borderDash: [],
              borderDashOffset: 0.0,
              borderJoinStyle: "miter",
              pointBorderColor: "rgba(75,192,192,1)",
              pointBackgroundColor: "#fff",
              pointBorderWidth: 1,
              pointHoverRadius: 5,
              pointHoverBackgroundColor: "rgba(75,192,192,1)",
              pointHoverBorderColor: "rgba(220,220,220,1)",
              pointHoverBorderWidth: 2,
              pointRadius: 1,
              pointHitRadius: 10,
              data: this.salesOrders.value.map(saleOrder =>  saleOrder.netAmount),
              spanGaps: false
            }
          ]
        }
      });

I would like to thanks again here DJ Adams for his sessions because of which i have written some less code. If map function was not know I would have created separate arrays by looping and all. 

So our charts integration is also done, Demo Time!

Final Demo

So far we have seen our app only in browser. Lets deploy it to iOS emulator and see how it works.

What is next?

I think I will keep experimenting SAPUI5 Web Components with other framework, different web components, how one web component interact with other etc. and share my experience. I must congratulate the SAPUI5 Web component team for the great work, only request is we need more components:)

Feel free to provide your feedback!

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