Bei der Entwicklung von Arbeitsabläufen kann es vorkommen, dass die bisher besprochenen Werkzeuge nicht ausreichen, um die erforderliche Logik zu implementieren. Dies ist typischerweise immer dann der Fall, wenn Sie die rohen Eingabedaten manipulieren müssen, z. B. bevor Sie sie in einem Ausdruck vergleichen oder in einer Kontextvariablen speichern. In diesen Fällen sollte die Option, unsere eingebettete JavaScript (JS)-Engine im Workflow-Markup zu verwenden, eine praktikable Lösung bieten.
Die Verwendung von JavaScript in einem Workflow sollte immer innerhalb eines <![CDATA[ ... ]]>
Tags erfolgen, um XML-Parserfehler zu vermeiden. Ein JS-Bereich wird mit ?{ .
.. }?
. Sie können innerhalb des JS-Bereichs mit context.variable_name
auf Kontextvariablen zugreifen. Um auf Ereignisdaten zuzugreifen, würden Sie z. B. event.field
verwenden:
<setvar id="add_digit_from_speech_command">
<context_of>workflow</context_of>
<context_update>
<param name="number" type="long"><![CDATA[ ?{ context.number + Number(event.command.substr(event.command.length - 1, event.command.length)) }? ]]></param>
</context_update>
</setvar>
Wie Sie im obigen Beispiel sehen können, können Sie beliebige native JS schreiben. Dies kann auch mehrere Zeilen und eine komplexere Handhabung umfassen. Auf der nächsten Seite sehen Sie einige weitere Beispiele.
Eingebettete Funktionen
Es gibt einige eingebettete Funktionen, die Sie direkt im Workflow-XML verwenden können, ohne einen JS-Kontext zu öffnen. Einige dieser Beispiele werden regelmäßig in bestimmten Anwendungsfällen verwendet:
- exists: exists(#{shelve})
- toUppercase: toUppercase( '#{material_name} ' )
- toLowercase: toLowercase( '#{material_name} ' )
- trim: trim( # {material_name} )
- enthält: enthält( # {erster_code}, #{zweiter_code})
- startsWith: startsWith( # {erster_code}, #{zweiter_code})
- endsWith: endsWith( # {erster_code}, #{zweiter_code})
- gleich: gleich( # {erster_code}, #{zweiter_code})
- substring: substring( # {material_name}, 0, 3)
Das folgende Beispiel enthält die Funktionen toUpperCase
, trim
und substring
.
<rule id="speak_material">
<expression><![CDATA[ #{event:command} == toUpperCase('#{material_name}') ]]></expression>
<actions>
<setvar id="set_material_type">
<context_update>
<param name="material_type" type="string">trim(substring(#{material_name}, 0, 3))</param>
</context_update>
</setvar>
</actions>
</rule>
Das obige Beispiel ist typisch, denn Sprachbefehle werden immer in Großbuchstaben ausgegeben. Wenn Sie einen Sprachbefehl mit einem Inhalt in Ihrem Arbeitsablauf vergleichen wollen, sollten Sie ihn immer auch in Großbuchstaben umwandeln.
Tipps und Tricks: Verwenden Sie keine Leerzeichen zur besseren Lesbarkeit des Codes innerhalb eines param-Tags
vom Typ string
, da diese Teil der zu bearbeitenden Zeichenkette werden würden. Ein Beispiel: <param name="material_type" type="string">trim(substring(#{material_name}, 0, 3)) </param>
würde z.B. MAT_
ergeben (wobei _ ein Leerzeichen ist), obwohl Sie trim verwendet haben.
Beispiel
Sehen wir uns einige weitere Beispiele für Anwendungsfälle an, in denen die JS-Engine nützlich ist:
Dynamischer Zugriff auf Daten
Manchmal müssen Sie dynamisch auf Daten zugreifen (basierend auf dem Inhalt einer anderen Kontextvariablen):
<setvar id="set_step">
<context_update>
<param name="step" type="object"><![CDATA[ ?{context.steps[context.current_step_index]}? ]]></param>
</context_update>
</setvar>
Bedingte Datenmanipulation
Sie könnten zwar auch mehrere Aktionen und Regeln erstellen, um dies zu realisieren, aber mit JS können Sie sich kurz fassen:
<setvar id="set_text_color">
<context_update>
<param name="label_text_color" type="string"><![CDATA[ ?{ (context.urgent)? 'red' : 'black' }? ]]></param>
</context_update>
</setvar>
Erzeugung und Manipulation von Objekten
Mit JavaScript können Sie auch Objekte erzeugen oder manipulieren. In dem folgenden Beispiel soll der Arbeiter in die Lage versetzt werden, mit Sprachbefehlen einen Betrag von 0-99 auszudrücken. Jeder Sprachbefehl muss separat zur Sprachgrammatik hinzugefügt werden, aber mit JavaScript können wir dies abkürzen:
<action id="add_amount_speech_commands" type="speech_modify_commands_in_grammar">
<param name="slot">wf_editor_slot</param>
<param name="commands"><![CDATA[ ?{
Array.apply(null, {length: 100})
.map(Number.call, Number)
.map(function(e) {
return { 'name': 'AMOUNT ' + (e), 'description': `AMOUNT [0-99]`}
}
)}? ]]></param>
<param name="modification">add_commands</param>
</action>
In Ausdrücken
Es gibt auch Anwendungsfälle, in denen JS bei Ausdrücken hilft. Im folgenden Beispiel verarbeiten wir ein Ereignis, das ausgelöst wird, wenn ein Gerät eines Drittanbieters abgeschaltet wird. Wir verwenden JS, um eine Kette von MAC-Adressen nach der MAC des getrennten Geräts zu durchsuchen.
<rule id="device_vanished">
<expression><![CDATA[ #{event:command}== 'DEVICEVANISHED' && ?{context.mac.search(event.mac)>-1}?]]></expression>
<actions>
<action ref="back_to_start"/>
</actions>
</rule>
Beachten Sie, dass die Verwendung von JavaScript auf Ausdrücke beschränkt ist: Der Inhalt aller Ausdrücke wird abgeschnitten, um alle Zeilenumbrüche und Leerzeichen zu entfernen, die die Logik unterbrechen könnten. Daher können Sie nicht mehrere Zeilen JavaScript in Ausdrücken verwenden.
Wildcard-Widget
Ein weiterer typischer Anwendungsfall für JS ist das Platzhalter-Widget. Da wir das Layouten noch nicht eingeführt haben, werden wir hier kein Beispiel betrachten, aber die Widget-Dokumentation enthält eines.
Zuweisung
Aufgabe 1:
In der aktuellen Version unserer Komponente ist die Ausgabe unserer Wahl ganz in Großbuchstaben und wird als solche in der Benutzeroberfläche der nächsten Komponente angezeigt. Lassen wir es ein bisschen netter aussehen:
- Verwenden Sie JavaScript oder eingebettete Funktionen, um die resultierende Auswahl in einer natürlicheren Großschreibung zu speichern.
Komponente herunterladen
Lösung
Nachstehend finden Sie ein Lösungsbeispiel:
<rule id="choice_made">
<expression><![CDATA[ #{event:command} == 'APPLE' || #{event:command} == 'PEAR' ]]></expression>
<actions>
<setvar id="save_choice">
<context_of>workflow</context_of>
<context_update>
<param name="choice" type="string"><![CDATA[ ?{ event.command.slice(0,1) + event.command.slice(1).toLowerCase() }? ]]></param>
</context_update>
</setvar>
<action ref="show_confirmation_dialog"/>
</actions>
</rule>
Download-Komponente (Post-Assignment)
In der nächsten Lektion werden wir uns schließlich damit beschäftigen , wie man die Benutzeroberfläche einer Komponente gestaltet.