Valider une variable d'entrée

Ce guide explique comment valider une variable d'entrée.

Lorsque vous définissez une variable d'entrée, nous vous recommandons de vérifier que l'utilisateur saisit une valeur appropriée. Par exemple, si vous demandez à l'utilisateur de saisir un chiffre, vérifiez qu'il saisit 1 au lieu de a pour vous assurer que votre étape s'exécute sans erreur.

Il existe deux façons de valider une variable d'entrée :

  • Validation côté client : Avec la validation côté client, vous vérifiez les saisies de l'utilisateur directement sur son appareil. L'utilisateur reçoit un retour immédiat et peut corriger les erreurs dans sa saisie lors de la configuration de l'étape.
  • Validation côté serveur : la validation côté serveur vous permet d'exécuter une logique sur le serveur lors de la validation. C'est utile lorsque vous devez rechercher des informations que le client ne possède pas, comme des données dans d'autres systèmes ou bases de données.

Validation côté client

Il existe deux façons d'implémenter la validation côté client :

  • Pour une validation de base, comme vérifier qu'un widget contient moins d'un certain nombre de caractères ou le symbole @, appelez la classe Validation du service Card du module complémentaire Google Workspace.
  • Pour une validation robuste, comme la comparaison des valeurs de widget avec d'autres valeurs de widget, vous pouvez ajouter une validation CEL (Common Expression Language) aux widgets de fiche compatibles suivants à l'aide de CardService.

Appeler la classe Validation

L'exemple suivant valide qu'un widget TextInput contient 10 caractères ou moins :

Apps Script

const validation = CardService.newValidation().setCharacterLimit('10').setInputType(
    CardService.InputType.TEXT);

Pour d'autres options de validation, utilisez la validation CEL.

Validation CEL

La validation Common Expression Language (CEL) offre des vérifications instantanées des entrées sans la latence de la validation côté serveur en déchargeant les vérifications des valeurs d'entrée qui ne dépendent pas de la recherche de données provenant d'autres services vers le côté client.

Vous pouvez également utiliser CEL pour créer des comportements de carte, comme afficher ou masquer un widget en fonction du résultat de la validation. Ce type de comportement est utile pour afficher ou masquer un message d'erreur qui aide les utilisateurs à corriger leurs saisies.

Pour créer une validation CEL complète, vous devez utiliser les composants suivants :

  • ExpressionData dans la fiche : contient la logique de validation et la logique de déclenchement de widget spécifiées lorsqu'une des conditions définies est remplie.

    • Id : identifiant unique de ExpressionData dans la carte actuelle.
    • Expression : chaîne CEL qui définit la logique de validation (par exemple, "value1 == value2").
    • Conditions : liste de conditions contenant une sélection de résultats de validation prédéfinis (SUCCESS ou FAILURE). Les conditions sont liées au EventAction côté widget via Triggers avec un actionRuleId partagé.
    • EventAction au niveau de la fiche : active les validations CEL dans la fiche et associe le champ ExpressionData aux widgets de résultats via des déclencheurs post-événement.
      • actionRuleId : ID unique de ce EventAction.
      • ExpressionDataAction : définissez sur START_EXPRESSION_EVALUATION pour indiquer que cette action lance l'évaluation CEL.
      • Trigger : connecte Conditions à EventActions côté widget en fonction de actionRuleId.
  • EventAction au niveau du widget : contrôle le comportement du widget de résultats lorsque la condition de réussite ou d'échec est remplie. Par exemple, un widget de résultat peut être un TextParagraph qui contient un message d'erreur qui n'est visible que lorsque la validation échoue.

    • actionRuleId : correspond à actionRuleId dans Trigger côté carte.
    • CommonWidgetAction : définit les actions qui n'impliquent pas d'évaluations, comme la mise à jour de la visibilité des widgets.
      • UpdateVisibilityAction : action qui met à jour l'état de visibilité d'un widget (VISIBLE ou HIDDEN).

L'exemple suivant montre comment implémenter la validation CEL pour vérifier si deux entrées de texte sont égales. Un message d'erreur s'affiche si elles ne sont pas égales.

  • Lorsque la failCondition est remplie (les entrées ne sont pas égales), le widget de message d'erreur est défini sur VISIBLE et s'affiche.
    Figure 1 : Lorsque la condition failCondition est remplie (les entrées ne sont pas égales), le widget de message d'erreur est défini sur VISIBLE et s'affiche.
  • Lorsque la condition successCondition est remplie (les entrées sont égales), le widget de message d'erreur est défini sur HIDDEN et n'apparaît pas.
    Figure 2 : Lorsque la condition successCondition est remplie (les entrées sont égales), le widget de message d'erreur est défini sur HIDDEN et n'apparaît pas.

Voici l'exemple de code d'application et le fichier manifeste JSON :

Apps Script

function onConfig() {

  // Create a Card
  let card = CardService.newCardBuilder();

  const textInput_1 = CardService.newTextInput()
    .setTitle("Input number 1")
    .setFieldName("value1"); // FieldName's value must match a corresponding ID defined in the inputs[] array in the manifest file.
  const textInput_2 = CardService.newTextInput()
    .setTitle("Input number 2")
    .setFieldName("value2"); // FieldName's value must match a corresponding ID defined in the inputs[] array in the manifest file.
  let sections = CardService.newCardSection()
    .setHeader("Two number equals")
    .addWidget(textInput_1)
    .addWidget(textInput_2);

  // CEL Validation

  // Define Conditions
  const condition_success = CardService.newCondition()
    .setActionRuleId("CEL_TEXTINPUT_SUCCESS_RULE_ID")
    .setExpressionDataCondition(
      CardService.newExpressionDataCondition()
      .setConditionType(
        CardService.ExpressionDataConditionType.EXPRESSION_EVALUATION_SUCCESS));
  const condition_fail = CardService.newCondition()
    .setActionRuleId("CEL_TEXTINPUT_FAILURE_RULE_ID")
    .setExpressionDataCondition(
      CardService.newExpressionDataCondition()
      .setConditionType(
        CardService.ExpressionDataConditionType.EXPRESSION_EVALUATION_FAILURE));

  // Define Card-side EventAction
  const expressionDataAction = CardService.newExpressionDataAction()
    .setActionType(
      CardService.ExpressionDataActionType.START_EXPRESSION_EVALUATION);
  // Define Triggers for each Condition respectively
  const trigger_success = CardService.newTrigger()
    .setActionRuleId("CEL_TEXTINPUT_SUCCESS_RULE_ID");
  const trigger_failure = CardService.newTrigger()
    .setActionRuleId("CEL_TEXTINPUT_FAILURE_RULE_ID");

  const eventAction = CardService.newEventAction()
    .setActionRuleId("CEL_TEXTINPUT_EVALUATION_RULE_ID")
    .setExpressionDataAction(expressionDataAction)
    .addPostEventTrigger(trigger_success)
    .addPostEventTrigger(trigger_failure);

  // Define ExpressionData for the current Card
  const expressionData = CardService.newExpressionData()
    .setId("expData_id")
    .setExpression("value1 == value2") // CEL expression
    .addCondition(condition_success)
    .addCondition(condition_fail)
    .addEventAction(eventAction);
  card = card.addExpressionData(expressionData);

  // Create Widget-side EventActions and a widget to display error message
  const widgetEventActionFail = CardService.newEventAction()
    .setActionRuleId("CEL_TEXTINPUT_FAILURE_RULE_ID")
    .setCommonWidgetAction(
      CardService.newCommonWidgetAction()
      .setUpdateVisibilityAction(
        CardService.newUpdateVisibilityAction()
        .setVisibility(
          CardService.Visibility.VISIBLE)));
  const widgetEventActionSuccess = CardService.newEventAction()
    .setActionRuleId("CEL_TEXTINPUT_SUCCESS_RULE_ID")
    .setCommonWidgetAction(
      CardService.newCommonWidgetAction()
      .setUpdateVisibilityAction(
        CardService.newUpdateVisibilityAction()
        .setVisibility(
          CardService.Visibility.HIDDEN)));
  const errorWidget = CardService.newTextParagraph()
    .setText("The first and second value must match.")
    .setVisibility(CardService.Visibility.HIDDEN) // Initially hidden
    .addEventAction(widgetEventActionFail)
    .addEventAction(widgetEventActionSuccess);
  sections = sections.addWidget(errorWidget);

  card = card.addSection(sections);
  // Build and return the Card
  return card.build();
}

Fichier manifeste JSON

{
  "timeZone": "America/Los_Angeles",
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8",
  "addOns": {
    "common": {
      "name": "CEL validation example",
      "logoUrl": "https://www.gstatic.com/images/branding/productlogos/calculator_search/v1/web-24dp/logo_calculator_search_color_1x_web_24dp.png",
      "useLocaleFromApp": true
    },
    "flows": {
      "workflowElements": [
        {
          "id": "actionElement",
          "state": "ACTIVE",
          "name": "CEL Demo",
          "description": "Demonstrates CEL Validation",
          "workflowAction": {
            "inputs": [
              {
                "id": "value1",
                "description": "The first number",
                "cardinality": "SINGLE",
                "dataType": {
                  "basicType": "INTEGER"
                }
              },
              {
                "id": "value2",
                "description": "The second number",
                "cardinality": "SINGLE",
                "dataType": {
                  "basicType": "INTEGER"
                }
              }
            ],
            "onConfigFunction": "onConfig",
            "onExecuteFunction": "onExecute"
          }
        }
      ]
    }
  }
}

Widgets et opérations de validation CEL compatibles

Widgets de carte compatibles avec la validation CEL

Les widgets suivants sont compatibles avec la validation CEL :

  • TextInput
  • SelectionInput
  • DateTimePicker

Opérations de validation CEL acceptées

  • Opérations arithmétiques
    • + : ajoute deux nombres int64, uint64 ou double.
    • - : soustrait deux nombres int64, uint64 ou double.
    • * : multiplie deux nombres int64, uint64 ou double.
    • / : divise deux nombres int64, uint64 ou double (division entière).
    • % : calcule le modulo de deux nombres int64 ou uint64.
    • - : annule un nombre int64 ou uint64.
  • Opérations logiques :
    • && : effectue une opération logique AND sur deux valeurs booléennes.
    • || : effectue une opération logique OR sur deux valeurs booléennes.
    • ! : effectue une opération logique NOT sur une valeur booléenne.
  • Opérations de comparaison :
    • == : vérifie si deux valeurs sont égales. Compatible avec les nombres et les listes.
    • != : vérifie si deux valeurs ne sont pas égales. Compatible avec les nombres et les listes.
    • < : vérifie si le premier nombre int64, uint64 ou double est inférieur au second.
    • <= : vérifie si le premier nombre (int64, uint64 ou double) est inférieur ou égal au second.
    • > : vérifie si le premier nombre int64, uint64 ou double est supérieur au second.
    • >= : vérifie si le premier nombre (int64, uint64 ou double) est supérieur ou égal au second.
  • Opérations List :
    • in : vérifie si une valeur est présente dans une liste. Compatible avec les nombres, les chaînes et les listes imbriquées.
    • size : renvoie le nombre d'éléments d'une liste. Compatible avec les nombres et les listes imbriquées.

Scénarios de validation CEL non acceptés

  • Taille incorrecte des arguments pour les opérations binaires : les opérations binaires (par exemple, add_int64, "est égal à") nécessitent exactement deux arguments. Si vous fournissez un nombre d'arguments différent, une erreur sera générée.
  • Taille des arguments incorrecte pour les opérations unaires : les opérations unaires (par exemple, negate_int64) nécessitent un seul argument. Si vous fournissez un nombre d'arguments différent, une erreur sera générée.
  • Types non acceptés dans les opérations numériques : les opérations numériques binaires et unaires n'acceptent que les arguments numériques. Si vous fournissez d'autres types (par exemple, booléen), une erreur sera générée.

Validation côté serveur

La validation côté serveur vous permet d'exécuter une logique côté serveur en spécifiant onSaveFunction() dans le code de votre étape. Lorsque l'utilisateur quitte la fiche de configuration de l'étape, onSaveFunction() s'exécute et vous permet de vérifier la saisie de l'utilisateur.

Si l'entrée de l'utilisateur est valide, renvoyez saveWorkflowAction.

Si l'entrée de l'utilisateur n'est pas valide, renvoyez une fiche de configuration qui affiche un message d'erreur expliquant à l'utilisateur comment résoudre le problème.

Étant donné que la validation côté serveur est asynchrone, l'utilisateur peut ne pas être informé de l'erreur de saisie tant qu'il n'a pas publié son flux.

Chaque id d'entrée validé dans le fichier manifeste doit correspondre à un name de widget de carte dans le code.

L'exemple suivant valide qu'une saisie de texte par l'utilisateur inclut le signe "@" :

Fichier manifeste

L'extrait du fichier manifeste spécifie un onSaveFunction() nommé "onSave" :

JSON

{
  "timeZone": "America/Los_Angeles",
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8",
  "addOns": {
    "common": {
      "name": "Server-side validation example",
      "logoUrl": "https://www.gstatic.com/images/branding/productlogos/calculator_search/v1/web-24dp/logo_calculator_search_color_1x_web_24dp.png",
      "useLocaleFromApp": true
    },
    "flows": {
      "workflowElements": [
        {
          "id": "actionElement",
          "state": "ACTIVE",
          "name": "Calculate",
          "description": "Asks the user for an email address",
          "workflowAction": {
            "inputs": [
              {
                "id": "email",
                "description": "email address",
                "cardinality": "SINGLE",
                "required": true,
                "dataType": {
                  "basicType": "STRING"
                }
              }
            ],
            "onConfigFunction": "onConfigCalculate",
            "onExecuteFunction": "onExecuteCalculate",
            "onSaveFunction": "onSave"
          }
        }
      ]
    }
  }
}

Code d'application

Le code de l'étape inclut une fonction appelée onSave(). Il valide qu'une chaîne saisie par l'utilisateur inclut @. Si c'est le cas, il enregistre l'étape du flux. Si ce n'est pas le cas, une fiche de configuration s'affiche avec un message d'erreur expliquant comment résoudre le problème.

Apps Script

/**
 * Validates user input asynchronously when the user
 * navigates away from a step's configuration card.
*/
function onSave(event) {

  // "email" matches the input ID specified in the manifest file.
  var email = event.workflow.actionInvocation.inputs["email"];

  // Validate that the email address contains an "@" sign:
  if(email.includes("@")) {

  // If successfully validated, save and proceed.
    return {
      "hostAppAction" : {
        "workflowAction" : {
          "saveWorkflowAction" : {}
        }
      }
    };

  // If the input is invalid, return a card with an error message
  } else {

var card = {
    "sections": [
      {
        "header": "Collect Email",
        "widgets": [
          {
            "textInput": {
              "name": "email",
              "label": "email address",
              "hostAppDataSource" : {
                "workflowDataSource" : {
                  "includeVariables" : true
                }
              }
            }
          },
          {
            "textParagraph": {
              "text": "<b>Error:</b> Email addresses must include the '@' sign.",
              "maxLines": 1
            }
          }
        ]
      }
    ]
  };
  return pushCard(card);
  }
}