TypeScript für Fortgeschrittene: Vertiefen Sie Ihre Grundkenntnisse

In der dynamischen Welt der Webentwicklung ist es entscheidend, nicht nur neue Technologien zu erlernen, sondern auch das Wissen kontinuierlich zu vertiefen. TypeScript, als mächtige Erweiterung von JavaScript, bietet eine Fülle an Möglichkeiten, die Entwicklung von Anwendungen zu verbessern und zu vereinfachen. Wenn ihr bereits die Grundlagen von TypeScript gemeistert habt und bereit seid, eure Kenntnisse zu erweitern, seid ihr hier genau richtig.

In den kommenden Abschnitten werdet ihr lernen, wie ihr die Grundlagen von TypeScript weiter ausbaut, komplexe Typen handhabt, fortgeschrittene Funktionen nutzt und die Typsicherheit eurer Anwendungen auf ein neues Niveau hebt. Wir werden euch anhand praktischer Beispiele und tiefergehender Erklärungen zeigen, wie ihr eure Fähigkeiten in TypeScript weiterentwickeln könnt.

Die folgenden fünf Abschnitte bieten euch vertiefte Einblicke in erweiterte TypeScript-Techniken. Sie sind speziell darauf ausgelegt, euer Verständnis zu festigen und euch dabei zu unterstützen, komplexere und leistungsstärkere Anwendungen zu entwickeln. Lasst uns diese Reise fortsetzen und die Macht von TypeScript voll ausschöpfen!

Erweiterte Interface-Nutzung

Interfaces in TypeScript können verwendet werden, um die Struktur von komplexeren Objekten zu definieren, einschließlich optionaler Eigenschaften und Methoden:

interface Employee {
 id: number;
 name: string;
 role?: string; // Optional property
 updateRole(newRole: string): void; // Method
}
let employee: Employee = {
 id: 1,
 name: "Anna Schmidt",
 updateRole: function (newRole: string) {
 this.role = newRole;
 }
};
employee.updateRole("Developer");

Verwendung von Enums

Enums sind eine Möglichkeit, eine Menge von benannten Konstanten zu definieren. Sie können das Lesen des Codes erleichtern und Fehler reduzieren:

enum Direction {
 Up,
 Down,
 Left,
 Right
}
function move(direction: Direction) {
 // ...
}
move(Direction.Up);

Typschutz und Typassertionen

TypeScript erlaubt euch, Typen zu überprüfen und sicherzustellen, dass eine Variable von einem bestimmten Typ ist:

function isString(test: any): test is string {
 return typeof test === "string";
}
function example(foo: any) {
 if (isString(foo)) {
 // Hier weiß TypeScript, dass 'foo' ein String ist
 console.log("It's a string: " + foo);
 }
}
// Typassertion
let someValue: any = "Das ist ein String";
let strLength: number = (someValue as string).length;

Komplexe Generics

Generics können mit Interfaces und anderen Typen kombiniert werden, um noch mächtigere und wiederverwendbare Code-Komponenten zu erstellen:

interface Returnable<T> {
 data: T;
 returnData: () => T;
}
function createReturnable<T>(data: T): Returnable<T> {
 return {
 data,
 returnData() {
 return this.data;
 }
 };
}
const returnableNumber = createReturnable(10);
console.log(returnableNumber.returnData()); // Ausgabe: 10

Asynchrone Funktionen mit TypeScript

Asynchrone Funktionen in TypeScript können genauso definiert werden wie in modernem JavaScript, jedoch mit der zusätzlichen Sicherheit von Typen:

async function fetchData(url: string): Promise<any> {
 const response = await fetch(url);
 const data = await response.json();
 return data;
}
fetchData("https://api.example.com/data")
 .then(data => console.log(data))
 .catch(error => console.error(error));

Erweiterte Typen und Utility-Types

TypeScript bietet eine Reihe von nützlichen Utility-Typen, die euch helfen können, eure Typen flexibel zu gestalten:

type ReadOnlyEmployee = Readonly<Employee>;
let employee: ReadOnlyEmployee = {
 id: 1,
 name: "Anna Schmidt",
 updateRole: (newRole: string) => {
 // Diese Funktion kann nicht aufgerufen werden, wenn 'employee' als 'ReadOnlyEmployee' typisiert ist
 }
};
// 'employee' kann nicht verändert werden, da es ein Readonly-Typ ist
// employee.id = 2; // Error

Diese Beispiele sollten euch einen tieferen Einblick in die Fähigkeiten von TypeScript geben und wie ihr sie in euren eigenen Projekten nutzen könnt. TypeScript bietet eine reichhaltige Typensyntax, die es euch ermöglicht, eure Anwendungen präzise zu modellieren und die Vorteile der statischen Typüberprüfung voll auszuschöpfen.

Von JavaScript zu TypeScript: Grundlagen für Einsteiger

TypeScript fügt JavaScript die dringend benötigte Typisierung hinzu und hilft Entwicklern, sicherere und verständlichere Codebasen zu erstellen. Wenn ihr von JavaScript zu TypeScript wechselt, werdet ihr einige neue Konzepte kennenlernen müssen. Dieser Artikel führt euch durch die Grundlagen von TypeScript, damit ihr schnell loslegen könnt.

Variablentypen

Der vielleicht größte Vorteil von TypeScript ist die Fähigkeit, Variablen explizite Typen zuzuweisen. Diese Typen werden zur Kompilierzeit überprüft, was bedeutet, dass viele Fehler erkannt werden, bevor der Code überhaupt ausgeführt wird. Hier ein einfaches Beispiel:

let message: string = "Hello, TypeScript";
let count: number = 10;
let isActive: boolean = false;

Funktionstypisierung

In TypeScript könnt ihr nicht nur Variablen, sondern auch Funktionen Typen zuweisen. Ihr könnt sowohl den Typen der Argumente als auch den Typen des Rückgabewerts definieren:

function add(x: number, y: number): number {
 return x + y;
}

Interfaces

Interfaces sind ein mächtiges Feature von TypeScript, das euch erlaubt, die Form von Objekten zu definieren. Sie sind besonders nützlich, um sicherzustellen, dass bestimmte Objekte immer bestimmte Eigenschaften haben:

interface User {
 name: string;
 age: number;
}
const user: User = {
 name: "Max Mustermann",
 age: 28
};

Klassen und Vererbung

TypeScript unterstützt Klassen und Vererbung, ähnlich wie andere objektorientierte Sprachen. Dies ermöglicht es euch, euren Code in einer strukturierten Weise zu organisieren:

class Animal {
 name: string;
 constructor(name: string) {
 this.name = name;
 }
 move(distanceInMeters: number = 0) {
 console.log(`${this.name} moved ${distanceInMeters}m.`);
 }
}
class Snake extends Animal {
 constructor(name: string) {
 super(name);
 }
 move(distanceInMeters = 5) {
 console.log("Slithering...");
 super.move(distanceInMeters);
 }
}

Generics

Generics sind eine Möglichkeit, Komponenten zu erstellen, die mit verschiedenen Typen arbeiten können, ohne dabei den spezifischen Typ anzugeben. Sie geben euch Flexibilität sowie Typsicherheit:

function identity<T>(arg: T): T {
 return arg;
}
let output = identity<string>("myString");

Typinferenz und Union-Typen

TypeScript ist intelligent genug, um in vielen Fällen Typen selbst zu erkennen (Typinferenz). Außerdem könnt ihr Union-Typen nutzen, um eine Variable zu definieren, die mehr als einen Typ annehmen kann:

let uncertain: string | number;
uncertain = "Maybe a string?";
uncertain = 42; // Auch okay!

Fazit

Diese Grundlagen sind der erste Schritt, um TypeScript effektiv in euren Projekten einzusetzen. Durch das Erlernen dieser Konzepte werdet ihr in der Lage sein, Anwendungen zu schreiben, die nicht nur leistungsfähig, sondern auch einfacher zu warten und zu debuggen sind. Mit diesen Werkzeugen ausgestattet, könnt ihr beginnen, die tieferen, fortgeschritteneren Teile von TypeScript zu erkunden.

TypeScript in Visual Studio Code: Ein umfassender Startguide für Entwickler

Erste Schritte mit TypeScript in Visual Studio Code

Visual Studio Code (VS Code) ist ein beliebter Editor unter Entwicklern und bietet ausgezeichnete Unterstützung für TypeScript. Wenn du von JavaScript umsteigst, wirst du die TypeScript-Unterstützung in VS Code sehr hilfreich finden. Hier erfährst du, wie du TypeScript in VS Code einrichten kannst.

Schritt 1: Node.js und npm installieren

Bevor du mit TypeScript arbeiten kannst, musst du Node.js und npm installiert haben. Sie werden zusammen gebündelt und können von der offiziellen Node.js-Website heruntergeladen werden.

Schritt 2: TypeScript installieren

Mit installiertem npm kannst du nun TypeScript global auf deinem Rechner installieren, indem du den folgenden Befehl in deinem Terminal ausführst:

npm install -g typescript

Schritt 3: Dein Projekt in VS Code öffnen

Starte VS Code und öffne den Ordner, der dein Projekt enthält. Wenn du von Grund auf neu beginnst, kannst du einen neuen Ordner erstellen und ihn in VS Code öffnen.

Schritt 4: Ein neues TypeScript-Projekt initialisieren

Gib im integrierten Terminal in VS Code (das du mit Strg+ öffnen kannst) den folgenden Befehl ein, um eine tsconfig.json-Datei zu erstellen, welche die Konfigurationsdatei für TypeScript ist:

tsc --init
Dieser Befehl erzeugt eine tsconfig.json-Datei mit Standardeinstellungen, die du bei Bedarf anpassen kannst.

Schritt 5: TypeScript-Code schreiben

Erstelle eine neue Datei mit der Endung .ts. VS Code erkennt sie automatisch als TypeScript-Datei. Du kannst jetzt beginnen, deinen TypeScript-Code zu schreiben. Zum Beispiel:

function gruessen(person: string): string {
 return `Hallo, ${person}!`;
}
const benutzer = "Entwickler";
console.log(gruessen(benutzer));

Schritt 6: TypeScript in JavaScript kompilieren

Um deine TypeScript-Datei in JavaScript zu kompilieren, kannst du den TypeScript-Compiler im Terminal ausführen:

tsc
Wenn du eine tsconfig.json-Datei in deinem Projekt hast, wird tsc ohne Angabe von Dateien alle in dieser Konfiguration angegebenen Dateien kompilieren.

Schritt 7: Automatische Kompilierung aktivieren

Um den Entwicklungsprozess zu vereinfachen, kannst du die automatische Kompilierung von TypeScript-Dateien beim Speichern aktivieren. Drücke dazu Strg+Shift+P, um die Befehlspalette zu öffnen und tippe ‚Tasks: Configure Default Build Task‘. Wähle tsc: watch – tsconfig.json. Dadurch wird dein TypeScript-Code jedes Mal kompiliert, wenn du ihn speicherst.

Schritt 8: TypeScript-Funktionen in VS Code erkunden

VS Code bietet leistungsstarke Funktionen für die TypeScript-Entwicklung, wie IntelliSense, Code-Navigation und Refactoring-Tools. Nutze diese Funktionen, um deine Produktivität zu steigern.

Schritt 9: TypeScript-Deklarationsdateien installieren

Für die Verwendung bestimmter JavaScript-Bibliotheken mit TypeScript musst du möglicherweise TypeScript-Deklarationsdateien installieren, um Typdefinitionen zu erhalten. Du kannst sie mit npm installieren. Zum Beispiel für die beliebte Bibliothek lodash würdest du ausführen:

npm install --save @types/lodash

Fazit

Visual Studio Code und TypeScript zusammen schaffen eine robuste Umgebung für die Entwicklung skalierbarer und wartbarer JavaScript-Anwendungen. Indem du diesen Schritten folgst, wirst du den vollen Umfang der Leistungsfähigkeit von TypeScript in deinem Entwicklungsworkflow nutzen können.

Viel Spaß beim Programmieren mit TypeScript!

SAP Fiori Elements ABAPConf 2021 Report – CDS Tipps Tricks

SAP Fiori Elements ABAPConf 2021 Report – CDS Tipps Tricks

SAP Fiori Elements List Reports

CDS Tipps & Tricks

Im Rahmen der ABAPConf 2021 durfte die CloudDNA GmbH einen Vortrag zum Thema SAP Fiori Elements – CDS Tipps und Tricks halten.

Dabei zeigen wir Ihnen gängige Anwendungsfälle in der Entwicklung von SAP Fiori Elements Apps. 

Listendarstellung (@UI.lineItem)

@Metadata.layer: #CUSTOMER
annotate view ZC_AC_FLIGHTS with
{
 @UI.lineItem: [{ position: 10, importance: #HIGH }]
 Carrid;
 @UI.lineItem: [{ position: 20, importance: #HIGH }]
 Connid;
 @UI.lineItem: [{ position: 30, importance: #HIGH }]
 Fldate;
 @UI.lineItem: [{position: 40, importance: #MEDIUM }]
 Price;
 @UI.lineItem: [{position: 50, importance: #MEDIUM }]
 Seatsocc;
 @UI.hidden: true
 SeatsCritical; 
}

Listendarstellung mit Header (@UI.headerInfo)

@Metadata.layer: #CUSTOMER
@Search.searchable: true
@UI.headerInfo.typeName: 'Flight'
@UI.headerInfo.typeNamePlural: 'Flights'
annotate view ZC_AC_FLIGHTS with
{
 @Search.defaultSearchElement: true
 @UI.lineItem: [{ position: 10, importance: #HIGH }]
 Carrid;
 @UI.lineItem: [{ position: 20, importance: #HIGH }]
 Connid;
 @UI.lineItem: [{ position: 30, importance: #HIGH }]
 Fldate;
 @UI.lineItem: [{position: 40, importance: #MEDIUM }]
 Price;
 @UI.lineItem: [{position: 50, importance: #MEDIUM }]
 Seatsocc;
 @UI.hidden: true
 SeatsCritical; 
}

Listendarstellung mit Suche (@Search)

@Metadata.layer: #CUSTOMER
@Search.searchable: true
@UI.headerInfo.typeName: 'Flight'
@UI.headerInfo.typeNamePlural: 'Flights'
annotate view ZC_AC_FLIGHTS with
{
 @Search.defaultSearchElement: true
 @UI.lineItem: [{ position: 10, importance: #HIGH }]
 Carrid;
 @UI.lineItem: [{ position: 20, importance: #HIGH }]
 Connid;
 @UI.lineItem: [{ position: 30, importance: #HIGH }]
 Fldate;
 @UI.lineItem: [{position: 40, importance: #MEDIUM }]
 Price;
 @UI.lineItem: [{position: 50, importance: #MEDIUM }]
 Seatsocc;
 @UI.hidden: true
 SeatsCritical; 
}

Listendarstellung mit Filtern (@SelectionFields)

@Metadata.layer: #CUSTOMER
@Search.searchable: true
@UI.headerInfo.typeName: 'Flight'
@UI.headerInfo.typeNamePlural: 'Flights'
annotate view ZC_AC_FLIGHTS with
{
 @Search.defaultSearchElement: true
 @UI.lineItem: [{ position: 10, importance: #HIGH }]
 @UI.selectionField: [{ position: 10 }]
 Carrid;
 @UI.lineItem: [{ position: 20, importance: #HIGH }]
 @UI.selectionField: [{ position: 20 }]
 Connid;
 @UI.lineItem: [{ position: 30, importance: #HIGH }]
 @UI.selectionField: [{ position: 30 }]
 Fldate;
 @UI.lineItem: [{position: 40, importance: #MEDIUM }]
 Price;
 @UI.lineItem: [{position: 50, importance: #MEDIUM }]
 Seatsocc;
 @UI.hidden: true
 SeatsCritical; 
}

Listendarstellung mit Value Help (@Consumption.valueHelp)

Listendarstellung mit Select Filter (@ObjectModel.resultSet.sizeCategory)

Listendarstellung mit Date Range (@Consumption.filter.selectionType)

@Metadata.layer: #CUSTOMER
@Search.searchable: true
@UI.headerInfo.typeName: 'Flight'
@UI.headerInfo.typeNamePlural: 'Flights'
annotate view ZC_AC_FLIGHTS with
{
 @Search.defaultSearchElement: true
 @UI.lineItem: [{ position: 10, importance: #HIGH }]
 @UI.selectionField: [{ position: 10 }]
 Carrid;
 @UI.lineItem: [{ position: 20, importance: #HIGH }]
 @UI.selectionField: [{ position: 20 }]
 Connid;
 @UI.lineItem: [{ position: 30, importance: #HIGH }]
 @UI.selectionField: [{ position: 30 }]
 @Consumption.filter.selectionType: #INTERVAL
 Fldate;
 @UI.lineItem: [{position: 40, importance: #MEDIUM }]
 Price;
 @UI.lineItem: [{position: 50, importance: #MEDIUM }]
 Seatsocc;
 @UI.hidden: true
 SeatsCritical;
}

Listendarstellung LineItem Status Indicator (@UI.lineItem.criticality)

@Metadata.layer: #CUSTOMER
@Search.searchable: true
@UI.headerInfo.typeName: 'Flight'
@UI.headerInfo.typeNamePlural: 'Flights'
@UI.lineItem: [{criticality: 'SeatsCritical'}]
annotate view ZC_AC_FLIGHTS with
{
 @Search.defaultSearchElement: true
 @UI.lineItem: [{ position: 10, importance: #HIGH }]
 @UI.selectionField: [{ position: 10 }]
 Carrid;
 @UI.lineItem: [{ position: 20, importance: #HIGH }]
 @UI.selectionField: [{ position: 20 }]
 Connid;
 @UI.lineItem: [{ position: 30, importance: #HIGH }]
 @UI.selectionField: [{ position: 30 }]
 @Consumption.filter.selectionType: #INTERVAL
 Fldate;
 @UI.lineItem: [{position: 40, importance: #MEDIUM }]
 Price;
 @UI.lineItem: [{position: 50, importance: #MEDIUM }]
 Seatsocc;
 @UI.hidden: true
 SeatsCritical;
}

Listendarstellung LineItem Link (@UI.lineItem.type: #WITH_URL)

@Metadata.layer: #CUSTOMER
@Search.searchable: true
@UI.headerInfo.typeName: 'Flight'
@UI.headerInfo.typeNamePlural: 'Flights'
@UI.lineItem: [{criticality: 'SeatsCritical'}]
annotate view ZC_AC_FLIGHTS with
{
 @Search.defaultSearchElement: true
 @UI.lineItem: [{ position: 10, importance: #HIGH, type: #WITH_URL, url: 'Url' }]
 @UI.selectionField: [{ position: 10 }]
 Carrid;
 @UI.lineItem: [{ position: 20, importance: #HIGH }]
 @UI.selectionField: [{ position: 20 }]
 Connid;
 @UI.lineItem: [{ position: 30, importance: #HIGH }]
 @UI.selectionField: [{ position: 30 }]
 @Consumption.filter.selectionType: #INTERVAL
 Fldate;
 @UI.lineItem: [{position: 40, importance: #MEDIUM }]
 Price;
 @UI.lineItem: [{position: 50, importance: #MEDIUM }]
 Seatsocc;
 @UI.hidden: true
 SeatsCritical; 
}

Listendarstellung LineItem Progress Indicator (@UI.datapoint.visualization)

@Metadata.layer: #CUSTOMER
@Search.searchable: true
@UI.headerInfo.typeName: 'Flight'
@UI.headerInfo.typeNamePlural: 'Flights'
@UI.lineItem: [{criticality: 'SeatsCritical'}]
annotate view ZC_AC_FLIGHTS with
{
 @Search.defaultSearchElement: true
 @UI.lineItem: [{ position: 10, importance: #HIGH, type: #WITH_URL, url: 'Url' }]
 @UI.selectionField: [{ position: 10 }]
 Carrid;
 @UI.lineItem: [{ position: 20, importance: #HIGH }]
 @UI.selectionField: [{ position: 20 }]
 Connid;
 @UI.lineItem: [{ position: 30, importance: #HIGH }]
 @UI.selectionField: [{ position: 30 }]
 @Consumption.filter.selectionType: #INTERVAL
 Fldate;
 @UI.lineItem: [{position: 40, importance: #MEDIUM }]
 Price;
 @UI.lineItem: [{position: 50, importance: #MEDIUM, type: #AS_DATAPOINT }]
 @UI.dataPoint: {targetValueElement: 'Seatsmax', visualization: #PROGRESS, criticality: 'SeatsCritical'}
 Seatsocc;
 @UI.hidden: true
 SeatsCritical;
}

Solltet ihr die ABAPConf 2021 verpasst haben kommt Ihr hier zu You tube , ab 5:22:40 gehts mit unserem Beitrag CDS Tipps & Tricks für Fiori Elements Entwicklung

Unsere Empfehlung SAP Fiori Elememts das Handbuch klicken sie hier: SAP Fiori Elements das Praxishandbuch

SAP Fiori Elements - Das Praxishandbuch
SAPUI5 Custom Controls – Teil 2

SAPUI5 Custom Controls – Teil 2

SAPUI5 Custom Control Teil 2

Der Weg zum eigenen Control

Da wir nun im letzten Teil alles über den generellen Aufbau eines SAPUI5 Custom Controls gelernt haben, möchten wir das ganze in der Praxis anwenden.

 

Wie lege ich im SAPUI5 Custom Control eine Liste von Personen?

Unsere Aufgabenstellung ist folgende:

Wir möchten einen Weg finden, um eine Liste von Personen gemäß hypothetischen Firmen-Design-Guidelines darzustellen. Leider reicht das UI5 Framework für die angenommene Einschränkung nicht aus.

Daher benötigen wir ein Custom Control. Genauer gesagt, benötigen wir folgende Komponenten:

  • PersonList – Darstellung unserer Liste
  • PersonListItem – Eine einzelne Zeile
  • style.css – Custom Styling

Optional können noch folgende Files angelegt werden:

  • PersonListRenderer – Zum ausgelagerten Rendern der Liste
  • PersonListItemRenderer – Zum ausgelagterten Rendern eines Items

PersonListItem im SAPUI5 Custom Control

Wir arbeiten uns von unten nach oben. D.h. wir fangen mit unserem aggregierten Control an, welches eben das einzelne Listitem wäre.

Ausgeben möchten wir Vorname, Nachname und das Alter der Person. Um noch ein Custom-CSS reinzubekommen, werden wir Personen mit einem Alter geringer als 18 anders formattieren.

Erstellen wir zunächst ein neues UI5 Projekt und legen die Files für die Custom-Controls an.

Anschließend definieren wir ein Template für das PersonListItem:

Wir wissen, dass wir mit sap.ui.define ein neues Modul anlegen, das zur Laufzeit dynamisch von unserem UI5 Framework geladen wird. Und genau so definieren wir eben auch ein Custom Control. Dieses inkludiert das sap.ui.core.Control, welches wir per .extend erweitern und zurückliefern.

Unsere PersonListItem soll 3 verschiedene Personaleigenschaften ausgeben. Daher brauchen wir 3 Properties (Vorname, Nachname, Alter).

Aggregations soll unser PersonListItem nicht haben, denn wir möchten das PersonListItem selbst als zu aggregierendes Control verwenden.

Properties anlegen

Wir benötigen 3 Properties:

  • firstName: string
  • lastName: string
  • age: int

Auf die Properties kann per get<PropertyName>() zugegriffen werden.

 

Events anlegen

Wir möchten, dass bei einem Click auf das PersonListItem ein Event ausgeführt wird. Dieses liefert eine Hallo-Message zurück.

  • sayHello
    • parameter: message(string)

Anschließend definieren wir eine Eventhandler für das HTML-onclick-Event. Falls dieses auftritt, triggern wir das sayHello-Event und liefern eine Message bestehend aus Name und „says hello“ per message-Parameter zurück.

 

CSS Styling

Wir möchten unsere 3 Properties per HTML-ul-Element anzeigen. Da ist jedoch das Problem, dass die Liste standartmäßig untereinander ihre Items anordnet. Um das zu umgehen, sagen wir per CSS-Klasssenselektor, das alle li-Elemente unter der Klasse die CSS-Property display mit dem Wert inline bekommen.

Und zusätzlich definieren wir noch ein padding von 10 Pixel und die Schriftfarbe black;

 

Renderer

Der Renderer ist das Herzstück unseres Controls. Hier wird definiert, was wann und wie in das DOM eingtragen werden soll.

Die wichtigsten Renderer-Funktionen sind dem letzten Blog-Teil zu entnehmen.

Wir möchten unser Control als div-Element und einer ul ausgeben. Zusätzlich möchten wir noch das Alter dementsprechend farblich hervorheben, basierend auf dem Kriterium, dass das Alter > 18 ist.

1: div ausgeben

Zu aller erst erstellen wir per openStart ein öffnendes div-Tag. Dieses div-Tag wird per writeControlData die Control-Referenz geschrieben und anschließend fügen wir noch unsere CSS-Klasse hinzu. Dann wird das öffnende div-Tag mit > geschlossen.

2: Liste aufbauen

Wir erstellen eine neue unordered-list. Als erstes List-Item geben wir den Vornamen der Person aus und dann den Nachnamen.

3: Alter ausgeben

Je nach dem ob die Person ein Alter > 18 hat, erstellen wir ein List-Item mit dem Style colorred oder color: green.

4: Alles schließen

Zu letzt schließen wir die Liste und abschließend das div-Tag.

 

Somit ist unser PersonListItem komplett. Im nächsten Schritt werden wir nun die PersonList definieren und unser PersonListItem aggregieren.

PersonList im SAPUI5 Custom Control

Die PersonList soll einen Titel bekommen und unsere Personen per PersonListItem anzeigen.

Hierfür benötigen wir Properties und Aggregations.

Metadata definieren

Wir benötigen folgende Property für unseren Titel:

  • title (string) – default: Persons

Zusätzlich möchten wir noch PersonListItems aggregieren:

  • items (PersonListItem) – multiple: true

CSS Styling

per list-style: none sagen wir, dass unsere Personenliste keine Aufzählungszeichen haben sollte.

Dann selektieren wir alle Items mit einem ungeraden Index und färben diese grau ein.

Zusätzlich geben wir noch ein seitliches margin von 15 Pixel.

Renderer definieren

In unserem Renderer wollen wir den Titel der Personenliste und aggregiert die PersonListItems ausgeben.

1: div öffnen

Gleich wie beim PersonListItem öffnen wir einen div-Container und vergeben CSS-Klasse und Control-Data.

2: Titel ausgeben

Der Titel wird innerhalb eines h2-Tags ausgebeben.

3: Items-Aggregation rendern

Per getAggregation(„items“) können wir uns den Inhalt der Items-Aggregation in einem Array speichern. Dieses Array laufen wir durch und erstellen für jeden Eintrag ein neues li-Tag mit der myPersonListItemSelector-Klasse. Dieses bekommt ihren Inhalt per renderControl()-Funktion, welche die render-Methode des übergebenen Controls aufruft. In unserem Fall ist das das PersonListItem.

4: alles schließen

 Abschließend fügen wir noch die schließenden ul- und div-Tags hinzu.

Jetzt sind unsere Custom-Controls fertig und können in den Views verwendet werden.

Controls verwenden

Die beiden Custom Controls können nun in unserer View verwendet werden.

1: Namespace einbinden

Um Controls aus einem anderen Namensraum einzubinden, muss für diesen ein Alias angelegt werden. Wir verweisen hier auf unseren Folder, wo wir die Controls angelegt haben.

2: PersonList einfügen

Wir legen eine neue PersonList an. Dort vergeben wir die title-Property und legen eine items-Aggregation an.

3: PersonListItems hinzufügen

In der items-Aggregation legen wir nun mehrere PersonListItems an. Das würde natürlich auch über Aggregation-Binding in der PersonList per Model funktionieren.

Wir legen aber z.B. 3 PersonListItems an und vergeben allen Properties Werte. Zusätzlich definieren wir eine Funktion für unser sayHello-Event.

Dieses müssen wir dann noch im zugehörigen Controller ausprogrammieren.

Also definieren wir eine neue Methode namens onSayHelloHandler, wo wir den Eventparameter message auslesen und per alert anzeigen.

App ausführen

Unsere App ist nun funktionsfähig und zeig unsere Custom-Controls richtig an.

Wir sehen nun unseren Titel und 3 darunterliegende Personen, die farblich abwechselnd hinterlegt sind.

Zusammenfassung

In 2 Blogteilen haben wir nun alles Notwendige gelernt, um mit dem Entwickeln von eigenen Custom-Controls durchzustarte, falls die Anforderungen nicht durch das umfangreiche SAPUI5 Controls-Paket abgedeckt wird.

Eine weitere Vorgehensweise könnte sein, meine eigenen Custom-Controls in eine UI5-Library/Git Repo zu packen und zu deployen. Dann kann ich diese in weiteren Applikationen verwenden und kann mir meine eigene, umfangreiche Library bauen.

Nur sollte man nicht für jede Anforderung ein neues Control entwickeln oder ein bestehendes zu erweitern. Man sollte so gut und so weit wie möglich mit dem arbeiten, was einem das SAPUI5 Framework zur Verfügung stellt und sich so weit wie möglich in die Materie einarbeiten.

Wer also gerne mehr bezüglich UI5 wissen möchte, kann sich gerne unseren zahlreichen Blogs bedienen.

Die interessantesten für das Controls-Thema sind:

Vielen Dank für das Lesen dieser Blogreihe und wenn Fragen auftreten, können sie gerne in den Kommentaren gestellt werden.

Data Binding in SAPUI5

Data Binding in SAPUI5

Übersicht

In diesem Blog werden wir uns mit Data Binding in SAPUI5, Open UI5 und SAP Fiori Apps beschäftigen.

Die Inhalte werden in unseren SAP Trainings bis ins kleinste Detail behandelt. Diese Trainings laufen unter den Titeln HOUI5 und HOFIO und werden bei SAP im offiziellen Schulungskatalog für Deutschland, Österreich und der Schweiz gelistet.

Inhalt

In diesem Blog zeigen wir Ihnen folgende Themen: 

  • Grundlegendes zum Data Binding
  • Databinding Modi
    • One-Time-Binding
    • One-Way-Binding
    • Two-Way-Binding
  • Arten von Databindings
    • Property Binding
    • Aggregation Binding
    • Element Binding
  • Databinding Syntax
    • Binding Pfad
    • Composite Binding
    • Expression Binding
    • Metadata Binding

Grundlegendes zum Data Binding in SAPUI5

In SAPUI5 und OpenUI5 können Sie das Data Binding einsetzen, um Daten aus dem Model unter Verwendung von UI-Controls darzustellen. Das ermöglicht Ihnen auch das Aktualisieren und Editieren der Daten direkt im User Interface, dadurch verknüpfen Sie das User Interface mit dem Model.

Hierfür benötigen Sie folgende zwei Dinge:

  • Ein Data Model (JSON, OData)
  • Eine Bindinginstanz

Als Data Model verwenden Sie üblicherweise ein JSON- oder ein OData-Model. Das Model hält für Sie die Daten vor und bietet Ihnen Methoden an , um mit dem Server zu kommunizieren. Zusätzlich bietet es Ihnen Möglichkeiten, um Data Bindings programmatisch zu erstellen. Wenn Sie die Methode aufrufen sorgt es dafür, dass eine Binding Instanz für Sie erstellt wird. Die Instanz beinhaltet Informationen zum Binding sowie bestimmte Events. Ein spezieller Event wird getriggert, wenn sich die gebundenen Daten ändern.

Welche Data Binding Modi im SAPUI5 gibt es?

Durch die Enumeration „sap.ui.model.BindingMode“ werden Ihnen drei verschiedene Data Binding Modi bereitgestellt. Diese können Sie unter Verwendung der Methode „.setDefaultBindingMode(bindingMode)“ allgemein auf ein Model anwenden. Optional können Sie es über das Property „oBindingInfo.mode“ auch auf einzelne Binding Instanzen verwenden.

One-Time-Binding – sap.ui.model.BindingMode.OneTime

Setzen Sie den BindingMode auf „OneTime“, werden die Daten einmalig vom Model gelesen. Ausserdem können Sie nicht manipuliert werden.

One-Way-Binding – sap.ui.model.BindingMode.OneWay

“OneWay”-Binding bedeutet, dass die Daten vom Model gelesen und an die View gebunden werden. Die Daten können Sie in der View zwar manipulieren, aber leider können Sie die Änderungen nicht zurück ins Model übertragen. Dieser Binding Modus war für das JSON-Model lange Zeit das Standardverhalten.

Two-Way-Binding – sap.ui.model.BindingMode.TwoWay

Möchten Sie in der View Daten manipulieren und die Änderungen automatisch in das Model übernehmen? Dann ist der Binding Mode „TwoWay“ genau das Richtige für Sie. Im Gegensatz zum One-Way-Binding können Sie Daten vom Model zur View und umgekehrt übertragen.

Arten von Data Bindings in SAPUI5 und OpenUI5

In SAPUI5 und OpenUI5 gibt es drei unterschiedliche Arten von Data Bindings. Wie sie damit am arbeiten, führen wir im Folgenden Beitrag für Sie näher aus. Im Data Binding müssen Sie immer einen Bindingpfad angeben. Diesen sollen Sie durch ‚{}‘ kennzeichnen

Je nachdem, ob Sie das Default-Model oder ein Named-Model verwenden, unterscheidet sich dieser Pfad geringfügig.  Wenn Sie ein  Named-Models verwenden wollen, müssen dem Namen der Property noch ein ‚modelName>‘ voranstellen.

Möchten Sie die Eigenschaft „FirstName“ auf die value-Eigenschaft eines Inputs binden (Property Binding), sieht das, bei der Verwendung eines Default-Models, wie folgt aus:

Verwenden Sie hingegen ein Named-Model, müssen Sie der Eigenschaft der Modelname voranstellen:

Property Binding

Verwenden Sie ein Property Binding, um beispielsweise Daten in einem Formular zu binden. Hierfür müssen Sie in der entsprechenden Eigenschaft (z.B.: text, value, …) einen Binding-Pfad angeben.

Am Propertynamen vorangestellten ‚/‘ erkenne Sie, dass es sich um einen absoluten Pfad handelt. Das bedeutet, das sich die Eigenschaft „FirstName“ auf der Root-Ebene des Default-Models befindet.

Aggregation Binding

Möchten Sie Listen auf ein UI-Control binden, kommt das Aggregation Binding zum Einsatz. Es wird meist in Listen und Tabellen verwendet, dabei müssen Sie auch ein Template angeben. Dieses wird für jedes Element in der Liste geklont. Innerhalb des Templates müssen Sie relative Pfade verwenden, da der Pfad des Aggregation Bindings bereits auf die entsprechende Liste verweisen. Anstelle eines Templates haben Sie auch die Option eine Factory-Function anzugeben. Die definiert, wie die einzelnen Einträge im User Interface dargestellt werden sollen.

Default-Model

Named-Model

Element Binding

Das Element Binding ermöglicht Ihnen das Binden einzelner Elemente einer Liste auf UI-Controls. Hierbei wird ein sogenannter Binding-Context erzeugt. Die Binding-Pfade müssen Sie immer relativ angeben.

Dieses SAPUI5 Data Binding können Sie überwiegend in Master-Detail Fiori Apps einsetzen.

Das Element-Binding können Sie auf folgende Arten umsetzen:

  • Aufrufen der Methode bindElement im Controller
  • Verwenden einer Binding-Property des Controls

Data Binding Syntax

Mit einem Binding-Pfad können Sie ein UI-Control auf die Daten des Models binden.  Wenn sie durch das definieren eines Pfades, erstellen Sie einen Binding-Context.

Composite Binding

Wenn Sie einen Formatter verwenden, ist es häufig der Fall, dass mehrere Werte an den Formatter übergeben werden müssen. Diese Anforderung können Sie mit einem Composite-Binding umsetzen. In der jeweiligen Eigenschaft (value, text, …) des UI-Control kann das parts-Array, eine Liste paths definieren.

Welche Arten von Expression Binding gibt es ?

Mithilfe des Expression-Binding können Sie simple Prüfungen – z.B.: Vergleich von Werten – direkt in der View zur Laufzeit durchführen. Dadurch ersparen Sie sich das Implementieren von zusätzlichen Formatter-Funktionen im Controller.

Sie können das Expression-Binding auf 2 Arten umsetzen:

  • ‚{=expression}‘: Es wird ein One-Way-Binding verwendet. Sollten sich Werte im Model ändern, wird auch das Binding aktualisiert.
  • ‚{:=expression}‘: Es wird ein One-Time-Binding verwendet. Der Wert wird einmalig ermittelt und anschließend nicht mehr aktualisiert.

Als expression können Sie beliebige Prüfungen implementieren. Dabei ist die Syntax ähnliche jener in Javascript, jedoch werden nicht alle JavaScript Expressions unterstützt. Innerhalb der Expression greifen Sie auf Modeldaten folgendermaßen zu: ‚${binding}‘ oder ‚%{binding}‘

Eine Prüfung und entsprechende Anzeige verschiedener Werte sieht wie folgt aus:

${binding} VS %{binding}

Verwenden Sie ‚${binding}‘ wird der Wert automatisch in den Typ der Eigenschaft des Controls konvertiert. Im Falle des Visible-Properties eines sap.m.Input Controls wäre dies der Typ ‚boolean‘. Wenn Sie nicht immer ist diese Konvertierung erwünschen, können Sie diese mit ‚%{binding}‘ umgehen. ‚%{binding}‘ ist eine Kurzform für ‚${path: ´binding´, targetType: ´any´}‘. Den targetType können Sie durch alle Typen, die sap.ui.model.odata.type bietet ersetzen.

Metadata Binding

Möchten Sie die Metadata-Eigenschaften wie sap:label, sap:createable, sap:updatable, … in der View abfragen, können Sie dies mit einem Metadata-Binding erreichen.

Auch hier können Sie zwei Ansätze verwenden.

Absolute Bindings

Absolute Bindings sehen folgendermaßen aus:

/#EntityName/PropertyName/@Attribut

Relative Bindings

Nun zeige ich ihnen wie Relative Bindings aussehen:

/EntitySetName/PropertyName/#@Attribut

Best-Practice Beispiel zum Data Binding in SAPUI5 mit OData-Model und Two-Way-Binding

Abschließend hab ich noch für Sie ein kurzes Best-Practice Beispiel vorbereitet. Wir schicken mit Hilfe eines OData-Models und Two-Way-Binding ein Update auf die Details eines Employees.

Hier können sie folgende Methoden verwenden:

  • hasPendingChanges: Zum Abfragen, ob es Änderungen gibt
  • submitChanges: Mit ‚Save‘ werden Sie die Änderungen ans Backend schicken
  • resetChanges: Mit ‚Discard‘ werden Sie die Änderungen verwerfen

View:

Controller:

Bei unserem Blog über Data Binding in SAPUi5 haben sie nun viele Informationen bekommen. Wenn sie an weiteren Themen interessiert sind, klicken sie hier unten auf GIT oder SAPUI5 Custom Controls. 

Wollen Sie, dass  wir uns um Ihre Szenarien kümmern? Nehmen Sie gerne Kontakt auf den  klassische SAP Beratung und SAP Cloud Consulting liegt uns .Egal ob Deutschland, Schweiz oder Österreich – unser Team bestehend aus erfahrerenen Beratern und Entwicklern ist gerne für Sie da!

Wir lassen sie nicht in der Cloud hängen den SAP ( Cloud ) Consulting liegt in unsere DNA