OpenUI5/SAPUI5 Expression Binding in Beispielen

Einleitung

Mit Version 1.28 wurde Expression Binding eingeführt. Richtig eingesetzt, ermöglicht Expression-Binding teils triviale und manchmal auch nicht ganz triviale Logiken im View abzubilden, die man sonst mit Hilfe eines Formatters extern implementieren müsste.

Analog dem Grundsatz "Ein Bild sagt mehr als tausend Worte", versuche ich hier Expression Binding in Beispielen zu erläutern. Alle Beispiele sind auf JSFiddle erstellt worden und laden zum Ausprobieren ein.

Alles nur JavaScript?

Grundsätzlich wird Expression Binding mit {= oder {:= eingeleitet. {= beschreibt hierbei das am meisten verwendete One-Way-Binding, bei dem der Inhalt des Binding jedes mal neu berechnet wird, wenn ein gebundenener Model-Wert sich ändert. {:= hingegen wird nur einmalig am Anfang ausgewertet.

Innerhalb der Expression können JavaScript-Ausdrücke ausgewertet werden. Zum Beispiel können zwei Zahlen addiert werden:

<Input value="{=17+10}"/> <!-- 27 -->  

Aufgewertet wird das Expression Binding dadurch, dass man zusätzlich Variablen in Form von Model-Bindings verwenden kann. Zugriff erhält man hierbei durch die Abbrevation ${}.

Aber ist das denn auch sicher?

Wie immer bei JavaScript muss man darauf achten, dass JavaScript nicht typensicher ist.

<Input value="{:=${/value1} + ${/value2} + 3 - 3}" /> <!-- 27 -->  
<Input value="{:=${/value1} + ${/value2} + '3' - '3'}" /> <!-- 270 -->  
<Input value="{:='' + ${/value1} + ${/value2}}" /> <!-- 1710 -->  
<Input value="{:=${/value1} + ${/value2} + ''}" />  <!-- 27 -->  

Einmal, Zweimal,... Keinmal?

Was hier noch trivial wirkt, kann bei der Verwendung des One-Way-Bindings im Expression-Binding und einem Two-Way-Binding in einem anderen Control zu unerwarteten Problemen führen.

<Input value="{/value1}" valueLiveUpdate="true"/>  
<Input value="{/value2}" valueLiveUpdate="true"/>  
<Input value="{=${/value1} + ${/value2}}" />  

Versuchen Sie im folgenden Beispiel mal den Wert eines der beiden Values zu ändern.

Das Problem tritt hierbei auf, dass im Model anfangs der Wert als Zahl 17 hinterlegt wurde, jedoch das Change-Event den Zahl-Wert beim Ändern mit einem String "17" überschreibt. Der Operator + bewirkt dann in JavaScript die Konkatinierung von String

Auch eine Angabe von type="Number" bei den Input-Feldern hilft an dieser Stelle nicht, da diese nur die Eingabe des Input-Felds überwachen/validieren.
Abhilfe schafft hier zum Beispiel ein alter JS-Trick:

<Input value="{=(${/value1} * 1) + (${/value2} * 1)}" />  

Da Expression-Binding auch das Ausführen von Funktionen unterstützt, kann man auch eine echte Konvertierung vornehmen:

<Input value="{:=Number(${/value1}) + Number(${/value2})}" />  

Wie bereits eingangs erwähnt kann das Expression Binding auch als One-Time-Binding eingerichtet werden. Hierzu wird statt {= einfach {:= verwendet. Die Expression wird in diesem Fall einmal zu Anfang ausgeführt, jedoch danach nicht mehr geupdated, wenn sich ein Wert ändern sollte.

Ärgerlich... Hat man in einer komplexen Expression mal einen kleinen Syntax-Fehler, wie eine fehlende Klammer, erhält man wie zu Erwarten kein Ergebnis, aber auch keinen Hinweis wo man anfangen sollte zu suchen.

Und was bringt mir das?

Addition mit einem Formatter

// Globales Formatter Objekt
Formatter = {  
    add: function(a, b) {
      return a*1 + b*1;
  }
};
<Input value="{  
  parts: [
          {path: '/value1'},
          {path: '/value2'}
      ],
      formatter: 'Formatter.add'
    }" />

vs.

Addition mit Expression Binding

<Input value="{=(${/value1} * 1) + (${/value2} * 1)}" />  

Mit Expression-Bindings können viele Formatter-Funktionen eingespart werden. Sehr oft werden zum Beispiel Control-Elemente ein-/ausgeblendet oder aktiviert/deaktiviert abhängig von dem Status einer Eigenschaft. Wenn diese Eigenschaft nicht zufälligerweise true oder false zurückgegeben hat, musste man immer einen Formatter implementieren, der als Abhängigkeit geladen werden musste und dann View-Logik implementiert hat, die meist trivial war.

Daher können alle auf der Dokumenations-Seite genannten Operatoren verwendet werden, um Conditions einzurichten.

Muss ich sonst noch was beachten?

Bei den genannten Operatoren muss beachtet werden, dass gewisse Zeichen in XML escaped werden müssen, da man sonst keine Ausgabe erhält, sondern stattdessen eine Fehlermeldung.
Hierunter fallen die sehr oft verwendeten Zeichen & und <.
So wird aus ${/value1} && ${/value2} ==> ${/value1} &amp;&amp; ${/value2}

View Comments