Beispielprojekte und Anwendungsfälle > Anwendungsfall: 3D-Guided Service Instructions > 3D-Guided Service Instructions 302: Einfachen ThingWorx Dienst zu Vuforia Studio hinzufügen > getPriceAvailability aufrufen und den Ereignis-Listener "serviceInvokeComplete" verwenden
  
getPriceAvailability aufrufen und den Ereignis-Listener "serviceInvokeComplete" verwenden
Nachdem der Dienst getPriceAvailability zu Vuforia Studio hinzugefügt wurde, muss er im Erlebnis aufgerufen werden, damit die Daten zur Bearbeitung verfügbar sind. Dazu müssen Sie den Code aus 3D-Guided Service Instructions 301 aktualisieren. Darüber hinaus muss dem Code ein neuer Ereignis-Listener hinzugefügt werden, damit die Daten von diesem Dienst für das Erlebnis verfügbar sind.
* 
Der vollständige Code für diesen Abschnitt ist in Appendix 1 in GitHub verfügbar.
1. Öffnen Sie Home.js.
2. Nehmen Sie im Ereignis-Listener userpick die folgenden Änderungen vor:
a. Löschen Sie die Variable priceString. Der Datenzugriff erfolgt nun von dem shoppingThing in Vuforia Studio anstelle von den Attributen im Modell.
b. Erstellen Sie ein Objekt mit dem Namen meta, und legen Sie dafür den Geltungsbereich der Anwendung fest, damit verschiedene Funktionen im Skript darauf zugreifen können. Ändern Sie die Variablen partName, instructionName und partNumber, sodass sie Eigenschaften des meta-Objekts sind.
//
// create an object with the properties below that are based on attribute names from Creo Illustrate for this model. Use metadata.get to obtain the data from the JSON properties for this occurrence.
$scope.meta = {
partName : metadata.get(pathId, 'Display Name'),
instructionName : metadata.get(pathId, 'illustration'),
partNumber : metadata.get(pathId, 'partNumber'),
} // $scope.meta end
c. Löschen Sie die Variable price und den Anwendungsparameter priceInfo, da sie direkt von der Variablen priceString abhängig waren.
d. Bearbeiten Sie die Definition der Anwendungsparameter itemName und itemNumber, sodass sie mit der neuen Syntax zum Aufruf von partName und partNumber aus dem meta-Objekt übereinstimmen. Erstellen Sie dann eine neue Variable mit dem Namen target (Geltungsbereich der Anwendung), und legen Sie sie für die Variable targetName aus dem Ereignis userpick fest.
//
// set itemName app parameter to be equal to the partName variable, same relationship with itemNumber and partNumber and priceInfo and price.
// Set the itemCount to 1 for the purpose of this section, since it is not hooked up to an actual inventory.
$scope.app.params.itemName = $scope.meta.partName;
$scope.app.params.itemNumber = $scope.meta.partNumber;
$scope.app.params.itemCount = 1;

$scope.target = targetName;
e. Fügen Sie den folgenden Code hinzu, um den Dienst getPriceAvailability im shoppingThing auszulösen. Dieser Code ist im Format twx.app.fn.triggerDataService ('<TWX Entität>', '<TWX Dienst>', '<Parameter>'). Die Funktion triggerDataService ruft einen Dienst auf, der von ThingWorxVuforia Studio bereitgestellt wird, bei dem die ThingWorx Entität und der ThingWorx Dienst zusammen mit allen vom Dienst verwendeten Eingabeparametern aufgerufen werden. In unserem Fall ist das aufgerufene Ding shoppingThing. Es enthält alle Teileinformationen, den aufgerufenen Dienst (getPriceAvailability) und den Parameter (pid), welcher ein Parameter für die Teilenummer des ausgewählten Teils ist. Die Ausgabe dieses Diensts wird über eine asynchrone Callback-Funktion aufgerufen, die den Ereignis-Listener serviceInvokeComplete aufruft. Der Ereignis-Listener serviceInvokeComplete wird später in diesem Abschnitt erstellt.
//
// call the getPriceAvailability ThingWorx service based on partNumber
twx.app.fn.triggerDataService('shoppingThing', 'getPriceAvailability', {pid: $scope.meta.partNumber})
f. Die if-Anweisung für die Popups unten wird aus dem Ereignis-Listener userpick in den Ereignis-Listener serviceInvokeComplete verschoben. Kopieren Sie die schließenden Klammern für die PTC Metadaten-API, die catch-Anweisung sowie die schließenden Klammern für userpick, und fügen Sie sie unterhalb des Dienst-Triggers ein. Vergessen Sie nicht, den Code, den Sie gerade unter der "disassemble"-Funktion für das Popup kopiert haben, zu löschen, um keine zusätzlichen Klammern zu erhalten.
}) //end brackets for PTC API and .then
//
//catch statement if the promise of having a part with metadata is not met
.catch( (err) => { console.log('metadata extraction failed with reason : ' +err) })
}) //end brackets for userpick function. Will continue to move throughout code
3. Nachdem der Ereignis-Listener userpick aktualisiert wurde, erstellen Sie nun als nächsten Schritt den Ereignis-Listener serviceInvokeComplete. Dieser Ereignis-Listener wird erst aktiviert, wenn der Dienst getPriceAvailability abgeschlossen wurde.
a. Fügen Sie den folgenden Code für den Ereignis-Listener oberhalb der if-Anweisung für das Popup hinzu. Wählen Sie den Code vom Anfang der if-Anweisung bis zum Ende der disassemble-Funktion aus, und rücken Sie ihn für die korrekte Ausrichtung aus.
* 
In einem roten Kreis neben dieser Zeile befindet sich ein X, da die Endklammer dafür noch nicht erstellt wurde. Dies ist ein erwartetes Verhalten.
$scope.$on('getPriceAvailability.serviceInvokeComplete', function(evt) {
b. Der Prozess zum Aufrufen des Popups ändert sich jetzt, da Daten dynamisch von ThingWorx hinzugefügt werden. Erstellen Sie unter dem Ereignis-Listener serviceInvokeComplete eine Variable mit dem Namen rowData, die die aktuelle Zeile der Infotable aufruft, die mit dem Dienst getPriceAvailability erstellt wurde.
//
// variable holding all data for the current row in the infotable
var rowData = twx.app.mdl['shoppingThing'].svc['getPriceAvailability'].data.current
c. Fügen Sie im nächsten Schritt Skripte hinzu, um den Preis des ausgewählten Objekts zu ermitteln. Die Variable price verwendet Informationen aus ThingWorx und wird entweder als Zeichenfolge mit dem Preis des Teils in der ausgewählten Zeile mit einem $ davor angezeigt oder als ‘UNAVAILABLE’, wenn das Teil nicht verfügbar ist. Die von der Variablen price verwendeten Informationen werden mit einem bedingten Operator erstellt, der die Verfügbarkeit des Teils validiert, bevor der Preis des Teils geprüft wird. Dies kann auch mit einer if-Anweisung mit den gleichen Bedingungen erfolgen. Eine ähnliche Logik wird verwendet, um den Anwendungsparameter priceInfo zum Addieren von Preisen im Einkaufswagen zu erstellen.
//
// price is going to be the variable that is referenced in the popup, while the app parameter priceInfo will be used for adding the total in the cart
var price = rowData.avail === true ? '$' + rowData.price
: 'UNAVAILABLE';
$scope.app.params.priceInfo = rowData.avail === true ? parseFloat(rowData.price)
: undefined ;
d. Erstellen Sie eine Variable mit dem Namen meta, die verwendet wird, um das $scope.meta-Objekt in den Ereignis-Listener als lokales Objekt aufzurufen und auf diese Weise einen einfachen Zugriff auf seine Werte zu ermöglichen.
//
// create a variable to bring the $scope.meta object into this event listener as a local object
let meta = $scope.meta
e. Da dem Popup zusätzliche Informationen hinzugefügt werden, um anhand von Informationen aus dem shoppingThing zu bestimmen, ob ein Teil verfügbar ist oder nicht, wird die Vorlage für das Popup jetzt mit einer Funktion definiert, die später in der Aktivität erstellt wird. Löschen Sie daher vorerst die Bedingungen und die schließenden Klammern für die if-Anweisung, die Sie zuvor erstellt haben, und rücken Sie den Code für den Popup-Aufruf aus.
f. Löschen Sie den Code für das Popup, das zuvor im Falle von else für die if-Anweisung angezeigt worden wäre. Löschen Sie außerdem den Wert für die Eigenschaft template. Der Wert wird im nächsten Schritt ersetzt. Neben diesen Codezeilen werden Fehlerhinweise angezeigt, die jedoch durch das Füllen des Vorlagenwerts behoben werden.
g. Die Eigenschaft template sollte einen Wert haben, der die setTemplate-Funktion (die später erstellt wird) mit Eingaben des meta-Objekts und der Variablen price für das ausgewählte Teil aufruft. Der Code zum Aufrufen des Popups sollte jetzt mit dem unten angegebenen Code übereinstimmen.
//
// adds an ionic popup when a part is clicked
$scope.popup = $ionicPopup.show({
//
//call the function for setting the template
template: $scope.setTemplate(meta, price),
//
// set the scope for the popup
scope: $scope
}); //end of ionic popup
h. Zum Festlegen der Animationssequenz des Modells müssen für die disassemble-Funktion die Eigenschaften model und instruction in modelObject aktualisiert werden. An dieser Stelle wird auf die zuvor erstellte Variable $scope.target zugegriffen und instructionName mit seinem neuen Speicherort innerhalb des meta-Objekts aktualisiert.
//
// function to be bound to the Disassemble button in the popup
$scope.disassemble = function () {
//
// set an object that targets the model and its instruction property
var modelObject = { model: $scope.targetName,
instruction: 'l-Creo 3D - ' + meta.instructionName + '.pvi' };
//
// set the sequence for the quadcopter to be the name of the associated instruction
$scope.view.wdg.quadcopter.sequence = modelObject.instruction
} //disassemble function end
i. Fügen Sie eine Endklammer und eine runde Klammer hinzu, um den Aufruf des Diensts getPriceAvailability abzuschließen.
}) // getPriceAvailability end
4. Es muss ein weiterer userpick-Ereignis-Listener hinzugefügt werden, um den Prozess für die Verwendung von Ionic-Popups in Ihrem Erlebnis zu optimieren. Dieser Ereignis-Listener wird verwendet, um ein Popup zu schließen, das vor dem Klicken auf ein anderes Teil nicht geschlossen wurde. Wenn dieser Ereignis-Listener ausgelöst wird, wird das Popup für das erste geklickte Teil geschlossen und der Shader wird aus ihm entfernt, bevor ein neues Popup und Schattierung im nächsten ausgewählten Teil geöffnet wird.
//
// userpick event listener that will take place when you click on another part without choosing an option in the popup
$scope.$on('userpick', function (event, targetName, targetType, eventData) {

//
// close the popup and remove the shader from the part even when you didn't chose an option from the popup
$scope.popup.close()

$scope.hiliteOff()

}) // closing userpick end
5. Der letzte Schritt bei der Aktualisierung Ihres Erlebnisses ist wie bereits erwähnt das Erstellen der setTemplate-Funktion. Diese Funktion wird verwendet, um die Variable template festzulegen, die im Popup verwendet wird, um die für das Teil verfügbaren Informationen zu bestimmen. Sie enthält auch eine Logik, um zu bestimmen, ob einem Teil eine Demontagesequenz zugeordnet ist und ob diese in shoppingThing verfügbar ist.
a. Erstellen Sie unter der clearCart-Funktion eine Funktion mit dem Namen setTemplate mit Eingaben von meta und price.
//
// function for setting the template for the Ionic popup
$scope.setTemplate = function (meta, price) {

} // setTemplate end
b. Fügen Sie der Funktion zunächst eine Logik hinzu, um festzustellen, ob dem ausgewählten Teil eine Demontagesequenz zugeordnet ist. Die instr-Variable verwendet einen bedingten Operator, um zu prüfen, ob die Eigenschaft instructionName von meta gefüllt ist oder nicht, und ersetzt die zuvor verwendete if-Anweisung. Wenn eine Sequenz zugeordnet ist, wird eine Schaltfläche erstellt, die beim Anklicken die disassemble-Funktion auslöst, den Shader deaktiviert und das Popup schließt. Wenn keine Sequenz zugeordnet ist, wird instr eine leere Zeichenfolge.
//
// if there is a disassembly sequence associated with the part, create a Disassemble button in the popup, if not, no button will appear
var instr = meta.instructionName.length > 0 ? '<div class="btndisassemble" ng-click="hiliteOff();popup.close();disassemble();">Disassemble</div>'
: '';
c. Darüber hinaus müssen Sie Logik hinzufügen, um zu ermitteln, ob ein Teil verfügbar ist oder nicht. Erstellen Sie die addTo-Variable als Ergebnis eines bedingten Operators, der anhand der Informationen in shoppingThing ermittelt, ob einem Teil ein Preis zugeordnet ist. Wenn dies der Fall ist, wird der Preis im Popup zusammen mit der anklickbaren Schaltfläche Add to Cart angezeigt, die die addToCart-Funktion auslöst. Falls nicht, wird lediglich der Preis zum Popup hinzugefügt.
//
// if price != unavailable, define an add to cart button and have the price displayed in the popup, if it is unavailable, just display price
var addTo = price != 'UNAVAILABLE' ? price + '&nbsp; </div><div class="btnadd" ng-click="hiliteOff();popup.close();addToCart();">Add to Cart</div>'
: price ;
d. Nachdem die verfügbaren Schaltflächen für das Popup ermittelt wurden, wird die Variable template genauso erstellt wie die für vorherige Popups. Das Popup zeigt die Menge, die Teilenummer, den Teilenamen und den Preis des ausgewählten Teils sowie die für das Teil geltenden Schaltflächen an. Die Schaltfläche Continue wird erneut hinzugefügt, um das Popup zu schließen. Für die Variable template wird eine return-Anweisung hinzugefügt, sodass beim Ausführen der Funktion eine Ausgabe erfolgt. Dies schließt die setTemplate-Funktion ab.
//
// build the template for the popup
var template = '<div>' + $scope.app.params.itemCount + 'x  ' + meta.partNumber +
'&nbsp;</br>' + meta.partName +
'&nbsp;</br>' + addTo + instr +
'<div class="btncontinue" ng-click="hiliteOff();popup.close();">Continue</div>' ;

//
// return the template variable when this function is called
return template
6. Klicken Sie auf Vorschau.
a. Klicken Sie auf die Basis des Quadcopter, um die Popup-Option anzuzeigen für ein Teil, das zwar verfügbar ist, dem jedoch keine Demontagesequenz zugeordnet ist. Klicken Sie auf Continue, um das Popup zu schließen.
* 
Wenn Sie nicht auf die Schaltfläche Continue klicken, bevor Sie auf ein anderes Teil klicken, werden die Popups übereinander angezeigt, anstatt dass das erste Popup geschlossen wird.
b. Wählen Sie einen der Rotoren aus, um das Popup für ein Teil anzuzeigen, dem eine Demontagesequenz zugeordnet ist und das verfügbar ist.
c. Wählen Sie die Oberseite des Quadcopter aus, um das Popup für ein Teil anzuzeigen, dem keine Demontagesequenz zugeordnet ist und das nicht verfügbar ist.
Wählen Sie einen der Motoren aus, um das Popup für ein Teil anzuzeigen, dem zwar eine Demontagesequenz zugeordnet ist, das aber nicht verfügbar ist.
7. Dieser Abschnitt ist jetzt abgeschlossen. Der übrige Code in diesem Abschnitt ist der gleiche Code wie in 3D-Guided Service Instructions 301. Es sollte möglich sein, auf ein Teil zu klicken, ein Popup sollte angezeigt werden, und Sie sollten eine der vier oben genannten Optionen für ein Popup erhalten. Und falls zutreffend, sollten Sie das Teil dem Einkaufswagen hinzufügen können. Es sollte auch möglich sein, mit dem userInput-Widget nach Teilen zu suchen.
Im letzten Abschnitt dieses Anwendungsfalls werden Sie den persistenten Einkaufswagen mit ThingWorx erstellen.