Exemples de projets et de cas d'emploi > Cas d'utilisation : 3D-Guided Service Instructions > 3D-Guided Service Instructions 302 - Ajout d'un service ThingWorx simple à Vuforia Studio > Appel de getPriceAvailability et utilisation du module d'écoute d'événement serviceInvokeComplete
  
Appel de getPriceAvailability et utilisation du module d'écoute d'événement serviceInvokeComplete
Une fois que le service getPriceAvailability a été ajouté à Vuforia Studio, il doit être appelé dans l'expérience afin de rendre les données accessibles pour la manipulation. Pour ce faire, vous devez mettre à jour le code à partir de 3D-Guided Service Instructions 301. En outre, un nouveau module d'écoute d'événement doit être ajouté au code afin que les données de ce service soient accessibles par l'expérience.
* 
Le code complet de cette section est disponible dans l'Appendix 1 sur GitHub.
1. Ouvrez Home.js.
2. Dans le module d'écoute d'événement userpick, apportez les modifications suivantes :
a. Supprimez la variable priceString ; les données seront à présent accessibles à partir de shoppingThing dans Vuforia Studio plutôt qu'à partir des attributs du modèle.
b. Créez un objet nommé meta et définissez-le sur la plage de l'application de sorte qu'il soit accessible par différentes fonctions dans le script. Modifiez les variables partName, instructionName et partNumber afin qu'elles soient des propriétés de l'objet meta.
//
// 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. Supprimez la variable price et le paramètre d'application priceInfo car ils étaient directement dépendants de la variable priceString.
d. Modifiez la définition des paramètres d'application itemName et itemNumber afin qu'ils soient cohérents avec la nouvelle syntaxe d'appel de partName et partNumber à partir de l'objet meta. Créez ensuite une nouvelle variable nommée target (plage de l'application) et définissez-la sur la variable targetName à partir de l'événement userpick.
//
// 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. Ajoutez le code suivant pour déclencher le service getPriceAvailability dans shoppingThing. Ce code suit un format twx.app.fn.triggerDataService ('<Entité TWX>', '<Service TWX>', '<paramètre>'). La fonction triggerDataService appelle un service fourni par ThingWorxVuforia Studio, dans lequel l'entité et le service ThingWorx sont appelés, ainsi que les paramètres d'entrée que le service exécute. Dans notre cas, l'objet appelé est shoppingThing, qui contient toutes les informations sur la pièce, le service appelé (getPriceAvailability) et le paramètre (pid), qui est un paramètre pour le numéro de la pièce sélectionnée. La sortie de ce service est appelée à l'aide d'un rappel asynchrone, qui appelle le module d'écoute d'événement serviceInvokeComplete. Le module d'écoute d'événement serviceInvokeComplete sera créé ultérieurement dans cette section.
//
// call the getPriceAvailability ThingWorx service based on partNumber
twx.app.fn.triggerDataService('shoppingThing', 'getPriceAvailability', {pid: $scope.meta.partNumber})
f. L'instruction if pour les fenêtres contextuelles ci-dessous sera déplacée hors du module d'écoute d'événement userpick, dans le module d'écoute d'événement serviceInvokeComplete. Copiez les crochets fermants de l'API des métadonnées PTC, l'instruction catch et les crochets fermants userpick, puis collez-les sous le déclencheur de service. Assurez-vous de supprimer le code que vous venez de copier sous la fonction désassembler pour la fenêtre contextuelle, ou des crochets supplémentaires s'afficheront.
}) //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. Une fois le module d'écoute d'événement userpick mis à jour, il est temps de créer le module d'écoute d'événement serviceInvokeComplete. Ce module d'écoute d'événement ne sera activé qu'une fois le service getPriceAvailability terminé.
a. Ajoutez le code suivant pour le module d'écoute d'événement au-dessus de l'instruction if pour la fenêtre contextuelle. Sélectionnez le code depuis le début de l'instruction if jusqu'à la fin de la fonction disassemble et diminuez le retrait pour l'aligner correctement.
* 
Un X dans un cercle rouge s'affichera en regard de cette ligne car le crochet fermant correspondant n'a pas encore été créé. Ceci est attendu.
$scope.$on('getPriceAvailability.serviceInvokeComplete', function(evt) {
b. Le processus d'appel de la fenêtre contextuelle change maintenant que les données sont ajoutées dynamiquement à partir de ThingWorx. Sous le module d'écoute d'événement serviceInvokeComplete, créez une variable nommée rowData, qui appellera la ligne actuelle de la table d'informations qui a été créée avec le service getPriceAvailability.
//
// variable holding all data for the current row in the infotable
var rowData = twx.app.mdl['shoppingThing'].svc['getPriceAvailability'].data.current
c. Ensuite, ajoutez un script pour déterminer le prix de l'objet sélectionné. La variable price utilisera les informations de ThingWorx et sera définie sur une chaîne avec le prix de la pièce dans la ligne sélectionnée avec un $ devant, ou ‘UNAVAILABLE’ si la pièce n'est pas disponible. Les informations utilisées par la variable price sont créées à l'aide d'un opérateur conditionnel qui confirme que la pièce est disponible avant de vérifier son prix. Vous pouvez également effectuer cette opération à l'aide d'une instruction if avec les mêmes conditions. Une logique similaire est utilisée pour créer le paramètre d'application priceInfo utilisé pour ajouter des prix dans le panier.
//
// 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. Créez une variable nommée meta qui sera utilisée pour amener l'objet $scope.meta dans le module d'écoute d'événement en tant qu'objet local, afin de faciliter l'accès à ses valeurs.
//
// create a variable to bring the $scope.meta object into this event listener as a local object
let meta = $scope.meta
e. Etant donné que des informations supplémentaires seront ajoutées à la fenêtre contextuelle pour déterminer si une pièce est disponible ou non à partir des informations de shoppingThing, le modèle de la fenêtre contextuelle est maintenant défini à l'aide d'une fonction qui sera créée ultérieurement dans l'activité. Pour l'instant, supprimez les conditions et les crochets fermants de l'instruction if que vous avez créée précédemment et diminuez le retrait du code pour appeler la fenêtre contextuelle.
f. Supprimez le code de la fenêtre contextuelle pour ce qui aurait été précédemment le cas else pour l'instruction if. En outre, supprimez la valeur de la propriété template ; elle sera remplacée lors de l'étape suivante. Des indicateurs d'erreur s'affichent en regard de ces lignes de code, mais ils sont résolus lorsque la valeur du modèle est renseignée.
g. La propriété template doit avoir une valeur qui appelle la fonction setTemplate (qui sera créée ultérieurement) avec les entrées de l'objet meta et la variable price de la pièce sélectionnée. Le code permettant d'appeler la fenêtre contextuelle doit désormais correspondre au code fourni ci-dessous.
//
// 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. Pour la fonction disassemble, les propriétés model et instruction dans modelObject pour définir la séquence d'animation du modèle doivent être mises à jour. Il s'agit de l'emplacement où la variable $scope.target créée précédemment sera accessible, et instructionName sera mis à jour avec son nouvel emplacement à l'intérieur de l'objet meta.
//
// 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. Ajoutez un crochet fermant et une parenthèse pour terminer l'invocation du service getPriceAvailability.
}) // getPriceAvailability end
4. Pour simplifier le processus d'utilisation des fenêtres contextuelles ioniques dans votre expérience, vous devez ajouter un autre module d'écoute d'événement userpick. Ce module d'écoute d'événement sera utilisé pour fermer une fenêtre contextuelle qui n'était pas fermée avant de cliquer sur une autre pièce. Lorsqu'il est déclenché, ce module ferme le menu contextuel de la première pièce sur laquelle vous avez cliqué et supprime le nuanceur de celui-ci avant d'ouvrir une nouvelle fenêtre contextuelle et un nuanceur dans la pièce sélectionnée suivante.
//
// 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. La dernière étape de la mise à jour de votre expérience consiste à créer la fonction setTemplate mentionnée précédemment. Cette fonction sera utilisée pour définir la variable template qui sera utilisée dans la fenêtre contextuelle afin de déterminer les informations disponibles pour la pièce. Cela inclut la logique permettant de déterminer si une séquence de désassemblage est associée à une pièce et si elle est disponible dans shoppingThing.
a. Sous la fonction clearCart, créez une fonction nommée setTemplate avec les entrées de meta et price.
//
// function for setting the template for the Ionic popup
$scope.setTemplate = function (meta, price) {

} // setTemplate end
b. Tout d'abord, vous allez ajouter une logique à la fonction pour déterminer si une séquence de désassemblage est associée à la pièce sélectionnée. La variable instr utilise un opérateur conditionnel pour voir si la propriété instructionName de meta est renseignée ou non et elle prendra la place de l'instruction if que vous aviez précédemment. S'il existe une séquence associée, un bouton est créé, qui peut être utilisé pour déclencher la fonction disassemble, désactiver le moteur de rendu et fermer la fenêtre contextuelle. S'il n'existe pas de séquence associée, instr devient une chaîne vide.
//
// 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. En outre, vous devez ajouter une logique pour déterminer si une pièce est disponible ou non. Créez la variable addTo à la suite de la détermination par un opérateur conditionnel de l'association d'une pièce à un prix ou non d'après les informations de shoppingThing. Si tel est le cas, le prix s'affiche dans la fenêtre contextuelle, avec un bouton Add to Cart cliquable qui déclenche la fonction addToCart. Sinon, seul le prix est ajouté à la fenêtre contextuelle.
//
// 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. Une fois que les boutons disponibles pour la fenêtre contextuelle ont été déterminés, la variable template est créée comme celle que vous avez créée pour les fenêtres contextuelles précédentes. La fenêtre contextuelle affiche la quantité, le numéro de pièce, le nom de la pièce et le prix de la pièce sélectionnée, ainsi que les boutons qui s'appliquent à la pièce. Le bouton Continue est à nouveau ajouté pour fermer la fenêtre contextuelle. Une instruction de retour sera ajoutée pour la variable template pour qu'elle sorte de la fonction lors de son exécution. Cela permet de terminer la fonction setTemplate.
//
// 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. Cliquez sur Aperçu.
a. Cliquez sur la base du quadrirotor pour afficher l'option de la fenêtre contextuelle qui inclut une pièce disponible, mais pour laquelle aucune séquence de désassemblage n'est associée. Cliquez sur Continue pour fermer la fenêtre contextuelle.
* 
Si vous ne cliquez pas sur le bouton Continue avant de cliquer sur une autre pièce, les fenêtres contextuelles s'empilent les unes sur les autres et la première ne se ferme pas.
b. Sélectionnez l'un des rotors pour afficher la fenêtre contextuelle qui affiche une pièce disponible, à laquelle une séquence de désassemblage est associée.
c. Sélectionnez le haut du quadrirotor pour afficher la fenêtre contextuelle affichant une pièce non disponible, sans séquence de désassemblage associée.
Sélectionnez l'un des moteurs pour afficher la fenêtre contextuelle qui s'affiche lorsqu'une pièce est associée à une séquence de désassemblage mais n'est pas disponible.
7. Cette section est maintenant terminée. Tous les autres codes de cette section sont les mêmes que dans la section 3D-Guided Service Instructions 301. Vous devez pouvoir cliquer sur une pièce, une fenêtre contextuelle doit s'afficher et vous devez disposer de l'une des quatre options ci-dessus pour une fenêtre contextuelle. Et, le cas échéant, vous pouvez ajouter la pièce au panier. Vous devez également être en mesure de rechercher des pièces à l'aide du widget userInput.
Dans la dernière section de ce cas d'utilisation, vous allez créer le panier persistant à l'aide de ThingWorx.